"""
Subscription Tiers - Define provider tiers and their limits.

Provides:
- Provider enumeration
- Subscription tier enumeration
- Rate limit configurations per tier
"""

from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Optional


class Provider(Enum):
    """Supported AI providers."""

    ANTHROPIC = "anthropic"
    OPENAI = "openai"
    GOOGLE = "google"


class SubscriptionTier(Enum):
    """Subscription tier levels."""

    # Claude tiers
    CLAUDE_FREE = "claude_free"
    CLAUDE_PRO = "claude_pro"
    CLAUDE_MAX = "claude_max"

    # ChatGPT/Codex tiers
    CHATGPT_FREE = "chatgpt_free"
    CHATGPT_PLUS = "chatgpt_plus"
    CHATGPT_PRO = "chatgpt_pro"

    # Gemini tiers
    GEMINI_FREE = "gemini_free"
    GEMINI_PRO = "gemini_pro"
    GEMINI_ULTRA = "gemini_ultra"

    # Unknown/default
    UNKNOWN = "unknown"


@dataclass
class TierLimits:
    """Rate limits and capabilities for a subscription tier."""

    # Rate limits
    messages_per_window: int
    window_hours: float
    daily_messages: Optional[int] = None
    weekly_messages: Optional[int] = None

    # Capabilities
    context_window: int = 128000
    max_output_tokens: int = 4096
    supports_streaming: bool = True
    supports_vision: bool = True
    supports_tools: bool = True
    supports_computer_use: bool = False

    # Model access
    available_models: list[str] = field(default_factory=list)
    default_model: str = ""

    @property
    def messages_per_hour(self) -> float:
        """Calculate average messages per hour."""
        if self.window_hours > 0:
            return self.messages_per_window / self.window_hours
        return float("inf")

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary."""
        return {
            "messages_per_window": self.messages_per_window,
            "window_hours": self.window_hours,
            "daily_messages": self.daily_messages,
            "weekly_messages": self.weekly_messages,
            "context_window": self.context_window,
            "max_output_tokens": self.max_output_tokens,
            "supports_streaming": self.supports_streaming,
            "supports_vision": self.supports_vision,
            "supports_tools": self.supports_tools,
            "supports_computer_use": self.supports_computer_use,
            "available_models": self.available_models,
            "default_model": self.default_model,
        }


@dataclass
class SubscriptionConfig:
    """Full subscription configuration for an agent."""

    tier: SubscriptionTier
    provider: Provider
    limits: TierLimits
    account_email: str = ""
    autonomy_level: str = "assisted"  # "auto", "assisted", "manual"
    auto_response_enabled: bool = False
    metadata: dict[str, Any] = field(default_factory=dict)

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary."""
        return {
            "tier": self.tier.value,
            "provider": self.provider.value,
            "limits": self.limits.to_dict(),
            "account_email": self.account_email,
            "autonomy_level": self.autonomy_level,
            "auto_response_enabled": self.auto_response_enabled,
        }


