"""
Admin billing endpoints for enrichment revenue and cost tracking.

Provides financial visibility into:
- Overall billing summary (revenue, cost, margin)
- Per-customer usage and billing data
- Invoice generation
- CSV export for accounting/analytics
"""

from __future__ import annotations

import csv
import io
import logging
from datetime import datetime, timedelta, timezone
from decimal import Decimal
from typing import Any, Dict, List

from fastapi import APIRouter, Depends, HTTPException, Response
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession

from ....auth_security import require_admin, AdminContext
from ....db import get_session
from ....models import Account, EnrichmentUsage

logger = logging.getLogger(__name__)

router = APIRouter()


def _now_utc() -> datetime:
    return datetime.now(timezone.utc)


# ====================================================================
# Billing Summary
# ====================================================================


@router.get("/summary")
async def get_billing_summary(
    days: int = 30,
    _admin: AdminContext = Depends(require_admin),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, Any]:
    """
    Return overall billing summary for the specified time period.
    """
    since = _now_utc() - timedelta(days=days)

    # Aggregate stats
    stmt = select(
        func.count(EnrichmentUsage.id),
        func.coalesce(func.sum(EnrichmentUsage.credits_debited), 0),
        func.coalesce(func.sum(EnrichmentUsage.cost_usd), Decimal("0")),
        func.coalesce(func.sum(EnrichmentUsage.price_usd), Decimal("0")),
        func.coalesce(func.sum(EnrichmentUsage.margin_usd), Decimal("0")),
        func.coalesce(func.sum(EnrichmentUsage.records_written), 0),
        func.count(func.distinct(EnrichmentUsage.account_id)),
    ).where(EnrichmentUsage.created_at >= since)

    result = await db.execute(stmt)
    row = result.first()

    total_operations = int(row[0] or 0)
    total_credits = int(row[1] or 0)
    total_cost = float(row[2] or Decimal("0"))
    total_revenue = float(row[3] or Decimal("0"))
    total_margin = float(row[4] or Decimal("0"))
    total_records_enriched = int(row[5] or 0)
    unique_customers = int(row[6] or 0)

    # Unbilled amount
    unbilled_stmt = select(
        func.coalesce(func.sum(EnrichmentUsage.price_usd), Decimal("0"))
    ).where(
        EnrichmentUsage.created_at >= since,
        EnrichmentUsage.billed.is_(False),
    )
    unbilled_result = await db.execute(unbilled_stmt)
    unbilled_amount = float(unbilled_result.scalar() or Decimal("0"))

    margin_pct = (total_margin / total_revenue * 100) if total_revenue > 0 else 0.0

    return {
        "period_days": days,
        "total_operations": total_operations,
        "total_credits": total_credits,
        "total_cost_usd": total_cost,
        "total_revenue_usd": total_revenue,
        "total_margin_usd": total_margin,
        "margin_percent": round(margin_pct, 2),
        "records_enriched": total_records_enriched,
        "unique_customers": unique_customers,
        "unbilled_amount_usd": unbilled_amount,
    }


# ====================================================================
# Customer Breakdown
# ====================================================================


@router.get("/customers")
async def get_customer_billing(
    days: int = 30,
    limit: int = 100,
    _admin: AdminContext = Depends(require_admin),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, List[Dict[str, Any]]]:
    """
    Return per-customer billing breakdown.
    """
    since = _now_utc() - timedelta(days=days)

    stmt = (
        select(
            EnrichmentUsage.account_id,
            Account.name,
            func.count(EnrichmentUsage.id).label("operations"),
            func.coalesce(func.sum(EnrichmentUsage.credits_debited), 0).label(
                "credits"
            ),
            func.coalesce(func.sum(EnrichmentUsage.cost_usd), Decimal("0")).label(
                "cost"
            ),
            func.coalesce(func.sum(EnrichmentUsage.price_usd), Decimal("0")).label(
                "revenue"
            ),
            func.coalesce(func.sum(EnrichmentUsage.margin_usd), Decimal("0")).label(
                "margin"
            ),
            func.coalesce(func.sum(EnrichmentUsage.records_written), 0).label(
                "records_enriched"
            ),
        )
        .join(Account, EnrichmentUsage.account_id == Account.id)
        .where(EnrichmentUsage.created_at >= since)
        .group_by(EnrichmentUsage.account_id, Account.name)
        .order_by(func.sum(EnrichmentUsage.price_usd).desc())
        .limit(limit)
    )

    result = await db.execute(stmt)
    rows = result.all()

    customers = []
    for row in rows:
        revenue = float(row.revenue or Decimal("0"))
        cost = float(row.cost or Decimal("0"))
        margin = float(row.margin or Decimal("0"))
        margin_pct = (margin / revenue * 100) if revenue > 0 else 0.0

        customers.append(
            {
                "account_id": row.account_id,
                "account_name": row.name or "Unknown",
                "operations": int(row.operations or 0),
                "credits": int(row.credits or 0),
                "cost_usd": cost,
                "revenue_usd": revenue,
                "margin_usd": margin,
                "margin_percent": round(margin_pct, 2),
                "records_enriched": int(row.records_enriched or 0),
            }
        )

    return {"customers": customers}


