"""Partner dashboard (server-rendered HTML)."""

from typing import Optional
from datetime import datetime
import csv
import io
from urllib.parse import urlencode

from fastapi import APIRouter, Depends, Query, Form
from fastapi.responses import HTMLResponse, StreamingResponse, RedirectResponse
from sqlalchemy.orm import Session

from ..auth import get_partner_from_api_key, require_admin_api_key
from ..db import get_db
from ..models import CheckoutSession, Partner
from ..services import dashboard_service

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


def _page(title: str, body: str) -> HTMLResponse:
    html = f"""<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <title>{title}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <style>
      :root {{
        --ink: #0f172a;
        --muted: #475569;
        --bg: #f4f6f9;
        --card: #ffffff;
        --accent: #253454;
        --border: #e2e8f0;
      }}
      * {{ box-sizing: border-box; }}
      body {{ font-family: "Georgia", "Times New Roman", serif; margin: 0; background: var(--bg); color: var(--ink); }}
      .wrap {{ max-width: 1100px; margin: 40px auto; padding: 0 20px; }}
      .card {{ background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 20px; }}
      h1 {{ margin: 0 0 8px; }}
      .muted {{ color: var(--muted); font-size: 14px; }}
      .filters {{ display: grid; gap: 12px; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 16px 0 20px; }}
      .filters input, .filters select {{ padding: 10px; border: 1px solid var(--border); border-radius: 8px; }}
      .btn {{ background: var(--accent); color: #fff; padding: 10px 14px; border: 0; border-radius: 8px; font-weight: 600; }}
      .table-wrap {{ overflow-x: auto; }}
      table {{ width: 100%; border-collapse: collapse; font-size: 14px; min-width: 900px; }}
      th, td {{ padding: 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }}
      th {{ font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }}
      .pill {{ display: inline-block; padding: 4px 8px; border-radius: 999px; background: #eef2f7; font-size: 12px; }}
      .payout-form {{ margin-top: 8px; display: grid; gap: 6px; grid-template-columns: 110px 1fr 1fr auto; align-items: center; }}
      .payout-form input, .payout-form select {{ padding: 6px; border: 1px solid var(--border); border-radius: 6px; font-size: 12px; }}
      .payout-form button {{ padding: 6px 10px; font-size: 12px; }}
    </style>
  </head>
  <body>
    <div class="wrap">
      <div class="card">
        {body}
      </div>
    </div>
  </body>
</html>"""
    return HTMLResponse(content=html)


@router.get("", response_class=HTMLResponse)
def dashboard(
    q: Optional[str] = Query(default=None, description="Search by order ID or email"),
    status: Optional[str] = Query(default=None),
    payout_status: Optional[str] = Query(default=None),
    date_from: Optional[str] = Query(default=None),
    date_to: Optional[str] = Query(default=None),
    admin_key: Optional[str] = Query(default=None),
    page: int = Query(default=1, ge=1),
    page_size: int = Query(default=50, ge=1, le=200),
    db: Session = Depends(get_db),
    partner: Partner = Depends(get_partner_from_api_key),
):
    """Render partner dashboard with transaction list and filters."""

    query = dashboard_service.list_sessions(
        db, partner.id, q, status, payout_status, date_from, date_to
    )

    total_count = query.count()
    sessions = (
        query.order_by(CheckoutSession.created_at.desc())
        .offset((page - 1) * page_size)
        .limit(page_size)
        .all()
    )

    totals = dashboard_service.totals(db, partner.id)
    total_amount = totals[0] if totals else 0
    outstanding_amount = totals[1] if totals else 0

    def _page_link(target_page: int) -> str:
        params = {
            "q": q or "",
            "status": status or "",
            "payout_status": payout_status or "",
            "date_from": date_from or "",
            "date_to": date_to or "",
            "page": target_page,
            "page_size": page_size,
            "admin_key": admin_key or "",
        }
        return f"/dashboard?{urlencode(params)}"

    prev_link = _page_link(page - 1) if page > 1 else ""
    next_link = _page_link(page + 1) if page * page_size < total_count else ""

    csv_link = _page_link(page).replace("/dashboard?", "/dashboard.csv?")

    rows = ""
    for s in sessions:
        admin_hidden = (
            f"<input type='hidden' name='admin_key' value='{admin_key}'/>" if admin_key else ""
        )
        rows += f"""
        <tr>
          <td>{s.created_at.strftime("%Y-%m-%d %H:%M")}</td>
          <td>{s.external_order_id}</td>
          <td>{s.customer_name or ""}<div class="muted">{s.customer_email or ""}</div><div class="muted">{s.customer_country or ""}</div></td>
          <td>{s.service_type or ""}<div class="muted">{s.channel or ""}</div></td>
          <td>{s.amount} {s.currency}</td>
          <td><span class="pill">{s.status}</span></td>
          <td>
            <span class="pill">{s.payout_status}</span>
            <div class="muted">{s.payout_method or ""}</div>
            <form method="post" action="/dashboard/payout/{s.id}" class="payout-form">
              <select name="payout_status">
                <option value="not_paid" {"selected" if s.payout_status == "not_paid" else ""}>not_paid</option>
                <option value="scheduled" {"selected" if s.payout_status == "scheduled" else ""}>scheduled</option>
                <option value="paid" {"selected" if s.payout_status == "paid" else ""}>paid</option>
              </select>
              <input name="payout_method" placeholder="method" value="{s.payout_method or ""}"/>
              <input name="payout_batch_id" placeholder="batch id" value="{s.payout_batch_id or ""}"/>
              {admin_hidden}
              <button class="btn" type="submit">Update</button>
            </form>
          </td>
        </tr>
        """

    body = f"""
      <h1>Partner Dashboard</h1>
      <div class="muted">Partner: {partner.name}</div>
      <div class="muted">Total volume: {total_amount} | Outstanding: {outstanding_amount}</div>
      <form method="get">
        <div class="filters">
          <input name="q" placeholder="Search order or email" value="{q or ""}"/>
          <select name="status">
            <option value="">Status (all)</option>
            <option value="pending" {"selected" if status == "pending" else ""}>pending</option>
            <option value="paid" {"selected" if status == "paid" else ""}>paid</option>
            <option value="failed" {"selected" if status == "failed" else ""}>failed</option>
          </select>
          <select name="payout_status">
            <option value="">Payout (all)</option>
            <option value="not_paid" {"selected" if payout_status == "not_paid" else ""}>not_paid</option>
            <option value="scheduled" {"selected" if payout_status == "scheduled" else ""}>scheduled</option>
            <option value="paid" {"selected" if payout_status == "paid" else ""}>paid</option>
          </select>
          <input name="date_from" placeholder="Date from (YYYY-MM-DD)" value="{date_from or ""}"/>
        </div>
        <div class="filters" style="grid-template-columns: 1fr 1fr 1fr 1fr;">
          <input name="date_to" placeholder="Date to (YYYY-MM-DD)" value="{date_to or ""}"/>
          <input name="page_size" placeholder="Page size" value="{page_size}"/>
          <input name="admin_key" placeholder="Admin key (dev)" value="{admin_key or ""}"/>
          <div></div><div></div>
          <button class="btn" type="submit">Filter</button>
        </div>
      </form>
      <div class="muted" style="margin-top: 12px;">Results: {total_count} | Page: {page}</div>
      <div class="muted" style="margin: 12px 0 20px;">
        {"<a href='" + prev_link + "'>Prev</a>" if prev_link else ""}
        {" | " if prev_link and next_link else ""}
        {"<a href='" + next_link + "'>Next</a>" if next_link else ""}
      </div>
      <div class="table-wrap">
      <table style="margin-top: 8px;">
        <thead>
          <tr>
            <th>Date</th>
            <th>Order</th>
            <th>Customer</th>
            <th>Service</th>
            <th>Amount</th>
            <th>Status</th>
            <th>Payout</th>
          </tr>
        </thead>
        <tbody>
          {rows if rows else "<tr><td colspan='7'>No transactions found.</td></tr>"}
        </tbody>
      </table>
      </table>
      </div>
      <div class="muted" style="margin: 16px 0 0;">
        {"<a href='" + csv_link + "'>Download CSV</a>" if csv_link else ""}
      </div>
    """

    return _page("Partner Dashboard", body)


