from typing import Any

import httpx
from fastapi import APIRouter, Depends, HTTPException, Query, status
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession
from sqlmodel import select

from app.auth.tenant import get_current_restaurant, get_tenant_session
from app.config import get_settings
from app.models.restaurant import Restaurant
from app.payments.mollie import PaymentNotConfiguredError, get_payment, list_payments

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


class PaymentStatusResponse(BaseModel):
    """Normalized payment status returned by the payment status lookup endpoint."""

    payment_id: str
    status: str
    amount: str | None = None
    currency: str | None = None
    description: str | None = None
    created_at: str | None = None


_NOT_CONFIGURED: dict[str, str] = {
    "status": "configuration_required",
    "provider": "mollie",
    "code": "payment_provider_not_configured",
    "action": "Set MOLLIE_API_KEY",
}

_PLAN_DETAILS: dict[str, dict[str, Any]] = {
    "free": {
        "name": "Free",
        "price_monthly_cents": 0,
        "currency": "EUR",
        "features": [
            "1 AI agent (FAQ)",
            "Up to 50 reservations/month",
            "Website widget",
            "Basic analytics",
        ],
    },
    "starter": {
        "name": "Starter",
        "price_monthly_cents": 2900,
        "currency": "EUR",
        "features": [
            "3 AI agents (FAQ, Reservation, Takeaway)",
            "Up to 500 reservations/month",
            "All channels (WhatsApp, Instagram, Telegram)",
            "Advanced analytics",
            "Priority support",
        ],
    },
    "pro": {
        "name": "Pro",
        "price_monthly_cents": 7900,
        "currency": "EUR",
        "features": [
            "Unlimited AI agents",
            "Unlimited reservations",
            "All channels",
            "Custom AI training",
            "Dedicated support",
            "White-label widget",
        ],
    },
}

_UPGRADE_MAP: dict[str, str] = {
    "free": "starter",
    "starter": "pro",
}


@router.get("/")
async def get_billing(
    restaurant: Restaurant = Depends(get_current_restaurant),
) -> dict[str, Any]:
    settings = get_settings()
    configured = bool(settings.MOLLIE_API_KEY)
    if not configured:
        return {
            "status": "configuration_required",
            "provider": "mollie",
            "configured": configured,
            "code": "payment_provider_not_configured",
            "action": "Set MOLLIE_API_KEY",
        }

    return {
        "status": "ready",
        "provider": "mollie",
        "configured": configured,
        "restaurant_id": restaurant.id,
    }


@router.get("/subscription")
async def get_subscription(
    restaurant: Restaurant = Depends(get_current_restaurant),
) -> dict[str, Any]:
    """Return current subscription plan and upgrade options."""
    settings = get_settings()
    if not settings.MOLLIE_API_KEY:
        return {**_NOT_CONFIGURED, "plan": None, "checkout_url": None}

    plan_id: str = getattr(restaurant, "subscription_plan", None) or "free"
    plan = _PLAN_DETAILS.get(plan_id, _PLAN_DETAILS["free"])
    upgrade_plan_id = _UPGRADE_MAP.get(plan_id)
    upgrade_plan = _PLAN_DETAILS.get(upgrade_plan_id, {}) if upgrade_plan_id else {}

    return {
        "status": "active",
        "plan_id": plan_id,
        "plan_name": plan["name"],
        "price_monthly_cents": plan["price_monthly_cents"],
        "currency": plan["currency"],
        "features": plan["features"],
        "upgrade_plan_id": upgrade_plan_id,
        "upgrade_plan_name": upgrade_plan.get("name"),
        "upgrade_price_monthly_cents": upgrade_plan.get("price_monthly_cents"),
        # checkout_url is populated once Mollie subscription links are configured
        "checkout_url": None,
    }


@router.get("/invoices")
async def get_invoices(
    restaurant: Restaurant = Depends(get_current_restaurant),
    page: int = Query(1, ge=1),
    per_page: int = Query(10, ge=1, le=50),
) -> dict[str, Any]:
    """Return paginated invoice history from Mollie payments."""
    _ = restaurant
    settings = get_settings()
    if not settings.MOLLIE_API_KEY:
        return {
            **_NOT_CONFIGURED,
            "invoices": [],
            "total": 0,
            "page": page,
            "per_page": per_page,
            "total_pages": 0,
        }

    try:
        result = await list_payments(limit=per_page)
        invoices = [
            {
                "id": p["id"],
                "description": p.get("description", "Invoice"),
                "amount": p.get("amount", {}).get("value", "0.00"),
                "currency": p.get("amount", {}).get("currency", "EUR"),
                "status": p.get("status", "unknown"),
                "created_at": p.get("createdAt"),
                "pdf_url": p.get("_links", {}).get("settlement", {}).get("href"),
            }
            for p in result.get("payments", [])
        ]
        total = result.get("count", len(invoices))
        return {
            "invoices": invoices,
            "total": total,
            "page": page,
            "per_page": per_page,
            "total_pages": max(1, -(-total // per_page)) if total > 0 else 0,
        }
    except (PaymentNotConfiguredError, Exception):
        return {
            "invoices": [],
            "total": 0,
            "page": page,
            "per_page": per_page,
            "total_pages": 0,
        }


@router.get("/payment/{payment_id}/status", response_model=PaymentStatusResponse)
async def get_payment_status(
    payment_id: str,
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> PaymentStatusResponse:
    """Return the current status of a Mollie payment."""
    # Enforce tenant ownership: verify the payment belongs to this restaurant
    from app.models.order import Order

    ownership_result = await session.execute(
        select(Order).where(
            Order.mollie_payment_id == payment_id,
            Order.restaurant_id == restaurant.id,
        )
    )
    if ownership_result.scalar_one_or_none() is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Payment not found",
        )
    settings = get_settings()
    if not settings.MOLLIE_API_KEY:
        raise HTTPException(
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            detail="Payment provider not configured",
        )

    try:
        payment_data = await get_payment(payment_id)
    except PaymentNotConfiguredError as err:
        raise HTTPException(
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            detail="Payment provider not configured",
        ) from err
    except httpx.HTTPStatusError as exc:
        if exc.response.status_code == 404:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Payment not found",
            ) from exc
        raise HTTPException(
            status_code=status.HTTP_502_BAD_GATEWAY,
            detail="Payment provider error",
        ) from exc
    except Exception as err:
        raise HTTPException(
            status_code=status.HTTP_502_BAD_GATEWAY,
            detail="Payment provider error",
        ) from err

    return PaymentStatusResponse(
        payment_id=payment_data.get("id", payment_id),
        status=payment_data.get("status", "unknown"),
        amount=payment_data.get("amount", {}).get("value"),
        currency=payment_data.get("amount", {}).get("currency"),
        description=payment_data.get("description"),
        created_at=payment_data.get("createdAt"),
    )
