package metrics

import (
	"github.com/prometheus/client_golang/prometheus"

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

const namespace = "ticket_manager"

const (
	TimelineJobSyncWorkspace = "SyncWorkspaceTimeline"
	TimelineJobSyncLark      = "SyncLarkTimeline"

	DispatchAssignmentNotificationEventCardFailed      = "card_failed"
	DispatchAssignmentNotificationEventUrgentFailed    = "urgent_failed"
	DispatchAssignmentNotificationEventPageFailed      = "page_failed"
	DispatchAssignmentNotificationEventACKTimeout      = "ack_timeout"
	DispatchAssignmentNotificationEventLeaderEscalated = "leader_escalated"

	DispatchAssignmentActionCard             = "card"
	DispatchAssignmentActionUrgent           = "urgent"
	DispatchAssignmentActionPage             = "page"
	DispatchAssignmentActionLeaderEscalation = "leader_escalation"

	DispatchAssignmentActionResultSucceeded = "succeeded"
	DispatchAssignmentActionResultFailed    = "failed"
	DispatchAssignmentActionResultUnknown   = "unknown"
	DispatchAssignmentActionResultSkipped   = "skipped"

	DispatchAssignmentACKOutcomeMessageRead       = "message_read"
	DispatchAssignmentACKOutcomeStatusChanged     = "status_changed"
	DispatchAssignmentACKOutcomeTargetChanged     = "target_changed"
	DispatchAssignmentACKOutcomeUrgencyDowngraded = "urgency_downgraded"
	DispatchAssignmentACKOutcomeProjectChanged    = "project_changed"
	DispatchAssignmentACKOutcomeTimeout           = "timeout"

	DispatchAssignmentWorkflowOutcomeCompleted      = "completed"
	DispatchAssignmentWorkflowOutcomeAcknowledged   = "acked"
	DispatchAssignmentWorkflowOutcomeInvalidated    = "invalidated"
	DispatchAssignmentWorkflowOutcomeUnacknowledged = "unacknowledged"
	DispatchAssignmentWorkflowOutcomeEscalated      = "escalated"
	DispatchAssignmentWorkflowOutcomeFailed         = "failed"

	DispatchStalledAutoAssignmentRecoveryOutcomeScanned                = "scanned"
	DispatchStalledAutoAssignmentRecoveryOutcomeSkippedOutsideWindow   = "skipped_outside_window"
	DispatchStalledAutoAssignmentRecoveryOutcomeSkippedActiveExecution = "skipped_active_execution"
	DispatchStalledAutoAssignmentRecoveryOutcomeSkippedActiveTrigger   = "skipped_active_trigger"
	DispatchStalledAutoAssignmentRecoveryOutcomeSkippedNotEligible     = "skipped_not_eligible"
	DispatchStalledAutoAssignmentRecoveryOutcomeSkippedAlreadyAssigned = "skipped_already_assigned"
	DispatchStalledAutoAssignmentRecoveryOutcomeSkippedBackoff         = "skipped_backoff"
	DispatchStalledAutoAssignmentRecoveryOutcomeExhausted              = "exhausted"
	DispatchStalledAutoAssignmentRecoveryOutcomeTriggered              = "triggered"
	DispatchStalledAutoAssignmentRecoveryOutcomeRetried                = "retried"
	DispatchStalledAutoAssignmentRecoveryOutcomeTriggerFailed          = "trigger_failed"
)

var dispatchAssignmentDurationBuckets = []float64{1, 5, 10, 30, 60, 120, 300, 600, 900, 1200, 1800, 3600}

var (
	DispatchExecutions = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: namespace,
			Name:      "dispatch_executions_total",
			Help:      "How many Dispatch executions reached a terminal status.",
		},
		[]string{"mode", "status", "failure_code"},
	)
	DispatchLastFailedExecutionInfo = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "dispatch_last_failed_execution_info",
			Help:      "Information about the last failed Dispatch execution by mode.",
		},
		[]string{"mode", "execution_id", "issue_key", "failure_code"},
	)
	DispatchAssignmentNotificationEvents = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: namespace,
			Name:      "dispatch_assignment_notification_events_total",
			Help:      "How many notable assignment notification events were recorded from terminal Dispatch executions.",
		},
		[]string{"event"},
	)
	DispatchAssignmentActions = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: namespace,
			Name:      "dispatch_assignment_action_total",
			Help:      "How many assignment notification actions reached a terminal result.",
		},
		[]string{"action", "result", "role", "attempt"},
	)
	DispatchAssignmentACKs = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: namespace,
			Name:      "dispatch_assignment_ack_total",
			Help:      "How many assignment acknowledgement guards reached each outcome.",
		},
		[]string{"outcome", "role", "attempt"},
	)
	DispatchAssignmentACKWaitSeconds = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: namespace,
			Name:      "dispatch_assignment_ack_wait_seconds",
			Help:      "How long each assignment acknowledgement guard waited in seconds.",
			Buckets:   dispatchAssignmentDurationBuckets,
		},
		[]string{"outcome", "role", "attempt"},
	)
	DispatchAssignmentWorkflowDurationSeconds = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: namespace,
			Name:      "dispatch_assignment_workflow_duration_seconds",
			Help:      "How long terminal assignment notification workflows took in seconds.",
			Buckets:   dispatchAssignmentDurationBuckets,
		},
		[]string{"outcome", "role"},
	)
	DispatchCreatedExecutions = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "dispatch_created_executions",
			Help:      "Number of Dispatch executions currently in the created status.",
		},
		[]string{"mode"},
	)
	DispatchOldestCreatedExecutionAgeSeconds = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "dispatch_oldest_created_execution_age_seconds",
			Help:      "Age in seconds of the oldest Dispatch execution currently in the created status.",
		},
		[]string{"mode"},
	)
	DispatchExecutingExecutions = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "dispatch_executing_executions",
			Help:      "Number of Dispatch executions currently in the executing status.",
		},
		[]string{"mode"},
	)
	DispatchOldestExecutingExecutionAgeSeconds = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "dispatch_oldest_executing_execution_age_seconds",
			Help:      "Age in seconds of the oldest Dispatch execution currently in the executing status.",
		},
		[]string{"mode"},
	)
	DispatchTriggers = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "dispatch_triggers",
			Help:      "Number of Dispatch triggers currently in a recoverable status.",
		},
		[]string{"status"},
	)
	DispatchOldestTriggerAgeSeconds = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Name:      "dispatch_oldest_trigger_age_seconds",
			Help:      "Age in seconds of the oldest Dispatch trigger currently in a recoverable status.",
		},
		[]string{"status"},
	)
	DispatchStalledAutoAssignmentRecoveryIssues = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: namespace,
			Name:      "dispatch_stalled_auto_assignment_recovery_issues_total",
			Help:      "How many Jira issues the stalled auto-assignment recovery scan observed for each outcome.",
		},
		[]string{"outcome"},
	)
	TimelineQueuedTasks = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Subsystem: "timeline",
			Name:      "queued_tasks",
			Help:      "Number of Timeline tasks waiting to start.",
		},
		[]string{"job_name"},
	)
	TimelineOldestQueuedTimestampSeconds = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Subsystem: "timeline",
			Name:      "oldest_queued_timestamp_seconds",
			Help:      "Unix timestamp of the oldest Timeline task waiting to start, or zero when the queue is empty.",
		},
		[]string{"job_name"},
	)
	TimelineStaleProcessingWindows = prometheus.NewGauge(
		prometheus.GaugeOpts{
			Namespace: namespace,
			Subsystem: "timeline",
			Name:      "stale_processing_windows",
			Help:      "Number of Lark Timeline windows whose processing heartbeat is stale.",
		},
	)
)

