from datetime import datetime, timezone

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session

from app.api.deps import get_current_user
from app.core.config import get_settings
from app.core.database import get_db
from app.models import Plan, UpgradeRequest, User
from app.schemas.billing import (
    BillingMeOut,
    PlanOut,
    StripeCheckoutIn,
    StripeCheckoutOut,
    UpgradeRequestIn,
    UpgradeRequestOut,
)
from app.services.entitlements import (
    ensure_user_subscription,
    get_entitlements,
    get_plan_for_user,
    get_usage,
)

router = APIRouter(prefix="/billing", tags=["billing"])


@router.get("/me", response_model=BillingMeOut)
def billing_me(user: User = Depends(get_current_user), db: Session = Depends(get_db)):
    ensure_user_subscription(db, user)
    plan = get_plan_for_user(db, user)
    settings = get_settings()
    return BillingMeOut(
        plan=PlanOut.model_validate(plan),
        status="active",
        entitlements=get_entitlements(db, user),
        usage=get_usage(db, user),
        is_admin=user.is_admin,
        stripe_enabled=bool(settings.stripe_secret_key),
    )


@router.post("/upgrade-request", response_model=UpgradeRequestOut)
def request_upgrade(
    payload: UpgradeRequestIn,
    user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    plan = db.query(Plan).filter(Plan.key == payload.plan_key, Plan.is_active.is_(True)).first()
    if not plan:
        raise HTTPException(404, "Plan no encontrado")
    if plan.key == "free":
        raise HTTPException(400, "El plan Gratis no requiere solicitud")
    existing = (
        db.query(UpgradeRequest)
        .filter(
            UpgradeRequest.user_id == user.id,
            UpgradeRequest.plan_id == plan.id,
            UpgradeRequest.status == "pending",
        )
        .first()
    )
    if existing:
        return UpgradeRequestOut(
            id=existing.id,
            user_id=existing.user_id,
            plan_id=existing.plan_id,
            status=existing.status,
            message=existing.message,
            admin_note=existing.admin_note,
            created_at=existing.created_at,
            resolved_at=existing.resolved_at,
            user_email=user.email,
            plan_key=plan.key,
            plan_name=plan.name,
        )
    req = UpgradeRequest(
        user_id=user.id,
        plan_id=plan.id,
        status="pending",
        message=payload.message or "",
    )
    db.add(req)
    db.commit()
    db.refresh(req)
    return UpgradeRequestOut(
        id=req.id,
        user_id=req.user_id,
        plan_id=req.plan_id,
        status=req.status,
        message=req.message,
        admin_note=req.admin_note,
        created_at=req.created_at,
        resolved_at=req.resolved_at,
        user_email=user.email,
        plan_key=plan.key,
        plan_name=plan.name,
    )


@router.post("/stripe/checkout", response_model=StripeCheckoutOut)
def stripe_checkout(
    payload: StripeCheckoutIn,
    user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """Stub Stripe: si no hay STRIPE_SECRET_KEY, indica solicitar upgrade manual."""
    settings = get_settings()
    plan = db.query(Plan).filter(Plan.key == payload.plan_key).first()
    if not plan:
        raise HTTPException(404, "Plan no encontrado")
    if not settings.stripe_secret_key:
        return StripeCheckoutOut(
            ok=False,
            mode="stub",
            detail=(
                "Stripe no configurado. Usa «Solicitar upgrade» y el admin activará tu plan. "
                "Cuando configures STRIPE_SECRET_KEY + stripe_price_id en el plan, este endpoint creará checkout."
            ),
            checkout_url=None,
        )
    # Placeholder listo para integración real
    return StripeCheckoutOut(
        ok=False,
        mode="stripe",
        detail=(
            "Stripe keys presentes pero checkout aún no cableado a SDK. "
            f"Plan {plan.key} price_id={plan.stripe_price_id or '—'}. Usa upgrade-request mientras tanto."
        ),
        checkout_url=None,
    )


@router.post("/stripe/webhook")
def stripe_webhook():
    settings = get_settings()
    if not settings.stripe_secret_key:
        return {"ok": True, "mode": "stub", "detail": "Webhook ignorado (Stripe no configurado)"}
    return {"ok": True, "mode": "stripe", "detail": "Webhook recibido (handler pendiente de eventos)"}
