"""Subscription API views.

Endpoints:
  GET    /api/v1/subscription/                    — current subscription + plan info
  GET    /api/v1/subscription/plans/              — list public plans
  POST   /api/v1/subscription/start-trial/        — start a trial
  POST   /api/v1/subscription/change-plan/        — upgrade / downgrade
  POST   /api/v1/subscription/cancel/             — cancel subscription
  GET    /api/v1/subscription/features/           — all enabled feature keys (frontend)
  GET    /api/v1/subscription/limits/             — resource limits for current plan
  GET    /api/v1/subscription/addons/             — purchased add-on features
  POST   /api/v1/subscription/addons/             — purchase an add-on
  DELETE /api/v1/subscription/addons/<feature_key>/  — revoke an add-on
"""

from __future__ import annotations

from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response

from simorgh.apps.subscription import selectors, services
from simorgh.apps.subscription.services import SubscriptionError

from .serializers import (
    CancelSubscriptionSerializer,
    ChangePlanSerializer,
    PlanSerializer,
    PurchaseAddonSerializer,
    StartTrialSerializer,
    TenantAddonFeatureSerializer,
    TenantSubscriptionSerializer,
)


def _require_tenant(request: Request) -> Response | None:
    """Return a 400 Response if tenant is not on the request, else None."""
    if not getattr(request, "tenant", None):
        return Response(
            {"detail": "Tenant not found."}, status=status.HTTP_400_BAD_REQUEST
        )
    return None


# ---------------------------------------------------------------------------
# Subscription current state
# ---------------------------------------------------------------------------


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def subscription_detail(request: Request) -> Response:
    """GET /api/v1/subscription/

    Returns the current tenant subscription.  If none exists yet, returns 204.
    """
    err = _require_tenant(request)
    if err:
        return err

    sub = selectors.get_active_subscription(request.tenant.pk)
    if sub is None:
        return Response(status=status.HTTP_204_NO_CONTENT)

    return Response(TenantSubscriptionSerializer(sub).data)


# ---------------------------------------------------------------------------
# Plans
# ---------------------------------------------------------------------------


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def plan_list(request: Request) -> Response:
    """GET /api/v1/subscription/plans/

    Returns all publicly visible active plans.
    """
    plans = selectors.list_public_plans()
    return Response(PlanSerializer(plans, many=True).data)


# ---------------------------------------------------------------------------
# Subscription lifecycle actions
# ---------------------------------------------------------------------------


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def start_trial(request: Request) -> Response:
    """POST /api/v1/subscription/start-trial/

    Body: ``{"plan_code": "free"}``
    """
    err = _require_tenant(request)
    if err:
        return err

    serializer = StartTrialSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)

    try:
        sub = services.start_trial(
            tenant=request.tenant,
            plan_code=serializer.validated_data["plan_code"],
        )
    except SubscriptionError as exc:
        return Response({"detail": str(exc)}, status=status.HTTP_400_BAD_REQUEST)

    return Response(
        TenantSubscriptionSerializer(sub).data, status=status.HTTP_201_CREATED
    )


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def change_plan(request: Request) -> Response:
    """POST /api/v1/subscription/change-plan/

    Body: ``{"plan_code": "business", "billing_cycle": "monthly"}``
    """
    err = _require_tenant(request)
    if err:
        return err

    serializer = ChangePlanSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)

    sub = selectors.get_active_subscription(request.tenant.pk)
    if sub is None:
        # No existing subscription — create a new active one.
        try:
            sub = services.create_subscription(
                tenant=request.tenant,
                plan_code=serializer.validated_data["plan_code"],
                billing_cycle=serializer.validated_data["billing_cycle"],
                actor=request.user,
            )
        except SubscriptionError as exc:
            return Response({"detail": str(exc)}, status=status.HTTP_400_BAD_REQUEST)
    else:
        try:
            sub = services.change_plan(
                sub_id=sub.pk,
                new_plan_code=serializer.validated_data["plan_code"],
                actor=request.user,
            )
        except SubscriptionError as exc:
            return Response({"detail": str(exc)}, status=status.HTTP_400_BAD_REQUEST)

    return Response(TenantSubscriptionSerializer(sub).data)


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def cancel_subscription(request: Request) -> Response:
    """POST /api/v1/subscription/cancel/

    Body: ``{"reason": "..."}``
    """
    err = _require_tenant(request)
    if err:
        return err

    serializer = CancelSubscriptionSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)

    sub = selectors.get_active_subscription(request.tenant.pk)
    if sub is None:
        return Response(
            {"detail": "No active subscription found."},
            status=status.HTTP_404_NOT_FOUND,
        )

    try:
        sub = services.cancel_subscription(
            sub_id=sub.pk,
            reason=serializer.validated_data.get("reason", ""),
            actor=request.user,
        )
    except SubscriptionError as exc:
        return Response({"detail": str(exc)}, status=status.HTTP_400_BAD_REQUEST)

    return Response(TenantSubscriptionSerializer(sub).data)


# ---------------------------------------------------------------------------
# Features
# ---------------------------------------------------------------------------


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def feature_list(request: Request) -> Response:
    """GET /api/v1/subscription/features/

    Returns all enabled feature keys for the current tenant.
    Used by the frontend manifest to gate navigation items.
    """
    err = _require_tenant(request)
    if err:
        return err

    enabled = selectors.get_all_enabled_features(request.tenant.pk)
    return Response({"features": sorted(enabled)})


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def limits_detail(request: Request) -> Response:
    """GET /api/v1/subscription/limits/

    Returns the resource limits for the current tenant's plan.
    """
    err = _require_tenant(request)
    if err:
        return err

    return Response(selectors.get_plan_limits(request.tenant.pk))


# ---------------------------------------------------------------------------
# Add-on features
# ---------------------------------------------------------------------------


@api_view(["GET", "POST"])
@permission_classes([IsAuthenticated])
def addon_list(request: Request) -> Response:
    """GET  /api/v1/subscription/addons/  — list purchased add-ons
    POST /api/v1/subscription/addons/  — purchase an add-on
    """
    err = _require_tenant(request)
    if err:
        return err

    if request.method == "GET":
        addons = selectors.get_addons(request.tenant.pk)
        return Response(TenantAddonFeatureSerializer(addons, many=True).data)

    # POST
    serializer = PurchaseAddonSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)

    addon = services.purchase_addon(
        tenant=request.tenant,
        feature_key=serializer.validated_data["feature_key"],
        actor=request.user,
        expires_at=serializer.validated_data.get("expires_at"),
        price_paid=serializer.validated_data.get("price_paid", 0),
    )
    return Response(
        TenantAddonFeatureSerializer(addon).data, status=status.HTTP_201_CREATED
    )


@api_view(["DELETE"])
@permission_classes([IsAuthenticated])
def addon_detail(request: Request, feature_key: str) -> Response:
    """DELETE /api/v1/subscription/addons/<feature_key>/"""
    err = _require_tenant(request)
    if err:
        return err

    services.revoke_addon(
        tenant=request.tenant,
        feature_key=feature_key,
        actor=request.user,
    )
    return Response(status=status.HTTP_204_NO_CONTENT)
