from __future__ import annotations

"""Subscription manager responsible for tier resolution."""

from dataclasses import dataclass, field
from typing import Optional

from .models import SubscriptionFeatures, SubscriptionTier, get_features_for_tier


@dataclass
class SubscriptionManager:
    """Represent a user's subscription and expose helper methods."""

    user_id: str
    tier: SubscriptionTier = SubscriptionTier.FREE
    _cached_features: Optional[SubscriptionFeatures] = field(default=None, init=False, repr=False)
    _override_features: Optional[SubscriptionFeatures] = field(default=None, init=False, repr=False)

    def set_tier(self, tier: str | SubscriptionTier) -> None:
        """Update the current tier."""
        tier_enum = self._coerce_tier(tier)
        if tier_enum != self.tier:
            self.tier = tier_enum
            self._cached_features = None
            self._override_features = None

    def get_features(self) -> SubscriptionFeatures:
        """Return the feature set for the current tier."""
        if self._override_features is not None:
            return self._override_features
        if self._cached_features is None:
            self._cached_features = get_features_for_tier(self.tier)
        return self._cached_features

    def get_domain_limit(self) -> int:
        return self.get_features().domain_limit

    def get_user_limit(self) -> int:
        return self.get_features().max_users

    def can_use_invasive_tests(self) -> bool:
        return self.get_features().allow_invasive_tests

    def can_export_html(self) -> bool:
        return self.get_features().allow_html_export

    def can_manage_users(self) -> bool:
        return self.get_features().allow_multi_user

    def can_use_api(self) -> bool:
        return self.get_features().allow_api_access

    def apply_features(self, features: SubscriptionFeatures) -> None:
        """Override the current feature set using licence-derived values."""
        self.tier = features.tier
        self._override_features = features
        self._cached_features = None

    @staticmethod
    def _coerce_tier(tier: str | SubscriptionTier) -> SubscriptionTier:
        if isinstance(tier, SubscriptionTier):
            return tier
        try:
            return SubscriptionTier(tier.lower())
        except ValueError as exc:
            raise ValueError(f"Unknown subscription tier: {tier}") from exc
