"""Subscription domain models.

Core entities for the feature-based licensing system:
  PlatformPlan     — tiered plan definitions (aliased as Plan)
  PlanFeature      — features included in each plan (aliased as PlanEntitlement)
  Addon             — standalone addon product (Phase B)
  AddonEntitlement  — features included in an addon (Phase B)
  TenantSubscription — per-tenant subscription lifecycle
  TenantAddonFeature — add-on features purchased separately
"""

from __future__ import annotations

from typing import ClassVar

from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from simorgh.core.models import TenantScopedModel, TimeStampedModel, UUIDModel

# ---------------------------------------------------------------------------
# Addon (Phase B)
# ---------------------------------------------------------------------------


class Addon(UUIDModel, TimeStampedModel):
    """A standalone addon product purchasable on top of any Plan.

    Examples: "AI Assistant", "Advanced Reporting", "API Access Pack".
    """

    code = models.SlugField(
        _("code"),
        max_length=40,
        unique=True,
        db_index=True,
        help_text=_("Stable machine-readable code, e.g. 'ai-assistant'."),
    )
    name = models.CharField(_("name"), max_length=200)
    description = models.TextField(_("description"), blank=True, default="")
    price_monthly = models.DecimalField(
        _("monthly price"), max_digits=12, decimal_places=2, default=0,
    )
    price_yearly = models.DecimalField(
        _("yearly price"), max_digits=12, decimal_places=2, default=0,
    )
    is_active = models.BooleanField(_("active"), default=True)
    sort_order = models.PositiveSmallIntegerField(
        _("sort order"), default=0, db_index=True,
    )

    class Meta:
        verbose_name = _("addon")
        verbose_name_plural = _("addons")
        ordering = ("sort_order", "code")

    def __str__(self) -> str:
        return f"{self.name} ({self.code})"


class AddonEntitlement(UUIDModel, TimeStampedModel):
    """Maps feature keys to an Addon — controls which features each addon unlocks."""

    addon = models.ForeignKey(
        Addon,
        on_delete=models.CASCADE,
        related_name="entitlements",
        verbose_name=_("addon"),
    )
    feature_key = models.CharField(
        _("feature key"),
        max_length=120,
        db_index=True,
        help_text=_("Dotted key, e.g. 'ai.assistant' — 3-level: module.capability.feature."),
    )
    enabled_by_default = models.BooleanField(_("enabled by default"), default=True)
    config_json = models.JSONField(
        _("config"),
        default=dict,
        blank=True,
        help_text=_("Limits, e.g. {'max': 100}"),
    )

    class Meta:
        verbose_name = _("addon entitlement")
        verbose_name_plural = _("addon entitlements")
        ordering = ("addon__code", "feature_key")
        constraints: ClassVar[list[models.BaseConstraint]] = [
            models.UniqueConstraint(
                fields=("addon", "feature_key"),
                name="subscription_addonentitlement_unique",
            ),
        ]

    def __str__(self) -> str:
        return f"{self.addon.code} → {self.feature_key}"


# ---------------------------------------------------------------------------
# Plan (was PlatformPlan)
# ---------------------------------------------------------------------------


class PlatformPlan(UUIDModel, TimeStampedModel):
    """A tier of the Simorgh platform (e.g. free, starter, business, enterprise).

    Aliased as ``Plan`` for Phase B compatibility.
    """

    class Currency(models.TextChoices):
        IRR = "IRR", _("Iranian Rial")
        USD = "USD", _("US Dollar")

    code = models.CharField(
        _("code"),
        max_length=40,
        unique=True,
        db_index=True,
        help_text=_("Stable code: free | starter | business | enterprise | custom"),
    )
    name = models.CharField(_("name"), max_length=200)
    description = models.TextField(_("description"), blank=True, default="")

    price_monthly = models.DecimalField(
        _("monthly price"), max_digits=12, decimal_places=2, default=0
    )
    price_yearly = models.DecimalField(
        _("yearly price"), max_digits=12, decimal_places=2, default=0
    )
    currency = models.CharField(
        _("currency"),
        max_length=8,
        choices=Currency.choices,
        default=Currency.IRR,
    )

    user_limit = models.IntegerField(
        _("user limit"),
        default=-1,
        help_text=_("-1 means unlimited"),
    )
    storage_gb = models.IntegerField(_("storage (GB)"), default=1)
    workflow_limit = models.IntegerField(
        _("workflow limit"),
        default=-1,
        help_text=_("-1 means unlimited"),
    )
    api_calls_per_month = models.IntegerField(
        _("API calls per month"),
        default=-1,
        help_text=_("-1 means unlimited"),
    )
    trial_days = models.IntegerField(_("trial days"), default=14)

    is_public = models.BooleanField(
        _("public"),
        default=True,
        help_text=_("Show on pricing page"),
    )
    is_active = models.BooleanField(_("active"), default=True)
    sort_order = models.PositiveIntegerField(_("sort order"), default=0, db_index=True)

    class Meta:
        verbose_name = _("plan")
        verbose_name_plural = _("plans")
        ordering = ("sort_order", "code")

    def __str__(self) -> str:
        return f"{self.name} ({self.code})"


# Phase B alias
Plan = PlatformPlan


# ---------------------------------------------------------------------------
# PlanFeature
# ---------------------------------------------------------------------------


