// Package state provides thread-safe global state management for the copilot service.
// It maintains configuration, tokens, cached data, and rate limiting information.
package state

import (
	"sync"
	"time"
)

// =============================================================================
// Quota Types
// =============================================================================

// QuotaDetail represents detailed quota information for a specific feature.
type QuotaDetail struct {
	// Entitlement is the total quota allowance
	Entitlement float64 `json:"entitlement"`
	// OverageCount is the number of times quota has been exceeded
	OverageCount float64 `json:"overage_count"`
	// OveragePermitted indicates if overage is allowed
	OveragePermitted bool `json:"overage_permitted"`
	// PercentRemaining is the percentage of quota remaining
	PercentRemaining float64 `json:"percent_remaining"`
	// QuotaID is the unique identifier for this quota
	QuotaID string `json:"quota_id"`
	// QuotaRemaining is the remaining quota count
	QuotaRemaining float64 `json:"quota_remaining"`
	// Remaining is the remaining count (may differ from QuotaRemaining)
	Remaining float64 `json:"remaining"`
	// Unlimited indicates if this quota has no limit
	Unlimited bool `json:"unlimited"`
}

// QuotaSnapshots contains quota information for different Copilot features.
type QuotaSnapshots struct {
	// Chat is the quota information for chat features
	Chat QuotaDetail `json:"chat"`
	// Completions is the quota information for code completion features
	Completions QuotaDetail `json:"completions"`
	// PremiumInteractions is the quota information for premium features
	PremiumInteractions QuotaDetail `json:"premium_interactions"`
}

// CopilotUsageResponse represents the Copilot usage and subscription information.
type CopilotUsageResponse struct {
	// AccessTypeSKU is the stock keeping unit for the access type
	AccessTypeSKU string `json:"access_type_sku"`
	// AnalyticsTrackingID is used for analytics tracking
	AnalyticsTrackingID string `json:"analytics_tracking_id"`
	// AssignedDate is when the subscription was assigned
	AssignedDate string `json:"assigned_date"`
	// CanSignupForLimited indicates if user can sign up for limited access
	CanSignupForLimited bool `json:"can_signup_for_limited"`
	// ChatEnabled indicates if chat features are enabled
	ChatEnabled bool `json:"chat_enabled"`
	// CopilotPlan is the name of the Copilot subscription plan
	CopilotPlan string `json:"copilot_plan"`
	// OrganizationLoginList is list of organization logins with access
	OrganizationLoginList []interface{} `json:"organization_login_list"`
	// OrganizationList is list of organizations with access
	OrganizationList []interface{} `json:"organization_list"`
	// QuotaResetDate is when the quota will reset
	QuotaResetDate string `json:"quota_reset_date"`
	// QuotaSnapshots contains detailed quota information
	QuotaSnapshots QuotaSnapshots `json:"quota_snapshots"`
}

// =============================================================================
// TokenState - State for a single token pair
// =============================================================================

// TokenState holds state for a single GitHub/Copilot token pair.
// All fields are protected by a read-write mutex for thread-safe access.
type TokenState struct {
	// mu protects all fields from concurrent access
	mu sync.RWMutex

	// gitHubToken stores the GitHub authentication token
	gitHubToken string
	// copilotToken stores the GitHub Copilot API token
	copilotToken string
	// copilotUsage stores the Copilot usage and quota information
	copilotUsage *CopilotUsageResponse
	// gitHubUser stores the GitHub username associated with this token
	gitHubUser string

	// planTier caches the subscription tier, computed when usage data is set
	planTier ModelTier

	// enabled indicates whether this token is currently active and can be used
	enabled bool

	// lastRequestTime tracks the last API request for rate limiting
	lastRequestTime time.Time
	// lastRefreshTime tracks when the copilot token was last refreshed
	lastRefreshTime time.Time
}

// NewTokenState creates a new TokenState with the given GitHub token.
func NewTokenState(gitHubToken string) *TokenState {
	return &TokenState{
		gitHubToken: gitHubToken,
		enabled:     true, // Tokens are enabled by default
	}
}

// GitHubToken returns the GitHub authentication token thread-safely.
func (s *TokenState) GitHubToken() string {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.gitHubToken
}

// SetGitHubToken updates the GitHub authentication token thread-safely.
func (s *TokenState) SetGitHubToken(token string) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.gitHubToken = token
}

// CopilotToken returns the GitHub Copilot API token thread-safely.
func (s *TokenState) CopilotToken() string {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.copilotToken
}

// SetCopilotToken updates the GitHub Copilot API token thread-safely.
func (s *TokenState) SetCopilotToken(token string) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.copilotToken = token
}

// CopilotUsage returns the GitHub Copilot usage and quota information thread-safely.
func (s *TokenState) CopilotUsage() *CopilotUsageResponse {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.copilotUsage
}

// SetCopilotUsage updates the GitHub Copilot usage and quota information thread-safely.
// It also caches the computed plan tier to avoid repeated lookups.
func (s *TokenState) SetCopilotUsage(usage *CopilotUsageResponse) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.copilotUsage = usage
	s.planTier = PlanTier(usage.CopilotPlan)
}

// PlanTier returns the cached subscription tier for this token.
func (s *TokenState) PlanTier() ModelTier {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.planTier
}

// LastRequestTime returns the timestamp of the last API request thread-safely.
func (s *TokenState) LastRequestTime() time.Time {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.lastRequestTime
}

// SetLastRequestTime updates the last request timestamp thread-safely.
func (s *TokenState) SetLastRequestTime(t time.Time) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.lastRequestTime = t
}

// LastRefreshTime returns the timestamp of the last copilot token refresh thread-safely.
func (s *TokenState) LastRefreshTime() time.Time {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.lastRefreshTime
}

// SetLastRefreshTime updates the last refresh timestamp thread-safely.
func (s *TokenState) SetLastRefreshTime(t time.Time) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.lastRefreshTime = t
}

// GitHubUser returns the GitHub username thread-safely.
func (s *TokenState) GitHubUser() string {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.gitHubUser
}

// SetGitHubUser updates the GitHub username thread-safely.
func (s *TokenState) SetGitHubUser(user string) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.gitHubUser = user
}

// HasPremiumQuota checks if the token has available premium quota.
// Returns true if the premium interactions quota has remaining capacity.
func (s *TokenState) HasPremiumQuota() bool {
	s.mu.RLock()
	defer s.mu.RUnlock()

	if s.copilotUsage == nil {
		// No usage info yet, assume available
		return true
	}

	quota := s.copilotUsage.QuotaSnapshots.PremiumInteractions
	if quota.Unlimited {
		return true
	}

	// Check if there's remaining quota
	return quota.Remaining > 0 || quota.PercentRemaining > 0
}

// PremiumQuota returns the premium interactions quota detail.
func (s *TokenState) PremiumQuota() QuotaDetail {
	s.mu.RLock()
	defer s.mu.RUnlock()

	if s.copilotUsage == nil {
		return QuotaDetail{}
	}

	return s.copilotUsage.QuotaSnapshots.PremiumInteractions
}

// Enabled returns whether the token is currently enabled thread-safely.
func (s *TokenState) Enabled() bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.enabled
}

// SetEnabled updates the enabled state of the token thread-safely.
func (s *TokenState) SetEnabled(enabled bool) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.enabled = enabled
}
