# app/modules/billing/models/merchant_subscription.py
"""
Merchant-level subscription model.

Replaces StoreSubscription with merchant-level billing:
- One subscription per merchant per platform
- Merchant is the billing entity (not the store)
- Stores inherit features/limits from their merchant's subscription
"""

from datetime import UTC, datetime

from sqlalchemy import (
    Boolean,
    Column,
    DateTime,
    ForeignKey,
    Index,
    Integer,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.orm import relationship

from app.core.database import Base
from app.modules.billing.models.subscription import SubscriptionStatus
from models.database.base import TimestampMixin


class MerchantSubscription(Base, TimestampMixin):
    """
    Per-merchant, per-platform subscription tracking.

    The merchant (legal entity) subscribes and pays, not the store.
    A merchant can own multiple stores and subscribe per-platform.

    Example:
        Merchant "Boucherie Luxembourg" subscribes to:
        - Orion OMS (Professional tier)
        - Loyalty+ (Essential tier)

        Their stores inherit features from the merchant's subscription.
    """

    __tablename__ = "merchant_subscriptions"

    id = Column(Integer, primary_key=True, index=True)

    # Who pays
    merchant_id = Column(
        Integer,
        ForeignKey("merchants.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
    )

    # Which platform
    platform_id = Column(
        Integer,
        ForeignKey("platforms.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
    )

    # Which tier
    tier_id = Column(
        Integer,
        ForeignKey("subscription_tiers.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )

    # Status
    status = Column(
        String(20),
        default=SubscriptionStatus.TRIAL.value,
        nullable=False,
        index=True,
    )

    # Billing period
    is_annual = Column(Boolean, default=False, nullable=False)
    period_start = Column(DateTime(timezone=True), nullable=False)
    period_end = Column(DateTime(timezone=True), nullable=False)

    # Trial info
    trial_ends_at = Column(DateTime(timezone=True), nullable=True)

    # Stripe integration (per merchant)
    stripe_customer_id = Column(String(100), nullable=True, index=True)
    stripe_subscription_id = Column(String(100), nullable=True, index=True)
    stripe_payment_method_id = Column(String(100), nullable=True)

    # Payment failure tracking
    payment_retry_count = Column(Integer, default=0, nullable=False)
    last_payment_error = Column(Text, nullable=True)

    # Cancellation
    cancelled_at = Column(DateTime(timezone=True), nullable=True)
    cancellation_reason = Column(Text, nullable=True)

    # Relationships
    merchant = relationship(
        "Merchant",
        backref="subscriptions",
        foreign_keys=[merchant_id],
    )
    platform = relationship(
        "Platform",
        foreign_keys=[platform_id],
    )
    tier = relationship(
        "SubscriptionTier",
        foreign_keys=[tier_id],
    )

    __table_args__ = (
        UniqueConstraint(
            "merchant_id", "platform_id",
            name="uq_merchant_platform_subscription",
        ),
        Index("idx_merchant_sub_status", "merchant_id", "status"),
        Index("idx_merchant_sub_platform", "platform_id", "status"),
    )

    def __repr__(self):
        return (
            f"<MerchantSubscription("
            f"merchant_id={self.merchant_id}, "
            f"platform_id={self.platform_id}, "
            f"status='{self.status}'"
            f")>"
        )

    # =========================================================================
    # Status Checks
    # =========================================================================

    @property
    def is_active(self) -> bool:
        """Check if subscription allows access."""
        return self.status in [
            SubscriptionStatus.TRIAL.value,
            SubscriptionStatus.ACTIVE.value,
            SubscriptionStatus.PAST_DUE.value,
            SubscriptionStatus.CANCELLED.value,
        ]

    @property
    def is_trial(self) -> bool:
        """Check if currently in trial."""
        return self.status == SubscriptionStatus.TRIAL.value

    @property
    def trial_days_remaining(self) -> int | None:
        """Get remaining trial days."""
        if not self.is_trial or not self.trial_ends_at:
            return None
        remaining = (self.trial_ends_at - datetime.now(UTC)).days
        return max(0, remaining)


__all__ = ["MerchantSubscription"]
