package request

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
)

type Checker interface {
	Check() error
}

func ParseParamFail(ctx *gin.Context, r interface{}, fs ...func() error) bool {
	if r != nil {
		err := ctx.ShouldBind(r)
		if err != nil {
			err = HTTPError{Status: http.StatusBadRequest, Msg: err.Error()}

			return Fail(ctx, err)
		}

		if checker, ok := r.(Checker); ok {
			err := checker.Check()
			if err != nil {
				err = HTTPError{Status: http.StatusBadRequest, Msg: err.Error()}

				return Fail(ctx, err)
			}
		}
	}

	for _, f := range fs {
		err := f()
		if err != nil {
			err = HTTPError{Status: http.StatusBadRequest, Msg: err.Error()}

			return Fail(ctx, err)
		}
	}

	return false
}

func Fail(ctx *gin.Context, err error) bool {
	if err == nil {
		return false
	}

	status := http.StatusInternalServerError
	if v, ok := err.(HTTPError); ok {
		status = v.Status
	}

	ctx.JSON(status, gin.H{"msg": err.Error()})

	return true
}

func Success(ctx *gin.Context, data interface{}) {
	if data == nil {
		ctx.Status(http.StatusNoContent)
		return
	}

	switch ctx.Request.Method {
	case http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodDelete:
		ctx.JSON(http.StatusOK, data)
	case http.MethodPost, http.MethodPut, http.MethodPatch:
		ctx.JSON(http.StatusCreated, data)
	default:
		ctx.JSON(http.StatusBadRequest, HTTPError{Msg: fmt.Sprintf("unsupported request method %s", ctx.Request.Method)})
	}
}
