package performance_insight

import (
	"github.com/gin-gonic/gin"
	"github.com/pingcap/errors"

	"github.com/pingcap-inc/clinic/pkg/datasource"
	"github.com/pingcap-inc/clinic/pkg/db"
	"github.com/pingcap-inc/clinic/pkg/ngm/config"
	"github.com/pingcap-inc/clinic/pkg/ngm/performance_insight/api"
	"github.com/pingcap-inc/clinic/pkg/ngm/performance_insight/compute_engine"
	"github.com/pingcap-inc/clinic/pkg/ngm/performance_insight/service"
)

func InitPerformanceInsightApi(r *gin.RouterGroup, s *Service) {
	performanceInsight := r.Group("/performance_insight")
	{
		task := performanceInsight.Group("/tasks")
		{
			task.POST("", s.taskApi.HandleCreate)
			task.GET("", s.taskApi.HandleQuery)
			task.GET("/:task_id", s.taskApi.HandleGet)
			task.GET("/latest", s.taskApi.HandleGetLatest)
			task.DELETE("/:task_id", s.taskApi.HandleCancel)
		}
		connection := performanceInsight.Group("/tidb_connection")
		{
			connection.GET("", s.taskApi.ClusterActivated)
			connection.POST("", s.taskApi.Activate)
			connection.DELETE("", s.taskApi.Deactivate)
			connection.GET("/clinic_outbound_public_addresses", s.taskApi.HandleGetClinicPublicAddresses)
		}
		unstablePlan := performanceInsight.Group("/unstable_plan")
		{
			unstablePlan.GET("/statements", s.planApi.HandleQueryStatements)
			unstablePlan.GET("/statements/:statement_id", s.planApi.HandleGetStatement)
		}
		ia := performanceInsight.Group("/index_advisor")
		{
			ia.GET("/results", s.iaApi.HandleGetResultList)
			ia.GET("/results/:id", s.iaApi.HandleGetResultDetail)
		}
	}
}

type Service struct {
	taskApi *api.TaskAPI
	planApi *api.UnstablePlanResultAPI
	iaApi   *api.IndexAdvisorAPI
}

func NewPerformanceInsightService(cfg *config.NgmApiServerConfig) (*Service, error) {
	// Init database.
	if err := db.Initialize(cfg.DBConfig, true); err != nil {
		return nil, errors.Annotate(err, "init db failed")
	}

	// Init dependencies.
	if err := datasource.Initialize(*cfg.DBaasConfig, nil); err != nil {
		return nil, errors.Annotate(err, "init dbaas core api failed")
	}

	// Init services.
	secretSvc, err := service.NewSecretService(cfg.AwsSecretsManagerRegion)
	if err != nil {
		return nil, errors.Annotate(err, "init performance insight secret service failed")
	}
	ceClient := compute_engine.NewComputerEngineClient(cfg.ComputeEngineAddress, cfg.Env)
	taskSvc := service.NewTaskService(cfg, secretSvc, ceClient)
	taskApi := api.NewTaskAPI(taskSvc)
	unstablePlanSvc := service.NewUnstablePlanService()
	unstablePlanApi := api.NewUnstablePlanResultAPI(unstablePlanSvc)
	iaSvc := service.NewIndexAdvisorService()
	iaApi := api.NewIndexAdvisorAPI(iaSvc)

	return &Service{
		taskApi: taskApi,
		planApi: unstablePlanApi,
		iaApi:   iaApi,
	}, nil
}