func InitMetrics() {
	inframetrics.RegisterGinMetrics(namespace)
	inframetrics.RegisterServiceMetrics(namespace)
	prometheus.MustRegister(
		DispatchExecutions,
		DispatchLastFailedExecutionInfo,
		DispatchAssignmentNotificationEvents,
		DispatchAssignmentActions,
		DispatchAssignmentACKs,
		DispatchAssignmentACKWaitSeconds,
		DispatchAssignmentWorkflowDurationSeconds,
		DispatchCreatedExecutions,
		DispatchOldestCreatedExecutionAgeSeconds,
		DispatchExecutingExecutions,
		DispatchOldestExecutingExecutionAgeSeconds,
		DispatchTriggers,
		DispatchOldestTriggerAgeSeconds,
		DispatchStalledAutoAssignmentRecoveryIssues,
		TimelineQueuedTasks,
		TimelineOldestQueuedTimestampSeconds,
		TimelineStaleProcessingWindows,
	)
	for _, jobName := range []string{TimelineJobSyncWorkspace, TimelineJobSyncLark} {
		TimelineQueuedTasks.WithLabelValues(jobName).Set(0)
		TimelineOldestQueuedTimestampSeconds.WithLabelValues(jobName).Set(0)
	}
	TimelineStaleProcessingWindows.Set(0)
	for _, event := range []string{
		DispatchAssignmentNotificationEventCardFailed,
		DispatchAssignmentNotificationEventUrgentFailed,
		DispatchAssignmentNotificationEventPageFailed,
		DispatchAssignmentNotificationEventACKTimeout,
		DispatchAssignmentNotificationEventLeaderEscalated,
	} {
		DispatchAssignmentNotificationEvents.WithLabelValues(event).Add(0)
	}
	for _, outcome := range []string{
		DispatchStalledAutoAssignmentRecoveryOutcomeScanned,
		DispatchStalledAutoAssignmentRecoveryOutcomeSkippedOutsideWindow,
		DispatchStalledAutoAssignmentRecoveryOutcomeSkippedActiveExecution,
		DispatchStalledAutoAssignmentRecoveryOutcomeSkippedActiveTrigger,
		DispatchStalledAutoAssignmentRecoveryOutcomeSkippedNotEligible,
		DispatchStalledAutoAssignmentRecoveryOutcomeSkippedAlreadyAssigned,
		DispatchStalledAutoAssignmentRecoveryOutcomeSkippedBackoff,
		DispatchStalledAutoAssignmentRecoveryOutcomeExhausted,
		DispatchStalledAutoAssignmentRecoveryOutcomeTriggered,
		DispatchStalledAutoAssignmentRecoveryOutcomeRetried,
		DispatchStalledAutoAssignmentRecoveryOutcomeTriggerFailed,
	} {
		DispatchStalledAutoAssignmentRecoveryIssues.WithLabelValues(outcome).Add(0)
	}
}
