package metrics

import (
	"testing"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/stretchr/testify/require"

	inframetrics "github.com/tidbcloud/aisupport/packages/sdk-go/infra/metrics"
)

func TestInitMetrics(t *testing.T) {
	resetMetrics()
	registry := prometheus.NewRegistry()
	originalRegisterer := prometheus.DefaultRegisterer
	originalGatherer := prometheus.DefaultGatherer
	prometheus.DefaultRegisterer = registry
	prometheus.DefaultGatherer = registry
	t.Cleanup(func() {
		prometheus.DefaultRegisterer = originalRegisterer
		prometheus.DefaultGatherer = originalGatherer
		inframetrics.Gin = nil
		inframetrics.ServiceEventJob = nil
		inframetrics.ServiceCronJob = nil
		resetMetrics()
	})

	InitMetrics()

	require.NotNil(t, inframetrics.Gin)
	require.NotNil(t, inframetrics.ServiceEventJob)
	require.NotNil(t, inframetrics.ServiceCronJob)

	inframetrics.Gin.ReqDur.WithLabelValues("200", "GET", "/api/v1/ticketmanager/engineers").Observe(0.1)
	inframetrics.Gin.RespSize.Observe(128)
	inframetrics.ServiceEventJob.SyncCount.WithLabelValues("DispatchService", "RunDispatchExecution", "success").Inc()
	inframetrics.ServiceEventJob.SyncDur.WithLabelValues("DispatchService", "RunDispatchExecution", "success").Observe(0.1)
	inframetrics.ServiceCronJob.SyncCount.WithLabelValues("EngineerService", "EngineerUserSync", "failed").Inc()
	inframetrics.ServiceCronJob.SyncDur.WithLabelValues("EngineerService", "EngineerUserSync", "failed").Observe(0.1)
	DispatchExecutions.WithLabelValues("live", "failed", "ACTION_EXECUTION_FAILED").Inc()
	DispatchLastFailedExecutionInfo.WithLabelValues("live", "101", "TCOC-101", "ACTION_EXECUTION_FAILED").Set(1)
	DispatchAssignmentNotificationEvents.WithLabelValues(DispatchAssignmentNotificationEventCardFailed).Inc()
	DispatchAssignmentActions.WithLabelValues("card", "failed", "assignee", "").Inc()
	DispatchAssignmentACKs.WithLabelValues("timeout", "assignee", "1").Inc()
	DispatchAssignmentACKWaitSeconds.WithLabelValues("timeout", "assignee", "1").Observe(300)
	DispatchAssignmentWorkflowDurationSeconds.WithLabelValues("unacknowledged", "assignee").Observe(900)
	DispatchCreatedExecutions.WithLabelValues("live").Set(1)
	DispatchOldestCreatedExecutionAgeSeconds.WithLabelValues("live").Set(30)
	DispatchExecutingExecutions.WithLabelValues("live").Set(2)
	DispatchOldestExecutingExecutionAgeSeconds.WithLabelValues("live").Set(900)
	DispatchTriggers.WithLabelValues("pending").Set(1)
	DispatchOldestTriggerAgeSeconds.WithLabelValues("pending").Set(60)
	DispatchStalledAutoAssignmentRecoveryIssues.WithLabelValues(DispatchStalledAutoAssignmentRecoveryOutcomeRetried).Inc()
	TimelineQueuedTasks.WithLabelValues(TimelineJobSyncWorkspace).Set(2)
	TimelineOldestQueuedTimestampSeconds.WithLabelValues(TimelineJobSyncWorkspace).Set(1_000)
	TimelineStaleProcessingWindows.Set(1)

	metricFamilies, err := registry.Gather()
	require.NoError(t, err)
	names := make([]string, 0, len(metricFamilies))
	for _, family := range metricFamilies {
		names = append(names, family.GetName())
	}
	require.ElementsMatch(t, []string{
		"ticket_manager_cron_job_sync_count_total",
		"ticket_manager_cron_job_sync_duration_seconds",
		"ticket_manager_dispatch_assignment_ack_total",
		"ticket_manager_dispatch_assignment_ack_wait_seconds",
		"ticket_manager_dispatch_assignment_action_total",
		"ticket_manager_dispatch_assignment_notification_events_total",
		"ticket_manager_dispatch_assignment_workflow_duration_seconds",
		"ticket_manager_dispatch_created_executions",
		"ticket_manager_dispatch_executions_total",
		"ticket_manager_dispatch_executing_executions",
		"ticket_manager_dispatch_last_failed_execution_info",
		"ticket_manager_dispatch_oldest_created_execution_age_seconds",
		"ticket_manager_dispatch_oldest_executing_execution_age_seconds",
		"ticket_manager_dispatch_oldest_trigger_age_seconds",
		"ticket_manager_dispatch_triggers",
		"ticket_manager_dispatch_stalled_auto_assignment_recovery_issues_total",
		"ticket_manager_event_job_sync_count_total",
		"ticket_manager_event_job_sync_duration_seconds",
		"ticket_manager_gin_request_duration_seconds",
		"ticket_manager_gin_response_size_bytes",
		"ticket_manager_timeline_oldest_queued_timestamp_seconds",
		"ticket_manager_timeline_queued_tasks",
		"ticket_manager_timeline_stale_processing_windows",
	}, names)
}

func resetMetrics() {
	DispatchExecutions.Reset()
	DispatchLastFailedExecutionInfo.Reset()
	DispatchAssignmentNotificationEvents.Reset()
	DispatchAssignmentActions.Reset()
	DispatchAssignmentACKs.Reset()
	DispatchAssignmentACKWaitSeconds.Reset()
	DispatchAssignmentWorkflowDurationSeconds.Reset()
	DispatchCreatedExecutions.Reset()
	DispatchOldestCreatedExecutionAgeSeconds.Reset()
	DispatchExecutingExecutions.Reset()
	DispatchOldestExecutingExecutionAgeSeconds.Reset()
	DispatchTriggers.Reset()
	DispatchOldestTriggerAgeSeconds.Reset()
	DispatchStalledAutoAssignmentRecoveryIssues.Reset()
	TimelineQueuedTasks.Reset()
	TimelineOldestQueuedTimestampSeconds.Reset()
	TimelineStaleProcessingWindows.Set(0)
}