@router.get(".csv")
def dashboard_csv(
    q: Optional[str] = Query(default=None),
    status: Optional[str] = Query(default=None),
    payout_status: Optional[str] = Query(default=None),
    date_from: Optional[str] = Query(default=None),
    date_to: Optional[str] = Query(default=None),
    db: Session = Depends(get_db),
    partner: Partner = Depends(get_partner_from_api_key),
):
    """Export partner transactions as CSV."""

    query = db.query(CheckoutSession).filter(CheckoutSession.partner_id == partner.id)
    if q:
        like = f"%{q}%"
        query = query.filter(
            (CheckoutSession.external_order_id.ilike(like))
            | (CheckoutSession.customer_email.ilike(like))
        )
    if status:
        query = query.filter(CheckoutSession.status == status)
    if payout_status:
        query = query.filter(CheckoutSession.payout_status == payout_status)
    if date_from:
        try:
            dt_from = datetime.fromisoformat(date_from)
            query = query.filter(CheckoutSession.created_at >= dt_from)
        except ValueError:
            pass
    if date_to:
        try:
            dt_to = datetime.fromisoformat(date_to)
            query = query.filter(CheckoutSession.created_at <= dt_to)
        except ValueError:
            pass

    output = io.StringIO()
    writer = csv.writer(output)
    writer.writerow(
        [
            "date",
            "order_id",
            "customer_name",
            "customer_email",
            "customer_country",
            "service_type",
            "channel",
            "amount",
            "currency",
            "status",
            "payout_status",
            "payout_method",
            "payout_batch_id",
            "payout_paid_at",
        ]
    )
    for s in query.order_by(CheckoutSession.created_at.desc()).all():
        writer.writerow(
            [
                s.created_at.isoformat(),
                s.external_order_id,
                s.customer_name or "",
                s.customer_email or "",
                s.customer_country or "",
                s.service_type or "",
                s.channel or "",
                s.amount,
                s.currency,
                s.status,
                s.payout_status,
                s.payout_method or "",
                s.payout_batch_id or "",
                s.payout_paid_at.isoformat() if s.payout_paid_at else "",
            ]
        )

    output.seek(0)
    return StreamingResponse(
        output,
        media_type="text/csv",
        headers={"Content-Disposition": "attachment; filename=transactions.csv"},
    )


@router.post("/payout/{session_id}")
def dashboard_update_payout(
    session_id: str,
    payout_status: str = Form(...),
    payout_method: Optional[str] = Form(default=None),
    payout_batch_id: Optional[str] = Form(default=None),
    admin_key: Optional[str] = Form(default=None),
    db: Session = Depends(get_db),
):
    """Handle payout updates from the dashboard form (admin only)."""

    require_admin_api_key(admin_key=admin_key)
    session = db.get(CheckoutSession, session_id)
    if not session:
        return RedirectResponse(url="/dashboard", status_code=303)

    session.payout_status = payout_status
    session.payout_method = payout_method
    session.payout_batch_id = payout_batch_id
    db.commit()
    return RedirectResponse(url=f"/dashboard?admin_key={admin_key or ''}", status_code=303)
