// Code generated by candi v1.8.18.

package resthandler

import (
	"net/http"

	"github.com/labstack/echo"

	"monorepo/services/master-service/internal/modules/acl/domain"
	"monorepo/services/master-service/internal/modules/acl/usecase"

	"pkg.agungdp.dev/candi/candihelper"
	"pkg.agungdp.dev/candi/candishared"
	"pkg.agungdp.dev/candi/codebase/interfaces"
	"pkg.agungdp.dev/candi/tracer"
	"pkg.agungdp.dev/candi/wrapper"
)

// RestHandler handler
type RestHandler struct {
	mw        interfaces.Middleware
	uc        usecase.ACLUsecase
	validator interfaces.Validator
}

// NewRestHandler create new rest handler
func NewRestHandler(mw interfaces.Middleware, uc usecase.ACLUsecase, validator interfaces.Validator) *RestHandler {
	return &RestHandler{
		mw: mw, uc: uc, validator: validator,
	}
}

// Mount handler with root "/"
// handling version in here
func (h *RestHandler) Mount(root *echo.Group) {
	v1Root := root.Group(candihelper.V1)

	acl := v1Root.Group("/acl", echo.WrapMiddleware(h.mw.HTTPBearerAuth))
	acl.POST("/role", h.addRole, echo.WrapMiddleware(h.mw.HTTPPermissionACL("acl.addRole")))
	acl.POST("/grantuser", h.grantUser, echo.WrapMiddleware(h.mw.HTTPPermissionACL("acl.grantUser")))
	acl.POST("/checkpermission", h.checkPermission)
	acl.GET("/role", h.getAllRole, echo.WrapMiddleware(h.mw.HTTPPermissionACL("acl.getAllRole")))
	acl.GET("/role/:id", h.getDetailRole, echo.WrapMiddleware(h.mw.HTTPPermissionACL("acl.getDetailRole")))
	acl.DELETE("/role/revoke", h.revokeUserRole)
}

func (h *RestHandler) getAllRole(c echo.Context) error {
	trace := tracer.StartTrace(c.Request().Context(), "ACLDeliveryREST:getAllRole")
	defer trace.Finish()

	var filter domain.RoleListFilter
	if err := candihelper.ParseFromQueryParam(c.Request().URL.Query(), &filter); err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}
	trace.SetTag("filter", filter)

	data, meta, err := h.uc.GetAllRole(trace.Context(), filter)
	if err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	return wrapper.NewHTTPResponse(http.StatusOK, "success", data, meta).JSON(c.Response())
}

func (h *RestHandler) addRole(c echo.Context) error {
	trace := tracer.StartTrace(c.Request().Context(), "AclDeliveryREST:Hello")
	defer trace.Finish()

	var payload domain.AddRoleRequest
	if err := c.Bind(&payload); err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	data, err := h.uc.SaveRole(trace.Context(), payload)
	if err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	return wrapper.NewHTTPResponse(http.StatusOK, "ok", data).JSON(c.Response())
}

func (h *RestHandler) grantUser(c echo.Context) error {
	trace := tracer.StartTrace(c.Request().Context(), "AclDeliveryREST:Hello")
	defer trace.Finish()

	var payload domain.GrantUserRequest
	if err := c.Bind(&payload); err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	if err := h.uc.GrantUser(trace.Context(), payload); err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	return wrapper.NewHTTPResponse(http.StatusOK, "ok").JSON(c.Response())
}

func (h *RestHandler) checkPermission(c echo.Context) error {
	trace := tracer.StartTrace(c.Request().Context(), "AclDeliveryREST:checkPermission")
	defer trace.Finish()
	ctx := trace.Context()

	var payload domain.CheckPermissionRequest
	if err := c.Bind(&payload); err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	tokenClaim := candishared.ParseTokenClaimFromContext(ctx)
	payload.UserID = tokenClaim.Additional.(map[string]interface{})["user_id"].(string)

	role, err := h.uc.CheckPermission(ctx, payload.UserID, payload.PermissionCode)
	if err != nil {
		return wrapper.NewHTTPResponse(http.StatusBadRequest, err.Error()).JSON(c.Response())
	}

	return wrapper.NewHTTPResponse(http.StatusOK, "ok", map[string]string{"roleId": role}).JSON(c.Response())
}

func (h *RestHandler) getDetailRole(c echo.Context) error {
	trace := tracer.StartTrace(c.Request().Context(), "AclDeliveryREST:getDetailRole")
	defer trace.Finish()

	var payload domain.GrantUserRequest
	if err := c.Bind(&payload); err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	data, err := h.uc.GetDetailRole(trace.Context(), c.Param("id"))
	if err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	return wrapper.NewHTTPResponse(http.StatusOK, "ok", data).JSON(c.Response())
}

func (h *RestHandler) revokeUserRole(c echo.Context) error {
	trace := tracer.StartTrace(c.Request().Context(), "AclDeliveryREST:revokeUserRole")
	defer trace.Finish()

	var payload domain.GrantUserRequest
	if err := c.Bind(&payload); err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	err := h.uc.RevokeUserRole(trace.Context(), payload.UserID, payload.RoleID)
	if err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

	return wrapper.NewHTTPResponse(http.StatusOK, "Success").JSON(c.Response())
}
