"""Subscription selectors — read-only queries."""

from __future__ import annotations

from typing import TYPE_CHECKING

from django.db.models import QuerySet
from django.utils import timezone

from simorgh.apps.subscription.models import (
    PlatformPlan,
    TenantAddonFeature,
    TenantSubscription,
)

if TYPE_CHECKING:
    from simorgh.apps.tenants.models import Tenant


def get_active_subscription(tenant_id: int) -> TenantSubscription | None:
    """Return the active (or trial) subscription for a tenant, or None."""
    return (
        TenantSubscription.objects.filter(tenant_id=tenant_id)
        .select_related("plan")
        .first()
    )


def get_plan(plan_code: str) -> PlatformPlan | None:
    """Return a PlatformPlan by code, or None."""
    return PlatformPlan.objects.filter(code=plan_code, is_active=True).first()


def list_public_plans() -> QuerySet[PlatformPlan]:
    """Return all publicly-visible active plans ordered by sort_order."""
    return PlatformPlan.objects.filter(is_active=True, is_public=True).order_by(
        "sort_order"
    )


def get_addons(tenant_id: int) -> QuerySet[TenantAddonFeature]:
    """Return all add-on features purchased by a tenant."""
    return TenantAddonFeature.objects.filter(tenant_id=tenant_id)


def get_active_addons(tenant_id: int) -> QuerySet[TenantAddonFeature]:
    """Return only active (non-expired) add-on features."""
    return _active_addon_qs(tenant_id)


def _active_addon_qs(tenant_id: int) -> QuerySet[TenantAddonFeature]:
    """Internal helper — add-ons that are currently active."""
    from django.db.models import Q

    now = timezone.now()
    return TenantAddonFeature.objects.filter(
        tenant_id=tenant_id
    ).filter(
        Q(expires_at__isnull=True) | Q(expires_at__gt=now)
    )


def is_feature_enabled(tenant: Tenant, feature_key: str) -> bool:
    """Feature Resolution Algorithm (6 steps).

    Step 1: feature.is_always_on == True                        → ENABLED
    Step 2: TenantFeatureOverride.enabled == False               → DISABLED
    Step 3: TenantFeatureOverride.enabled == True                → ENABLED
    Step 4: TenantAddonFeature (active, not expired)             → ENABLED
    Step 5: PlanEntitlement (tenant's active plan)               → ENABLED
    Step 6: default                                              → DISABLED

    Feature keys are resolved through the backward-compat alias layer
    (Phase C — old 2-level keys still work for 6 months).
    """
    from simorgh.apps.modules.compat import resolve_feature_key
    from simorgh.apps.modules.models import FeatureCatalog, TenantFeatureOverride

    feature_key = resolve_feature_key(feature_key)

    # Step 1 — always_on features
    try:
        catalog_entry = FeatureCatalog.objects.filter(code=feature_key).only(
            "is_always_on"
        ).first()
        if catalog_entry and getattr(catalog_entry, "is_always_on", False):
            return True
    except Exception:
        pass

    # Step 2 & 3 — explicit tenant override (tenant-wide, no user filter)
    override = (
        TenantFeatureOverride.objects.filter(
            tenant=tenant,
            feature_key=feature_key,
            user__isnull=True,
        )
        .only("enabled")
        .first()
    )
    if override is not None:
        return override.enabled

    # Step 4 — active add-on
    if _active_addon_qs(tenant.pk).filter(feature_key=feature_key).exists():
        return True

    # Step 5 — plan entitlement
    sub = get_active_subscription(tenant.pk)
    if sub and sub.plan.plan_features.filter(feature_key=feature_key, enabled_by_default=True).exists():
        return True

    # Step 6 — disabled by default
    return False


def get_all_enabled_features(tenant_id: int) -> set[str]:
    """Return the set of all enabled feature keys for a tenant.

    Used by the frontend manifest endpoint to gate navigation items.
    """

    from simorgh.apps.modules.models import FeatureCatalog

    enabled: set[str] = set()

    # always_on features
    always_on = FeatureCatalog.objects.filter(
        is_always_on=True
    ).values_list("code", flat=True)
    enabled.update(always_on)

    # plan features
    sub = get_active_subscription(tenant_id)
    if sub:
        plan_keys = sub.plan.plan_features.filter(
            enabled_by_default=True
        ).values_list("feature_key", flat=True)
        enabled.update(plan_keys)

    # active addons
    addon_keys = _active_addon_qs(tenant_id).values_list("feature_key", flat=True)
    enabled.update(addon_keys)

    # apply tenant-wide overrides
    from simorgh.apps.modules.models import TenantFeatureOverride

    overrides = TenantFeatureOverride.objects.filter(
        tenant_id=tenant_id, user__isnull=True
    ).values_list("feature_key", "enabled")
    for fkey, is_enabled in overrides:
        if fkey is None:
            continue
        if is_enabled:
            enabled.add(fkey)
        else:
            enabled.discard(fkey)

    return enabled


def get_plan_limits(tenant_id: int) -> dict:
    """Return resource limits for the tenant's active plan."""
    sub = get_active_subscription(tenant_id)
    if not sub:
        return {
            "user_limit": 3,
            "storage_gb": 1,
            "workflow_limit": 5,
            "api_calls_per_month": 1000,
        }
    plan = sub.plan
    return {
        "user_limit": plan.user_limit,
        "storage_gb": plan.storage_gb,
        "workflow_limit": plan.workflow_limit,
        "api_calls_per_month": plan.api_calls_per_month,
    }
