# app/modules/billing/routes/admin.py
"""
Billing module admin routes.

This module wraps the existing admin subscription routes and adds
module-based access control. The actual route implementations remain
in app/api/v1/admin/subscriptions.py for now, but are accessed through
this module-aware router.

Future: Move all route implementations here for full module isolation.
"""

import logging

from fastapi import APIRouter, Depends, Path, Query
from sqlalchemy.orm import Session

from app.api.deps import get_current_admin_api, require_module_access
from app.core.database import get_db
from app.modules.billing.services import admin_subscription_service, subscription_service
from app.modules.enums import FrontendType
from app.modules.tenancy.models import User
from app.modules.billing.schemas import (
    BillingHistoryListResponse,
    BillingHistoryWithVendor,
    SubscriptionStatsResponse,
    SubscriptionTierCreate,
    SubscriptionTierListResponse,
    SubscriptionTierResponse,
    SubscriptionTierUpdate,
    VendorSubscriptionCreate,
    VendorSubscriptionListResponse,
    VendorSubscriptionResponse,
    VendorSubscriptionUpdate,
    VendorSubscriptionWithVendor,
)

logger = logging.getLogger(__name__)

# Admin router with module access control
admin_router = APIRouter(
    prefix="/subscriptions",
    dependencies=[Depends(require_module_access("billing", FrontendType.ADMIN))],
)


# ============================================================================
# Subscription Tier Endpoints
# ============================================================================


