package org

import (
	"github.com/gin-gonic/gin"
	"go.uber.org/fx"

	"github.com/pingcap-inc/clinic/pkg/api/cluster"
)

func registerRouter(r *gin.RouterGroup, s *OrganizationService, cs *cluster.ClusterService) {
	org := r.Group("/orgs")
	// orgs
	org.POST("", s.Create)
	org.GET("", s.List)
	org.GET("/:oid", s.Get)
	org.GET("/external/:eid", s.GetByExternalID)
	org.PUT("/:oid", s.Update)
	org.GET("/:oid/tasks", s.GetTaskStatus)
	org.DELETE("/:oid", s.Delete)
	org.GET("/:oid/roles", s.ListRoles)
	org.POST("/:oid/star", s.Star)
	org.DELETE("/:oid/star", s.UnStar)
	org.GET("/:oid/projects", s.ListProjects)

	// users
	org.DELETE("/:oid/users/:id", s.DeleteUser)
	org.GET("/:oid/users", s.ListUsers)
	org.POST("/:oid/users/invite", s.Invite)
	org.PUT("/:oid/users/:id", s.UpdateUser)

	// api tokens
	org.POST("/:oid/keys", s.AddCredential)
	org.DELETE("/:oid/keys/:id", s.DeleteCredential)
	org.GET("/:oid/keys", s.ListCredentials)

	// clusters
	org.GET("/:oid/clusters", cs.ListCluster)
	org.POST("/:oid/clusters", cs.AddCluster)
	org.GET("/:oid/clusters/:cid", cs.GetCluster)
	org.GET("/:oid/clusters/:cid/metrics", cs.Metrics)
	org.PUT("/:oid/clusters/:cid/rebuild", cs.Rebuild)
	org.PUT("/:oid/clusters/:cid", cs.UpdateCluster)
	org.POST("/:oid/clusters/:cid/update_status", cs.UpdateClusterStatus)
	org.DELETE("/:oid/clusters/:cid", cs.Delete)
	org.GET("/:oid/clusters/:cid/data_status", cs.GetClusterDataStatus)
	org.GET("/:oid/clusters/:cid/data", cs.GetDataSummary)
	org.GET("/:oid/clusters/:cid/slowqueries", cs.ListSlowQueries)
	org.GET("/:oid/clusters/:cid/slowqueries/:queryid", cs.SlowQueryDetail)
	org.GET("/:oid/clusters/:cid/download/:itemid", cs.Download)
	org.GET("/:oid/clusters/:cid/downloadConf/:itemid", cs.DownloadConf)
	org.GET("/:oid/clusters/:cid/logurl/:itemid", cs.LogUrl)
	org.GET("/:oid/clusters/:cid/dashboard-versions", cs.ListDashboardVersions)
	org.GET("/:oid/clusters/:cid/dashboard", cs.ListDashboards)
	org.GET("/:oid/clusters/:cid/:itemid/meta", cs.FileMeta)
	org.GET("/:oid/clusters/:cid/resource-pool/components", cs.GetResourcePoolComponents)
	org.GET("/:oid/clusters/:cid/plan-replayer/files", cs.ListPlanReplayerFiles)
	org.POST("/:oid/clusters/:cid/plan-replayer/files/download-url", cs.GeneratePlanReplayerFileDownloadURL)

	org.GET("/:oid/clusters/:cid/slogans", cs.ListSlogans)
	org.POST("/:oid/clusters/:cid/slogans", cs.AddSlogan)
	org.DELETE("/:oid/clusters/:cid/slogans/:id", cs.DeleteSlogans)

	org.GET("/:oid/clusters/:cid/defaultconf", cs.DefaultConfValue)

	org.POST("/:oid/diag/precreate", s.Precreate)
	org.POST("/:oid/diag/upload", s.Upload)
	org.POST("/:oid/diag/flush", s.Flush)

	// Simple cluster basic info lookup (lightweight, direct DB query)
	r.GET("/clusters/:cid", cs.GetClusterByID)
}

// internalAPIRouter is for internal server
// which is only a subset api from public api
func internalAPIRouter(rg *gin.RouterGroup, orgSvc *OrganizationService, clusterSvc *cluster.ClusterService) {
	org := rg.Group("/orgs")
	org.GET("/external/:eid", orgSvc.GetByExternalID)
	org.GET("/:oid/clusters/:cid", clusterSvc.GetCluster)

	dataProxy := rg.Group("/internal/data-proxy/v1")
	dataProxy.GET("/orgs/:orgId/clusters/:clusterId/components", clusterSvc.GetDataProxyResourcePoolComponents)
}

var Module = fx.Options(
	fx.Provide(NewOrganizationService),
	fx.Provide(cluster.NewClusterService),
	fx.Invoke(registerRouter))

// InternalAPIModule is for internal server
// which is only a subset api from public api
var InternalAPIModule = fx.Options(
	fx.Provide(NewOrganizationService),
	fx.Provide(cluster.NewClusterService),
	fx.Invoke(internalAPIRouter),
)
