"""Stripe payment and subscription routes."""

from typing import Annotated, Any

from backend.config import PLATFORM_DOMAIN, logger, stripe
from backend.deps import ensure_supabase, limiter, verify_user
from backend.models import UrlResponse
from backend.pricing import get_stripe_price_id, get_trial_days, is_trial_enabled_for_plan
from fastapi import APIRouter, Depends, HTTPException, Request
from pydantic import BaseModel

router = APIRouter()


class CheckoutRequest(BaseModel):
    """Request model for creating Stripe checkout sessions."""

    tier: str
    billing_cycle: str = "monthly"  # monthly or yearly


@router.post("/stripe/checkout", response_model=UrlResponse)
@limiter.limit("5/minute")
async def create_checkout_session(
    request: Request,  # noqa: ARG001
    payload: CheckoutRequest,
    user: Annotated[dict, Depends(verify_user)],
) -> dict[str, Any]:
    """Create Stripe checkout session for subscription."""
    if not stripe.api_key:
        raise HTTPException(status_code=500, detail="Stripe not configured")

    # Get price ID from config
    price_id = get_stripe_price_id(payload.tier, payload.billing_cycle)
    if not price_id:
        raise HTTPException(status_code=400, detail=f"No price found for {payload.tier} ({payload.billing_cycle})")

    sb = ensure_supabase()
    result = sb.table("accounts").select("stripe_customer_id").eq("id", user["account_id"]).single().execute()
    if result.data and result.data.get("stripe_customer_id"):
        customer_id = result.data["stripe_customer_id"]
    else:
        customer = stripe.Customer.create(email=user["email"], metadata={"supabase_user_id": user["account_id"]})
        customer_id = customer.id
        sb.table("accounts").update({"stripe_customer_id": customer_id}).eq("id", user["account_id"]).execute()

    # Check if customer already has an active subscription
    subscriptions = stripe.Subscription.list(customer=customer_id, status="all", limit=10)
    for sub in subscriptions.data:
        if sub.status in ["active", "trialing"]:
            # Customer already has a subscription - they should use the portal to manage it
            logger.warning(
                "Customer %s already has an active subscription %s, redirecting to portal", customer_id, sub.id
            )
            # Create a portal session instead
            portal_session = stripe.billing_portal.Session.create(
                customer=customer_id, return_url=f"https://app.{PLATFORM_DOMAIN}/dashboard/billing"
            )
            return {"url": portal_session.url}

    checkout_params = {
        "line_items": [{"price": price_id, "quantity": 1}],
        "mode": "subscription",
        "success_url": f"https://app.{PLATFORM_DOMAIN}/dashboard?success=true&session_id={{CHECKOUT_SESSION_ID}}",
        "cancel_url": f"https://app.{PLATFORM_DOMAIN}/dashboard/billing/upgrade?cancelled=true",
        "allow_promotion_codes": True,
        "billing_address_collection": "required",
        "subscription_data": {
            "metadata": {
                "tier": payload.tier,
                "billing_cycle": payload.billing_cycle,
                "supabase_user_id": user["account_id"],
            }
        },
    }

    # Add trial period if enabled for this plan
    if is_trial_enabled_for_plan(payload.tier):
        checkout_params["subscription_data"]["trial_period_days"] = get_trial_days()

    checkout_params["customer"] = customer_id

    try:
        session = stripe.checkout.Session.create(**checkout_params)
    except Exception as e:
        logger.exception("Error creating checkout session")
        raise HTTPException(status_code=500, detail="Failed to create checkout session") from e

    return {"url": session.url}


@router.post("/stripe/portal", response_model=UrlResponse)
@limiter.limit("10/minute")
async def create_portal_session(request: Request, user: Annotated[dict, Depends(verify_user)]) -> dict[str, Any]:  # noqa: ARG001
    """Create Stripe customer portal session for subscription management."""
    if not stripe.api_key:
        raise HTTPException(status_code=500, detail="Stripe not configured")
    sb = ensure_supabase()

    # Stripe customer ID is stored on the accounts table
    result = sb.table("accounts").select("stripe_customer_id").eq("id", user["account_id"]).single().execute()
    if not result.data or not result.data.get("stripe_customer_id"):
        raise HTTPException(status_code=404, detail="No Stripe customer found")

    try:
        session = stripe.billing_portal.Session.create(
            customer=result.data["stripe_customer_id"],
            return_url=f"https://app.{PLATFORM_DOMAIN}/dashboard/billing?return=true",
        )
    except Exception as e:
        logger.exception("Error creating portal session")
        raise HTTPException(status_code=500, detail="Failed to create portal session") from e

    return {"url": session.url}
