package metrics

import (
	"github.com/pingcap/log"
	"github.com/prometheus/client_golang/prometheus"
	"go.uber.org/zap"

	"github.com/pingcap-inc/clinic/pkg/db/model"
)

func init() {
	prometheus.MustRegister(ImportMetricFileCount)
	prometheus.MustRegister(ImportMetricFileProcessSuccessfulCount)
	prometheus.MustRegister(ImportMetricFileProcessFailedCount)
	prometheus.MustRegister(SinkTimeSeriesCount)
	prometheus.MustRegister(SinkTimeSeriesDatapointCount)
	prometheus.MustRegister(SinkLogCount)
	prometheus.MustRegister(ImportLogFileCount)
	prometheus.MustRegister(ImportLogFileProcessSuccessfulCount)
	prometheus.MustRegister(ImportLogFileProcessFailedCount)
	prometheus.MustRegister(ListRecentJiraIssueBindRequestCount)
	prometheus.MustRegister(&ClinicCollector{})
	// prometheus.MustRegister(RebuildMetricCostTime)
	// prometheus.MustRegister(RebuildMetricCount)
	prometheus.MustRegister(RebuildLogsCostTime)
	prometheus.MustRegister(RebuildLogCount)
	prometheus.MustRegister(WaitingRebuildTaskCount)
	prometheus.MustRegister(WaitDecryptionTaskCount)
	prometheus.MustRegister(FastRebuildCostTime)
	prometheus.MustRegister(SlowRebuildCostTime)
	prometheus.MustRegister(PackageRebuildCostTime)
	prometheus.MustRegister(RebuildTaskFailed)

	prometheus.MustRegister(RequestCoreServerCount)
	prometheus.MustRegister(RequestCoreServerFailedCount)
	prometheus.MustRegister(RequestMetaDBCount)
	prometheus.MustRegister(RequestMetaDBFailedCount)
}