# Provider-specific tier configurations
TIER_CONFIGURATIONS: dict[SubscriptionTier, TierLimits] = {
    # Claude tiers
    SubscriptionTier.CLAUDE_FREE: TierLimits(
        messages_per_window=5,
        window_hours=5,
        context_window=128000,
        max_output_tokens=4096,
        available_models=["claude-sonnet-4-20250514"],
        default_model="claude-sonnet-4-20250514",
    ),
    SubscriptionTier.CLAUDE_PRO: TierLimits(
        messages_per_window=45,
        window_hours=5,
        context_window=200000,
        max_output_tokens=8192,
        supports_computer_use=True,
        available_models=[
            "claude-opus-4-20250514",
            "claude-sonnet-4-20250514",
            "claude-haiku-3-5-20241022",
        ],
        default_model="claude-sonnet-4-20250514",
    ),
    SubscriptionTier.CLAUDE_MAX: TierLimits(
        messages_per_window=225,
        window_hours=5,
        context_window=200000,
        max_output_tokens=16384,
        supports_computer_use=True,
        available_models=[
            "claude-opus-4-20250514",
            "claude-sonnet-4-20250514",
            "claude-haiku-3-5-20241022",
        ],
        default_model="claude-opus-4-20250514",
    ),

    # ChatGPT/Codex tiers
    SubscriptionTier.CHATGPT_FREE: TierLimits(
        messages_per_window=10,
        window_hours=3,
        context_window=8192,
        max_output_tokens=4096,
        supports_vision=False,
        available_models=["gpt-4o-mini"],
        default_model="gpt-4o-mini",
    ),
    SubscriptionTier.CHATGPT_PLUS: TierLimits(
        messages_per_window=80,
        window_hours=3,
        context_window=128000,
        max_output_tokens=4096,
        available_models=["gpt-4o", "gpt-4o-mini", "o1", "o1-mini"],
        default_model="gpt-4o",
    ),
    SubscriptionTier.CHATGPT_PRO: TierLimits(
        messages_per_window=200,
        window_hours=3,
        context_window=128000,
        max_output_tokens=16384,
        available_models=["gpt-4o", "gpt-4o-mini", "o1", "o1-mini", "o1-pro"],
        default_model="o1",
    ),

    # Gemini tiers
    SubscriptionTier.GEMINI_FREE: TierLimits(
        messages_per_window=50,
        window_hours=24,
        daily_messages=50,
        context_window=128000,
        available_models=["gemini-2.0-flash"],
        default_model="gemini-2.0-flash",
    ),
    SubscriptionTier.GEMINI_PRO: TierLimits(
        messages_per_window=1000,
        window_hours=24,
        daily_messages=1000,
        context_window=1000000,  # 1M context
        max_output_tokens=8192,
        available_models=["gemini-2.0-flash", "gemini-2.0-pro", "gemini-2.5-pro"],
        default_model="gemini-2.5-pro",
    ),
    SubscriptionTier.GEMINI_ULTRA: TierLimits(
        messages_per_window=2000,
        window_hours=24,
        daily_messages=2000,
        context_window=2000000,  # 2M context
        max_output_tokens=16384,
        available_models=["gemini-2.0-flash", "gemini-2.0-pro", "gemini-2.5-pro", "gemini-ultra"],
        default_model="gemini-ultra",
    ),

    # Unknown/default
    SubscriptionTier.UNKNOWN: TierLimits(
        messages_per_window=10,
        window_hours=1,
        context_window=8192,
        available_models=[],
        default_model="",
    ),
}


def get_tier_limits(tier: SubscriptionTier) -> TierLimits:
    """Get limits for a subscription tier."""
    return TIER_CONFIGURATIONS.get(tier, TIER_CONFIGURATIONS[SubscriptionTier.UNKNOWN])


def get_provider_for_tier(tier: SubscriptionTier) -> Provider:
    """Get provider for a subscription tier."""
    tier_name = tier.value.lower()
    if tier_name.startswith("claude"):
        return Provider.ANTHROPIC
    elif tier_name.startswith("chatgpt"):
        return Provider.OPENAI
    elif tier_name.startswith("gemini"):
        return Provider.GOOGLE
    return Provider.ANTHROPIC  # Default


def get_default_tier_for_provider(provider: Provider) -> SubscriptionTier:
    """Get default tier for a provider."""
    defaults = {
        Provider.ANTHROPIC: SubscriptionTier.CLAUDE_PRO,
        Provider.OPENAI: SubscriptionTier.CHATGPT_PLUS,
        Provider.GOOGLE: SubscriptionTier.GEMINI_PRO,
    }
    return defaults.get(provider, SubscriptionTier.UNKNOWN)


def list_tiers_for_provider(provider: Provider) -> list[SubscriptionTier]:
    """List all tiers for a provider."""
    provider_prefix = {
        Provider.ANTHROPIC: "claude",
        Provider.OPENAI: "chatgpt",
        Provider.GOOGLE: "gemini",
    }
    prefix = provider_prefix.get(provider, "")
    return [tier for tier in SubscriptionTier if tier.value.startswith(prefix)]
