"""Admin Payments routes (thin — all logic in app.payments.admin_services)."""

from __future__ import annotations

import csv
import io
from datetime import datetime

from flask import Response, render_template, request
from flask_login import login_required

from app.admin import admin_bp
from app.admin.utils import admin_required
from app.models import PaymentStatus
from app.models.base import utcnow
from app.payments import admin_services as pay_admin

_SORTS = dict(pay_admin.SORT_OPTIONS)


def _parse_date(raw: str | None):
    """Parse a ``YYYY-MM-DD`` string into a date, or None."""
    if not raw:
        return None
    try:
        return datetime.strptime(raw.strip(), "%Y-%m-%d").date()
    except ValueError:
        return None


def _read_filters() -> tuple[dict, dict]:
    """Return (service filters, raw strings for re-rendering the form)."""
    status = (request.args.get("status") or "").strip()
    provider = (request.args.get("provider") or "").strip()
    plan = (request.args.get("plan") or "").strip()
    q = (request.args.get("q") or "").strip()
    amount_min = request.args.get("amount_min", type=float)
    amount_max = request.args.get("amount_max", type=float)
    date_from_raw = (request.args.get("date_from") or "").strip()
    date_to_raw = (request.args.get("date_to") or "").strip()

    if status not in {s.value for s in PaymentStatus}:
        status = ""

    filters = {
        "status": status or None,
        "provider": provider or None,
        "plan": plan or None,
        "q": q or None,
        "amount_min": amount_min,
        "amount_max": amount_max,
        "date_from": _parse_date(date_from_raw),
        "date_to": _parse_date(date_to_raw),
    }
    raw = {
        "status": status, "provider": provider, "plan": plan, "q": q,
        "amount_min": request.args.get("amount_min", ""),
        "amount_max": request.args.get("amount_max", ""),
        "date_from": date_from_raw, "date_to": date_to_raw,
    }
    return filters, raw


@admin_bp.route("/payments")
@login_required
@admin_required
def payments_dashboard():
    """Payments dashboard: KPI cards, revenue analytics and a filterable table."""
    filters, raw = _read_filters()
    sort = request.args.get("sort", "recent")
    if sort not in _SORTS:
        sort = "recent"
    page = request.args.get("page", 1, type=int)

    pagination = pay_admin.list_payments(filters, sort=sort, page=page)
    filter_args = {k: v for k, v in {**raw, "sort": sort}.items() if v}

    from app.premium.config import CURRENCY_SYMBOL

    return render_template(
        "admin/payments/list.html",
        pagination=pagination,
        kpis=pay_admin.payment_kpis(),
        charts=pay_admin.revenue_analytics(),
        currency=CURRENCY_SYMBOL,
        meta=pay_admin.payment_meta,
        status_options=pay_admin.STATUS_OPTIONS,
        provider_options=pay_admin.provider_options(),
        plan_names=pay_admin.plan_options(),
        sort_options=pay_admin.SORT_OPTIONS,
        filter_args=filter_args,
        **raw,
        sort=sort,
    )


@admin_bp.route("/payments/export.csv")
@login_required
@admin_required
def payments_export():
    """Download the filtered payments as CSV (respects all active filters)."""
    filters, _ = _read_filters()
    sort = request.args.get("sort", "recent")
    if sort not in _SORTS:
        sort = "recent"

    buffer = io.StringIO()
    writer = csv.writer(buffer)
    writer.writerows(pay_admin.payments_csv_rows(filters, sort=sort))
    stamp = utcnow().strftime("%Y%m%d")
    return Response(
        buffer.getvalue(),
        mimetype="text/csv",
        headers={"Content-Disposition": f'attachment; filename="payments-{stamp}.csv"'},
    )