# ====================================================================
# Invoice Generation (Placeholder)
# ====================================================================


@router.post("/invoice/{account_id}")
async def generate_invoice(
    account_id: str,
    _admin: AdminContext = Depends(require_admin),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, Any]:
    """
    Generate an invoice for unbilled usage for a specific account.

    TODO: Integrate with Stripe invoice API to actually create the invoice.
    For now, this just returns the unbilled amount.
    """
    # Get unbilled usage for this account
    stmt = select(
        func.coalesce(func.sum(EnrichmentUsage.price_usd), Decimal("0")),
        func.count(EnrichmentUsage.id),
    ).where(
        EnrichmentUsage.account_id == account_id,
        EnrichmentUsage.billed.is_(False),
    )

    result = await db.execute(stmt)
    row = result.first()

    unbilled_amount = float(row[0] or Decimal("0"))
    unbilled_count = int(row[1] or 0)

    if unbilled_amount <= 0:
        raise HTTPException(
            status_code=400,
            detail="No unbilled charges for this account",
        )

    # TODO: Create actual Stripe invoice here
    # For now, return summary
    logger.info(
        "Invoice request for account %s: $%.2f (%d operations)",
        account_id,
        unbilled_amount,
        unbilled_count,
    )

    return {
        "account_id": account_id,
        "unbilled_amount_usd": unbilled_amount,
        "unbilled_operations": unbilled_count,
        "invoice_created": False,
        "message": "Invoice generation not yet implemented - Stripe integration pending",
    }


# ====================================================================
# CSV Export
# ====================================================================


@router.get("/export")
async def export_billing_csv(
    days: int = 30,
    _admin: AdminContext = Depends(require_admin),
    db: AsyncSession = Depends(get_session),
) -> Response:
    """
    Export billing data as CSV for accounting/analytics.
    """
    since = _now_utc() - timedelta(days=days)

    stmt = (
        select(
            EnrichmentUsage.created_at,
            EnrichmentUsage.account_id,
            Account.name,
            EnrichmentUsage.operation,
            EnrichmentUsage.provider,
            EnrichmentUsage.enrichment_type,
            EnrichmentUsage.credits_debited,
            EnrichmentUsage.cost_usd,
            EnrichmentUsage.price_usd,
            EnrichmentUsage.margin_usd,
            EnrichmentUsage.records_written,
            EnrichmentUsage.fields_updated,
            EnrichmentUsage.billed,
            EnrichmentUsage.stripe_invoice_id,
        )
        .join(Account, EnrichmentUsage.account_id == Account.id)
        .where(EnrichmentUsage.created_at >= since)
        .order_by(EnrichmentUsage.created_at.desc())
    )

    result = await db.execute(stmt)
    rows = result.all()

    # Build CSV
    output = io.StringIO()
    writer = csv.writer(output)

    # Header
    writer.writerow(
        [
            "Date",
            "Account ID",
            "Account Name",
            "Operation",
            "Provider",
            "Type",
            "Credits",
            "Cost USD",
            "Revenue USD",
            "Margin USD",
            "Records Enriched",
            "Fields Updated",
            "Billed",
            "Invoice ID",
        ]
    )

    # Data rows
    for row in rows:
        writer.writerow(
            [
                row.created_at.isoformat() if row.created_at else "",
                row.account_id or "",
                row.name or "Unknown",
                row.operation or "",
                row.provider or "",
                row.enrichment_type or "",
                row.credits_debited or 0,
                float(row.cost_usd or Decimal("0")),
                float(row.price_usd or Decimal("0")),
                float(row.margin_usd or Decimal("0")),
                row.records_written or 0,
                row.fields_updated or 0,
                "Yes" if row.billed else "No",
                row.stripe_invoice_id or "",
            ]
        )

    csv_content = output.getvalue()
    output.close()

    return Response(
        content=csv_content,
        media_type="text/csv",
        headers={
            "Content-Disposition": f"attachment; filename=enrichment_billing_{days}d.csv"
        },
    )
