package middleware

import (
	"fmt"
	"go-api/pkg/context"
	apierr "go-api/pkg/errors"
	"go-api/pkg/response"
	"runtime"
	"strings"
)

func ServerPanicCatch() context.CustomHandler {
	return func(c *context.C) {
		defer func() {
			if err := recover(); err != nil {
				// show error Stack
				// *****
				builder := &strings.Builder{}
				fmt.Printf("[Server Error Catch]\n")

				pc := make([]uintptr, 10)
				n := runtime.Callers(1, pc)
				frames := runtime.CallersFrames(pc[:n])
				for {
					frame, more := frames.Next()
					builder.WriteString(fmt.Sprintf("%s:%d %s\n", frame.File, frame.Line, frame.Function))
					if !more {
						break
					}
				}
				// *****

				var e *apierr.APIError
				if convertedErr, ok := err.(*apierr.APIError); ok {
					e = convertedErr
				} else {
					e = apierr.ErrInternalError
				}

				code := make([]response.MessageCode, 0)
				if c := e.Code(); c != nil {
					code = append(code, *c)
				}
				resp := response.Get(e.Status(), code...)

				c.AbortWithStatusJSON(resp.Status, resp.Body)
			}
		}()

		c.Next()

	}
}
