# app/modules/billing/routes/api/vendor_checkout.py
"""
Vendor checkout and subscription management endpoints.

Provides:
- Stripe checkout session creation
- Stripe portal session creation
- Subscription cancellation and reactivation
- Upcoming invoice preview
- Tier changes (upgrade/downgrade)

All routes require module access control for the 'billing' module.
"""

import logging

from fastapi import APIRouter, Depends
from pydantic import BaseModel
from sqlalchemy.orm import Session

from app.api.deps import get_current_vendor_api, require_module_access
from app.core.config import settings
from app.core.database import get_db
from app.modules.billing.services import billing_service, subscription_service
from app.modules.enums import FrontendType
from models.schema.auth import UserContext

vendor_checkout_router = APIRouter(
    dependencies=[Depends(require_module_access("billing", FrontendType.VENDOR))],
)
logger = logging.getLogger(__name__)


# ============================================================================
# Schemas
# ============================================================================


class CheckoutRequest(BaseModel):
    """Request to create a checkout session."""

    tier_code: str
    is_annual: bool = False


class CheckoutResponse(BaseModel):
    """Checkout session response."""

    checkout_url: str
    session_id: str


class PortalResponse(BaseModel):
    """Customer portal session response."""

    portal_url: str


class CancelRequest(BaseModel):
    """Request to cancel subscription."""

    reason: str | None = None
    immediately: bool = False


class CancelResponse(BaseModel):
    """Cancellation response."""

    message: str
    effective_date: str


class UpcomingInvoiceResponse(BaseModel):
    """Upcoming invoice preview."""

    amount_due_cents: int
    currency: str
    next_payment_date: str | None = None
    line_items: list[dict] = []


class ChangeTierRequest(BaseModel):
    """Request to change subscription tier."""

    tier_code: str
    is_annual: bool = False


class ChangeTierResponse(BaseModel):
    """Response for tier change."""

    message: str
    new_tier: str
    effective_immediately: bool


# ============================================================================
# Endpoints
# ============================================================================


@vendor_checkout_router.post("/checkout", response_model=CheckoutResponse)
def create_checkout_session(
    request: CheckoutRequest,
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """Create a Stripe checkout session for subscription."""
    vendor_id = current_user.token_vendor_id
    vendor = billing_service.get_vendor(db, vendor_id)

    # Build URLs
    base_url = f"https://{settings.platform_domain}"
    success_url = f"{base_url}/vendor/{vendor.vendor_code}/billing?success=true"
    cancel_url = f"{base_url}/vendor/{vendor.vendor_code}/billing?cancelled=true"

    result = billing_service.create_checkout_session(
        db=db,
        vendor_id=vendor_id,
        tier_code=request.tier_code,
        is_annual=request.is_annual,
        success_url=success_url,
        cancel_url=cancel_url,
    )
    db.commit()

    return CheckoutResponse(checkout_url=result["checkout_url"], session_id=result["session_id"])


@vendor_checkout_router.post("/portal", response_model=PortalResponse)
def create_portal_session(
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """Create a Stripe customer portal session."""
    vendor_id = current_user.token_vendor_id
    vendor = billing_service.get_vendor(db, vendor_id)
    return_url = f"https://{settings.platform_domain}/vendor/{vendor.vendor_code}/billing"

    result = billing_service.create_portal_session(db, vendor_id, return_url)

    return PortalResponse(portal_url=result["portal_url"])


@vendor_checkout_router.post("/cancel", response_model=CancelResponse)
def cancel_subscription(
    request: CancelRequest,
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """Cancel subscription."""
    vendor_id = current_user.token_vendor_id

    result = billing_service.cancel_subscription(
        db=db,
        vendor_id=vendor_id,
        reason=request.reason,
        immediately=request.immediately,
    )
    db.commit()

    return CancelResponse(
        message=result["message"],
        effective_date=result["effective_date"],
    )


@vendor_checkout_router.post("/reactivate")
def reactivate_subscription(
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """Reactivate a cancelled subscription."""
    vendor_id = current_user.token_vendor_id

    result = billing_service.reactivate_subscription(db, vendor_id)
    db.commit()

    return result


@vendor_checkout_router.get("/upcoming-invoice", response_model=UpcomingInvoiceResponse)
def get_upcoming_invoice(
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """Preview the upcoming invoice."""
    vendor_id = current_user.token_vendor_id

    result = billing_service.get_upcoming_invoice(db, vendor_id)

    return UpcomingInvoiceResponse(
        amount_due_cents=result.get("amount_due_cents", 0),
        currency=result.get("currency", "EUR"),
        next_payment_date=result.get("next_payment_date"),
        line_items=result.get("line_items", []),
    )


@vendor_checkout_router.post("/change-tier", response_model=ChangeTierResponse)
def change_tier(
    request: ChangeTierRequest,
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """Change subscription tier (upgrade/downgrade)."""
    vendor_id = current_user.token_vendor_id

    result = billing_service.change_tier(
        db=db,
        vendor_id=vendor_id,
        new_tier_code=request.tier_code,
        is_annual=request.is_annual,
    )
    db.commit()

    return ChangeTierResponse(
        message=result["message"],
        new_tier=result["new_tier"],
        effective_immediately=result["effective_immediately"],
    )
