package datasource

import (
	"path"

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

	"github.com/pingcap-inc/clinic/pkg/api/cloud"
	"github.com/pingcap-inc/clinic/pkg/config"
	"github.com/pingcap-inc/clinic/pkg/datasource"
	"github.com/pingcap-inc/clinic/pkg/importer/metrics"
	"github.com/pingcap-inc/clinic/pkg/proxy"
)

func RegisterComputeEngineDataRouter(r *gin.RouterGroup, api *ComputeEngineDataAPI, activeQPSSink *ActiveQPSSink) {
	api.logProxy.WithPathPrefixTrim(r.BasePath())
	dataRouter := r.Group("/data")
	dataRouter.Use(cloud.CloudPermission)
	// metrics query_range api
	// path: /clinic/api/v1/data/metrics
	dataRouter.GET("/metrics", api.ForwardMetricsQueryRangeRequest)
	dataRouter.GET("/control_plane/metrics", api.ForwardControlPlaneMetricsQueryRangeRequest)

	// log api
	// path: /clinic/api/v1/data/log/<suffix>
	dataRouter.POST("/log/:index/_search", api.ForwardLogRequest)
	dataRouter.GET("/log/:index/_search", api.ForwardLogRequest)
	dataRouter.POST("/log/_search/scroll", api.ForwardLogRequest)
	dataRouter.GET("/log/_search/scroll", api.ForwardLogRequest)

	// metrics select/query api
	// path: /clinic/api/v1/data/prometheus/<suffix>
	api.metricsProxy.WithPathPrefixTrim(path.Join(r.BasePath(), "/data/prometheus"))
	dataRouter.Any("/prometheus/*any", api.ForwardMetricsRequest)

	// active qps related api
	dataRouter.POST("/active_qps/batch_insert", activeQPSSink.BatchInsertActiveOPSGinHandler)
}

var extractCfg = func(cfg *config.Config) (*config.MetricConfig, *config.DatasourceLogConfig, *config.MetricConfig) {
	return &cfg.DatasourceConfig.MetricConfig, &cfg.DatasourceConfig.LogConfig, &cfg.SinkConfig.MetricConfig
}

var buildMetricSink = func(metricConfig *config.MetricConfig) *metrics.MetricSink {
	return &metrics.MetricSink{
		Host:         metricConfig.Host,
		Port:         metricConfig.Port,
		ClusterModel: metricConfig.InVMCluster(),
		OrgID:        8899,
	}
}

var buildActiveQPSOptions = func() []ActiveOPSSinkOption {
	return []ActiveOPSSinkOption{
		WithGetClusterInfoFn(datasource.GetCloudCluster),
		WithGetOrgInfoFn(datasource.GetOrganization),
	}
}

var Module = fx.Options(
	fx.Provide(fx.Annotate(extractCfg, fx.ResultTags(`name:"datasourcemetricconfig"`, `name:"datasourcelogconfig"`, `name:"activeqpsmetricconfig"`))),
	fx.Provide(fx.Annotate(func(handler *proxy.TiDBClusterMetricHandler) *proxy.TiDBClusterMetricHandler {
		return handler
	}, fx.ResultTags(`name:"metrichandler"`))),
	fx.Provide(fx.Annotate(func(o11yProxyHandler *proxy.O11yProxyHandler) *proxy.O11yProxyHandler {
		return o11yProxyHandler
	}, fx.ResultTags(`name:"o11yproxyhandler"`))),
	fx.Provide(fx.Annotate(buildMetricSink, fx.ParamTags(`name:"activeqpsmetricconfig"`), fx.ResultTags(`name:"activeqpsmetricsink"`))),
	fx.Provide(fx.Annotate(buildActiveQPSOptions, fx.ResultTags(`name:"activeqpsoptions"`))),
	fx.Provide(fx.Annotate(NewComputeEngineDataAPI, fx.ParamTags(`name:"datasourcemetricconfig"`, `name:"datasourcelogconfig"`, `name:"metrichandler"`, `name:"o11yproxyhandler"`))),
	fx.Provide(fx.Annotate(NewActiveQPSSink, fx.ParamTags(`name:"activeqpsmetricsink"`, `name:"activeqpsoptions"`))),
	fx.Invoke(RegisterComputeEngineDataRouter),
)
