// Code generated by candi v1.8.18.

package resthandler

import (
	"net/http"

	"github.com/labstack/echo"

	"monorepo/services/master-service/internal/modules/apps/domain"
	"monorepo/services/master-service/internal/modules/apps/usecase"
	shareddomain "monorepo/services/master-service/pkg/shared/domain"

	"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.AppsUsecase
	validator interfaces.Validator
}

// NewRestHandler create new rest handler
func NewRestHandler(mw interfaces.Middleware, uc usecase.AppsUsecase, 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)

	apps := v1Root.Group("/apps", echo.WrapMiddleware(h.mw.HTTPBearerAuth))
	apps.GET("", h.getAllApps, echo.WrapMiddleware(h.mw.HTTPPermissionACL("getAllApps")))
	apps.GET("/:code", h.getDetailAppByCode, echo.WrapMiddleware(h.mw.HTTPPermissionACL("getDetailApps")))
	apps.POST("", h.saveApps, echo.WrapMiddleware(h.mw.HTTPPermissionACL("addApps")))
	apps.POST("/permission/:id", h.saveAppPermission, echo.WrapMiddleware(h.mw.HTTPPermissionACL("saveAppPermission")))
	apps.GET("/permission", h.getAllPermissions, echo.WrapMiddleware(h.mw.HTTPPermissionACL("getAllPermissions")))
	apps.GET("/permission/me", h.getAllMePermissions)
	apps.GET("/me", h.getAllMeApps)
}

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

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

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

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

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

	data, err := h.uc.GetDetailApp(trace.Context(), c.Param("code"))
	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) saveApps(c echo.Context) error {
	trace := tracer.StartTrace(c.Request().Context(), "AppsDeliveryREST:saveApps")
	defer trace.Finish()

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

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

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

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

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

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

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

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

	var filter domain.FilterPermission
	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.GetAllPermissions(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) getAllMePermissions(c echo.Context) error {
	trace := tracer.StartTrace(c.Request().Context(), "AppsDeliveryREST:getAllMePermissions")
	defer trace.Finish()
	ctx := trace.Context()

	var filter domain.FilterPermission
	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)

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

	data, err := h.uc.GetAllUserPermissions(ctx, c.QueryParam("apps_code"), userID)
	if err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

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

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

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

	data, err := h.uc.GetUserApps(ctx, userID)
	if err != nil {
		return wrapper.NewHTTPResponse(http.StatusOK, err.Error()).JSON(c.Response())
	}

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