package admin

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"go.opentelemetry.io/otel/trace"
	"go.uber.org/dig"

	baseapi "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/api/base"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/apiserver"
	apiutils "github.com/tidbcloud/aisupport/packages/sdk-go/infra/apiserver/utils"
	"github.com/tidbcloud/aisupport/services/jsm-syncer/internal/app"
	accountresolver "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/accountresolver"
	atlassiansyncsvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/atlassiansync"
	reconciliationsvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/reconciliation"
	technicalrolewhitelistsvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/technicalrolewhitelist"
)

type HandlerParam struct {
	dig.In

	AccountResolver        accountresolver.Service
	AtlassianSync          atlassiansyncsvc.Service
	Reconciliation         reconciliationsvc.Service
	TechnicalRoleWhitelist technicalrolewhitelistsvc.Service
}

type Handler struct {
	accountResolver        accountresolver.Service
	atlassianSync          atlassiansyncsvc.Service
	reconciliation         reconciliationsvc.Service
	technicalRoleWhitelist technicalrolewhitelistsvc.Service
}

func NewHandler(param HandlerParam) app.HandlerResult {
	return app.HandlerResult{
		Handler: &Handler{
			accountResolver:        param.AccountResolver,
			atlassianSync:          param.AtlassianSync,
			reconciliation:         param.Reconciliation,
			technicalRoleWhitelist: param.TechnicalRoleWhitelist,
		},
	}
}

func (h *Handler) Name() string {
	return "AdminHandler"
}

func (h *Handler) Register(routers map[apiserver.RoutePath]gin.IRouter) error {
	router := routers[app.APIRoutePath]

	router.POST("/admin/atlassian-account-resolution", h.ResolveMissingAtlassianAccountIDs)
	router.POST("/admin/reconcile/orgs/:tidbcloud_org_id", h.ReconcileOrg)
	router.POST("/admin/reconcile/users/:tidbcloud_user_id", h.ReconcileUser)
	router.POST("/admin/reconcile/org-full-sync", h.ReconcileOrgFullSync)
	router.POST("/admin/reconcile/org-membership-sync", h.ReconcileOrgMembershipSync)
	router.POST("/admin/reconcile/org-metadata-backfill", h.ReconcileOrgMetadataBackfill)
	router.POST("/admin/reconcile/org-metadata-refresh", h.ReconcileOrgMetadataRefresh)
	router.POST("/admin/reconcile/lake-snapshot", h.ReconcileLakeSnapshot)
	router.POST("/admin/reconcile/technical-project-role", h.ReconcileTechnicalProjectRole)
	router.POST("/admin/technical-role-org-whitelists", h.CreateTechnicalRoleOrgWhitelist)
	router.GET("/admin/technical-role-org-whitelists", h.ListTechnicalRoleOrgWhitelists)
	router.GET("/admin/technical-role-org-whitelists/:tidbcloud_org_id", h.GetTechnicalRoleOrgWhitelist)
	router.PATCH("/admin/technical-role-org-whitelists/:tidbcloud_org_id", h.UpdateTechnicalRoleOrgWhitelist)
	router.DELETE("/admin/technical-role-org-whitelists/:tidbcloud_org_id", h.DeleteTechnicalRoleOrgWhitelist)
	return nil
}

func fail(c *gin.Context, err error) {
	apiutils.Fail(c, err)
}

func success(c *gin.Context, resp any) {
	apiutils.Success(c, resp)
}

func accepted(c *gin.Context, resp any) {
	baseapi.SetBaseResp(resp, http.StatusAccepted, "", trace.SpanContextFromContext(c).TraceID().String())
	c.JSON(http.StatusAccepted, resp)
}