var (
	ImportMetricFileCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "importer",
		Subsystem: "metrics",
		Name:      "metric_file_count",
		Help:      "the file count of metrics consumer receive",
	}, []string{"cluster_id", "file_uuid"})

	ImportMetricFileProcessSuccessfulCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "importer",
		Subsystem: "metrics",
		Name:      "metric_process_successful_file_count",
		Help:      "the file count of metrics consumer processed successful",
	}, []string{"cluster_id", "file_uuid"})

	ImportMetricFileProcessFailedCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "importer",
		Subsystem: "metrics",
		Name:      "metric_process_failed_file_count",
		Help:      "the file count of metrics consumer processed failed",
	}, []string{"cluster_id", "file_uuid"})

	SinkTimeSeriesCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "importer",
		Subsystem: "metrics",
		Name:      "sink_timeseries_count",
		Help:      "the count of metrics sink successful",
	}, []string{"cluster_id", "file_uuid"})

	SinkTimeSeriesDatapointCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "importer",
		Subsystem: "metrics",
		Name:      "sink_timeseries_datapoint_count",
		Help:      "the count of metrics datapoint sink successful",
	}, []string{"cluster_id", "file_uuid"})

	SinkLogCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "importer",
		Subsystem: "logs",
		Name:      "sink_log_count",
		Help:      "the count of metrics sink successful",
	}, []string{"file_uuid"})

	ImportLogFileCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "importer",
		Subsystem: "logs",
		Name:      "log_file_count",
		Help:      "the count of sink log file",
	}, []string{"cluster_id", "file_uuid"})

	ImportLogFileProcessSuccessfulCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "importer",
		Subsystem: "logs",
		Name:      "logs_process_successful_file_count",
		Help:      "the file count of log consumer processed successful",
	}, []string{"cluster_id", "file_uuid"})

	ImportLogFileProcessFailedCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "importer",
		Subsystem: "logs",
		Name:      "log_process_failed_file_count",
		Help:      "the file count of log consumer processed failed",
	}, []string{"cluster_id", "file_uuid"})

	ListRecentJiraIssueBindRequestCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "list_recent_jira_issue_bind_request_count",
		Help: "the count of api request from association-proxy",
	}, []string{})

	UploadPackageCount = prometheus.NewDesc(
		prometheus.BuildFQName("clinic", "upload", "file_count"),
		"upload file count",
		[]string{},
		nil)

	ClusterCount = prometheus.NewDesc(
		prometheus.BuildFQName("clinic", "upload", "cluster_count"),
		"cluster count",
		[]string{},
		nil)

	UserCount = prometheus.NewDesc(
		prometheus.BuildFQName("clinic", "user", "user_count"),
		"user count",
		[]string{},
		nil)

	OrgCount = prometheus.NewDesc(
		prometheus.BuildFQName("clinic", "org", "org_count"),
		"org count",
		[]string{},
		nil)

	//RebuildMetricCostTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{
	//	Namespace: "rebuild",
	//	Subsystem: "metrics",
	//	Name:      "cost_time",
	//	Help:      "the cost time of rebuild metric time",
	//}, []string{"cluster_id", "file_uuid"})

	WaitingRebuildTaskCount = prometheus.NewGauge(prometheus.GaugeOpts{
		Namespace: "rebuild",
		Subsystem: "waiting",
		Name:      "count",
		Help:      "the count of waiting rebuild",
	})

	//RebuildMetricCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
	//	Namespace: "rebuild",
	//	Subsystem: "metrics",
	//	Name:      "count",
	//	Help:      "the count of rebuild metric",
	//}, []string{"cluster_id", "file_uuid"})

	RebuildLogsCostTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "rebuild",
		Subsystem: "logs",
		Name:      "cost_time",
		Help:      "the cost time of rebuild log time",
	}, []string{"cluster_id", "file_uuid"})

	RebuildLogCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "rebuild",
		Subsystem: "logs",
		Name:      "count",
		Help:      "the count of rebuild logs",
	}, []string{"cluster_id", "file_uuid"})

	WaitDecryptionTaskCount = prometheus.NewGauge(prometheus.GaugeOpts{
		Namespace: "decryption",
		Subsystem: "decryption",
		Name:      "count",
		Help:      "the count of waiting dencrypt",
	})

	FastRebuildCostTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "rebuild",
		Subsystem: "fast_task",
		Name:      "cost_time",
		Help:      "the cost time of fast rebuild task",
	}, []string{"file_uuid"})

	SlowRebuildCostTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "rebuild",
		Subsystem: "slow_task",
		Name:      "cost_time",
		Help:      "the cost time of slow rebuild task",
	}, []string{"file_uuid"})

	PackageRebuildCostTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "rebuild",
		Subsystem: "package",
		Name:      "cost_time",
		Help:      "the cost time of rebuild package",
	}, []string{"file_uuid"})

	PackageDecompressCostTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "decompress",
		Subsystem: "package",
		Name:      "cost_time",
		Help:      "the cost time of decompress package",
	}, []string{"file_uuid"})

	RebuildTaskFailed = prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Namespace: "rebuild",
		Subsystem: "package",
		Name:      "failed",
		Help:      "the count of rebuild failed",
	}, []string{"file_uuid"})

	RequestCoreServerCount = prometheus.NewGauge(prometheus.GaugeOpts{
		Namespace: "coreserver",
		Subsystem: "request",
		Name:      "count",
		Help:      "the count of request core server",
	})

	RequestCoreServerFailedCount = prometheus.NewGauge(prometheus.GaugeOpts{
		Namespace: "coreserver",
		Subsystem: "request",
		Name:      "failed",
		Help:      "the failed count of request core server",
	})

	RequestMetaDBCount = prometheus.NewGauge(prometheus.GaugeOpts{
		Namespace: "metadb",
		Subsystem: "request",
		Name:      "count",
		Help:      "the count of request metadb",
	})

	RequestMetaDBFailedCount = prometheus.NewGauge(prometheus.GaugeOpts{
		Namespace: "metadb",
		Subsystem: "request",
		Name:      "failed",
		Help:      "the failed count of request metadb",
	})
)

type ClinicCollector struct{}

func (c *ClinicCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- UploadPackageCount
	ch <- ClusterCount
	ch <- UserCount
	ch <- OrgCount
}

func (c *ClinicCollector) Collect(ch chan<- prometheus.Metric) {
	uploadFileCount, err := model.UploadFileCount()
	if err != nil {
		log.Error("query upload files failed", zap.Error(err))
		return
	}
	ch <- prometheus.MustNewConstMetric(UploadPackageCount, prometheus.GaugeValue, float64(uploadFileCount))

	clusterCount, err := model.ClusterCount()
	if err != nil {
		log.Error("query clusters failed", zap.Error(err))
		return
	}
	ch <- prometheus.MustNewConstMetric(ClusterCount, prometheus.GaugeValue, float64(clusterCount))

	orgCount, err := model.OrganizationsCount()
	if err != nil {
		log.Error("query org failed", zap.Error(err))
		return
	}
	ch <- prometheus.MustNewConstMetric(OrgCount, prometheus.GaugeValue, float64(orgCount))

	userCount, err := model.UserCount()
	if err != nil {
		log.Error("query user failed", zap.Error(err))
		return
	}

	ch <- prometheus.MustNewConstMetric(UserCount, prometheus.GaugeValue, float64(userCount))

	//m := make(map[string]int)
	//for _, uf := range uploadfiles {
	//	v := m[uf.ClusterID]
	//	v++
	//	m[uf.ClusterID] = v
	//}
	//
	//for k, v := range m {
	//	ch <- prometheus.MustNewConstMetric(ClusterCount, prometheus.GaugeValue, float64(v), fmt.Sprintf("%s", k))
	//}
}