class PlanFeature(UUIDModel, TimeStampedModel):
    """Maps a feature key to a Plan — controls which features each plan includes.

    Aliased as ``PlanEntitlement`` for Phase B compatibility.
    """

    plan = models.ForeignKey(
        PlatformPlan,
        on_delete=models.CASCADE,
        related_name="plan_features",
        verbose_name=_("plan"),
    )
    feature_key = models.CharField(
        _("feature key"),
        max_length=120,
        db_index=True,
        help_text=_("Dotted key, e.g. 'crm.pipeline'"),
    )
    enabled_by_default = models.BooleanField(_("enabled by default"), default=True)
    config_json = models.JSONField(
        _("config"),
        default=dict,
        blank=True,
        help_text=_("Limits, e.g. {'max': 100}"),
    )

    class Meta:
        verbose_name = _("plan entitlement")
        verbose_name_plural = _("plan entitlements")
        ordering = ("plan__code", "feature_key")
        constraints: ClassVar[list[models.BaseConstraint]] = [
            models.UniqueConstraint(
                fields=("plan", "feature_key"),
                name="subscription_planfeature_unique_plan_key",
            ),
        ]

    def __str__(self) -> str:
        return f"{self.plan.code} → {self.feature_key}"


# Phase B alias
PlanEntitlement = PlanFeature


# ---------------------------------------------------------------------------
# TenantSubscription
# ---------------------------------------------------------------------------


class SubscriptionStatus(models.TextChoices):
    TRIAL = "trial", _("Trial")
    ACTIVE = "active", _("Active")
    SUSPENDED = "suspended", _("Suspended")
    EXPIRED = "expired", _("Expired")
    CANCELLED = "cancelled", _("Cancelled")


class TenantSubscription(UUIDModel, TenantScopedModel):
    """Active subscription linking a tenant to a plan."""

    # Override: subscription is tenant-level, not org-node-level.
    organization_node = models.ForeignKey(
        "organizations.OrganizationNode",
        on_delete=models.PROTECT,
        related_name="+",
        null=True,
        blank=True,
        verbose_name=_("organization node"),
    )

    plan = models.ForeignKey(
        PlatformPlan,
        on_delete=models.PROTECT,
        related_name="subscriptions",
        verbose_name=_("plan"),
    )
    status = models.CharField(
        _("status"),
        max_length=16,
        choices=SubscriptionStatus.choices,
        default=SubscriptionStatus.TRIAL,
        db_index=True,
    )

    trial_ends_at = models.DateTimeField(_("trial ends at"), null=True, blank=True)
    current_period_start = models.DateTimeField(
        _("period start"), null=True, blank=True
    )
    current_period_end = models.DateTimeField(
        _("period end"), null=True, blank=True
    )
    seat_count = models.IntegerField(_("seat count"), default=1)
    cancelled_at = models.DateTimeField(_("cancelled at"), null=True, blank=True)
    cancellation_reason = models.TextField(
        _("cancellation reason"), blank=True, default=""
    )

    class Meta:
        verbose_name = _("tenant subscription")
        verbose_name_plural = _("tenant subscriptions")
        ordering = ("-created_at",)
        constraints: ClassVar[list[models.BaseConstraint]] = [
            models.UniqueConstraint(
                fields=("tenant",),
                name="subscription_tenantsub_unique_per_tenant",
            ),
        ]
        indexes: ClassVar[list[models.Index]] = [
            models.Index(fields=("tenant", "status")),
        ]

    @property
    def is_active(self) -> bool:
        return self.status in (SubscriptionStatus.ACTIVE, SubscriptionStatus.TRIAL)

    def __str__(self) -> str:
        return f"{self.tenant_id} — {self.plan.code} ({self.status})"


# ---------------------------------------------------------------------------
# TenantAddonFeature
# ---------------------------------------------------------------------------


class TenantAddonFeature(UUIDModel, TenantScopedModel):
    """A feature purchased as an add-on outside the base plan."""

    # Phase B — link to Addon product catalogue
    addon = models.ForeignKey(
        Addon,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="tenant_purchases",
        verbose_name=_("addon"),
        help_text=_("The addon product this purchase is for."),
    )
    feature_key = models.CharField(
        _("feature key"),
        max_length=120,
        db_index=True,
        help_text=_("Dotted key, e.g. 'ai.assistant'"),
    )
    purchased_at = models.DateTimeField(_("purchased at"), default=timezone.now)
    expires_at = models.DateTimeField(
        _("expires at"),
        null=True,
        blank=True,
        help_text=_("null = never expires"),
    )
    price_paid = models.DecimalField(
        _("price paid"), max_digits=12, decimal_places=2, default=0
    )

    class Meta:
        verbose_name = _("tenant addon feature")
        verbose_name_plural = _("tenant addon features")
        ordering = ("-purchased_at",)
        constraints: ClassVar[list[models.BaseConstraint]] = [
            models.UniqueConstraint(
                fields=("tenant", "feature_key"),
                name="subscription_addonfeature_unique_per_tenant",
            ),
        ]
        indexes: ClassVar[list[models.Index]] = [
            models.Index(fields=("tenant", "feature_key")),
        ]

    @property
    def is_active(self) -> bool:
        return self.expires_at is None or self.expires_at > timezone.now()

    def __str__(self) -> str:
        return f"{self.tenant_id} + {self.feature_key}"