@admin_router.get("/tiers", response_model=SubscriptionTierListResponse)
def list_subscription_tiers(
    include_inactive: bool = Query(False, description="Include inactive tiers"),
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """
    List all subscription tiers.

    Returns all tiers with their limits, features, and Stripe configuration.
    """
    tiers = admin_subscription_service.get_tiers(db, include_inactive=include_inactive)

    return SubscriptionTierListResponse(
        tiers=[SubscriptionTierResponse.model_validate(t) for t in tiers],
        total=len(tiers),
    )


@admin_router.get("/tiers/{tier_code}", response_model=SubscriptionTierResponse)
def get_subscription_tier(
    tier_code: str = Path(..., description="Tier code"),
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """Get a specific subscription tier by code."""
    tier = admin_subscription_service.get_tier_by_code(db, tier_code)
    return SubscriptionTierResponse.model_validate(tier)


@admin_router.post("/tiers", response_model=SubscriptionTierResponse, status_code=201)
def create_subscription_tier(
    tier_data: SubscriptionTierCreate,
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """Create a new subscription tier."""
    tier = admin_subscription_service.create_tier(db, tier_data.model_dump())
    db.commit()
    db.refresh(tier)
    return SubscriptionTierResponse.model_validate(tier)


@admin_router.patch("/tiers/{tier_code}", response_model=SubscriptionTierResponse)
def update_subscription_tier(
    tier_data: SubscriptionTierUpdate,
    tier_code: str = Path(..., description="Tier code"),
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """Update a subscription tier."""
    update_data = tier_data.model_dump(exclude_unset=True)
    tier = admin_subscription_service.update_tier(db, tier_code, update_data)
    db.commit()
    db.refresh(tier)
    return SubscriptionTierResponse.model_validate(tier)


@admin_router.delete("/tiers/{tier_code}", status_code=204)
def delete_subscription_tier(
    tier_code: str = Path(..., description="Tier code"),
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """
    Soft-delete a subscription tier.

    Sets is_active=False rather than deleting to preserve history.
    """
    admin_subscription_service.deactivate_tier(db, tier_code)
    db.commit()


# ============================================================================
# Vendor Subscription Endpoints
# ============================================================================


@admin_router.get("", response_model=VendorSubscriptionListResponse)
def list_vendor_subscriptions(
    page: int = Query(1, ge=1),
    per_page: int = Query(20, ge=1, le=100),
    status: str | None = Query(None, description="Filter by status"),
    tier: str | None = Query(None, description="Filter by tier"),
    search: str | None = Query(None, description="Search vendor name"),
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """
    List all vendor subscriptions with filtering.

    Includes vendor information for each subscription.
    """
    data = admin_subscription_service.list_subscriptions(
        db, page=page, per_page=per_page, status=status, tier=tier, search=search
    )

    subscriptions = []
    for sub, vendor in data["results"]:
        sub_dict = {
            **VendorSubscriptionResponse.model_validate(sub).model_dump(),
            "vendor_name": vendor.name,
            "vendor_code": vendor.subdomain,
        }
        subscriptions.append(VendorSubscriptionWithVendor(**sub_dict))

    return VendorSubscriptionListResponse(
        subscriptions=subscriptions,
        total=data["total"],
        page=data["page"],
        per_page=data["per_page"],
        pages=data["pages"],
    )


# ============================================================================
# Statistics Endpoints
# ============================================================================


@admin_router.get("/stats", response_model=SubscriptionStatsResponse)
def get_subscription_stats(
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """Get subscription statistics for admin dashboard."""
    stats = admin_subscription_service.get_stats(db)
    return SubscriptionStatsResponse(**stats)


# ============================================================================
# Billing History Endpoints
# ============================================================================


@admin_router.get("/billing/history", response_model=BillingHistoryListResponse)
def list_billing_history(
    page: int = Query(1, ge=1),
    per_page: int = Query(20, ge=1, le=100),
    vendor_id: int | None = Query(None, description="Filter by vendor"),
    status: str | None = Query(None, description="Filter by status"),
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """List billing history (invoices) across all vendors."""
    data = admin_subscription_service.list_billing_history(
        db, page=page, per_page=per_page, vendor_id=vendor_id, status=status
    )

    invoices = []
    for invoice, vendor in data["results"]:
        invoice_dict = {
            "id": invoice.id,
            "vendor_id": invoice.vendor_id,
            "stripe_invoice_id": invoice.stripe_invoice_id,
            "invoice_number": invoice.invoice_number,
            "invoice_date": invoice.invoice_date,
            "due_date": invoice.due_date,
            "subtotal_cents": invoice.subtotal_cents,
            "tax_cents": invoice.tax_cents,
            "total_cents": invoice.total_cents,
            "amount_paid_cents": invoice.amount_paid_cents,
            "currency": invoice.currency,
            "status": invoice.status,
            "invoice_pdf_url": invoice.invoice_pdf_url,
            "hosted_invoice_url": invoice.hosted_invoice_url,
            "description": invoice.description,
            "created_at": invoice.created_at,
            "vendor_name": vendor.name,
            "vendor_code": vendor.subdomain,
        }
        invoices.append(BillingHistoryWithVendor(**invoice_dict))

    return BillingHistoryListResponse(
        invoices=invoices,
        total=data["total"],
        page=data["page"],
        per_page=data["per_page"],
        pages=data["pages"],
    )


# ============================================================================
# Vendor Subscription Detail Endpoints
# ============================================================================


@admin_router.post("/{vendor_id}", response_model=VendorSubscriptionWithVendor, status_code=201)
def create_vendor_subscription(
    create_data: VendorSubscriptionCreate,
    vendor_id: int = Path(..., description="Vendor ID"),
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """
    Create a subscription for a vendor.

    Creates a new subscription with the specified tier and status.
    Defaults to Essential tier with trial status.
    """
    # Verify vendor exists
    vendor = admin_subscription_service.get_vendor(db, vendor_id)

    # Create subscription using the subscription service
    sub = subscription_service.get_or_create_subscription(
        db,
        vendor_id=vendor_id,
        tier=create_data.tier,
        trial_days=create_data.trial_days,
    )

    # Update status if not trial
    if create_data.status != "trial":
        sub.status = create_data.status

    sub.is_annual = create_data.is_annual

    db.commit()
    db.refresh(sub)

    # Get usage counts
    usage = admin_subscription_service.get_vendor_usage_counts(db, vendor_id)

    logger.info(f"Admin created subscription for vendor {vendor_id}: tier={create_data.tier}")

    return VendorSubscriptionWithVendor(
        **VendorSubscriptionResponse.model_validate(sub).model_dump(),
        vendor_name=vendor.name,
        vendor_code=vendor.subdomain,
        products_count=usage["products_count"],
        team_count=usage["team_count"],
    )


@admin_router.get("/{vendor_id}", response_model=VendorSubscriptionWithVendor)
def get_vendor_subscription(
    vendor_id: int = Path(..., description="Vendor ID"),
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """Get subscription details for a specific vendor."""
    sub, vendor = admin_subscription_service.get_subscription(db, vendor_id)

    # Get usage counts
    usage = admin_subscription_service.get_vendor_usage_counts(db, vendor_id)

    return VendorSubscriptionWithVendor(
        **VendorSubscriptionResponse.model_validate(sub).model_dump(),
        vendor_name=vendor.name,
        vendor_code=vendor.subdomain,
        products_count=usage["products_count"],
        team_count=usage["team_count"],
    )


@admin_router.patch("/{vendor_id}", response_model=VendorSubscriptionWithVendor)
def update_vendor_subscription(
    update_data: VendorSubscriptionUpdate,
    vendor_id: int = Path(..., description="Vendor ID"),
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db),
):
    """
    Update a vendor's subscription.

    Allows admins to:
    - Change tier
    - Update status
    - Set custom limit overrides
    - Extend trial period
    """
    data = update_data.model_dump(exclude_unset=True)
    sub, vendor = admin_subscription_service.update_subscription(db, vendor_id, data)
    db.commit()
    db.refresh(sub)

    # Get usage counts
    usage = admin_subscription_service.get_vendor_usage_counts(db, vendor_id)

    return VendorSubscriptionWithVendor(
        **VendorSubscriptionResponse.model_validate(sub).model_dump(),
        vendor_name=vendor.name,
        vendor_code=vendor.subdomain,
        products_count=usage["products_count"],
        team_count=usage["team_count"],
    )


# ============================================================================
# Aggregate Feature Management Routes
# ============================================================================
# Include the features router to aggregate all billing-related admin routes
from app.modules.billing.routes.api.admin_features import admin_features_router

admin_router.include_router(admin_features_router, tags=["admin-features"])
