package queue

import (
	"sync"
	"time"
)

type HealthReporter struct {
	mu                      sync.RWMutex
	startedAt               time.Time
	lastPollAt              time.Time
	lastSuccessAt           time.Time
	lastFailureAt           time.Time
	lastError               string
	consecutivePollFailures int
	errorThreshold          int
	draining                bool
}

type HealthSnapshot struct {
	Status                 string    `json:"status"`
	StartedAt              time.Time `json:"started_at"`
	LastPollAt             time.Time `json:"last_poll_at,omitempty"`
	LastSuccessAt          time.Time `json:"last_success_at,omitempty"`
	LastFailureAt          time.Time `json:"last_failure_at,omitempty"`
	LastError              string    `json:"last_error,omitempty"`
	ConsecutivePollFailure int       `json:"consecutive_poll_failures"`
	Draining               bool      `json:"draining"`
}

func NewHealthReporter(errorThreshold int) *HealthReporter {
	if errorThreshold <= 0 {
		errorThreshold = 3
	}
	now := time.Now().UTC()
	return &HealthReporter{
		startedAt:      now,
		lastPollAt:     now,
		errorThreshold: errorThreshold,
	}
}

func (r *HealthReporter) MarkPollSuccess() {
	r.mu.Lock()
	defer r.mu.Unlock()
	now := time.Now().UTC()
	r.lastPollAt = now
	r.lastSuccessAt = now
	r.consecutivePollFailures = 0
	r.lastError = ""
}

func (r *HealthReporter) MarkPollFailure(err error) {
	r.mu.Lock()
	defer r.mu.Unlock()
	now := time.Now().UTC()
	r.lastPollAt = now
	r.lastFailureAt = now
	r.consecutivePollFailures++
	if err != nil {
		r.lastError = err.Error()
	}
}

func (r *HealthReporter) MarkDraining() {
	r.mu.Lock()
	defer r.mu.Unlock()
	r.draining = true
}

func (r *HealthReporter) Snapshot() HealthSnapshot {
	r.mu.RLock()
	defer r.mu.RUnlock()
	status := "ok"
	if r.draining {
		status = "draining"
	} else if r.consecutivePollFailures >= r.errorThreshold {
		status = "degraded"
	}
	return HealthSnapshot{
		Status:                 status,
		StartedAt:              r.startedAt,
		LastPollAt:             r.lastPollAt,
		LastSuccessAt:          r.lastSuccessAt,
		LastFailureAt:          r.lastFailureAt,
		LastError:              r.lastError,
		ConsecutivePollFailure: r.consecutivePollFailures,
		Draining:               r.draining,
	}
}
