"""
Dashboard domain: coffee analytics dashboard, settings, API keys.
"""
import asyncio
import hashlib
import secrets
from datetime import datetime
from pathlib import Path

from quart import Blueprint, flash, g, jsonify, redirect, render_template, request, url_for

from .. import analytics
from ..auth.routes import login_required, update_user

from ..core import csrf_protect, execute, fetch_all, fetch_one, soft_delete

# Blueprint with its own template folder
bp = Blueprint(
    "dashboard",
    __name__,
    template_folder=str(Path(__file__).parent / "templates"),
    url_prefix="/dashboard",
)


# =============================================================================
# SQL Queries
# =============================================================================

async def get_user_stats(user_id: int) -> dict:
    """Get dashboard stats for user."""
    api_calls = await fetch_one(
        """
        SELECT COUNT(*) as count FROM api_requests
        WHERE user_id = ? AND created_at > date('now', '-30 days')
        """,
        (user_id,),
    )

    return {
        "api_calls": api_calls["count"] if api_calls else 0,
    }


# API Key queries
async def create_api_key(user_id: int, name: str, scopes: list[str] = None) -> tuple[str, int]:
    """Create API key. Returns (raw_key, key_id) - raw_key shown only once."""
    raw_key = f"sk_{secrets.token_urlsafe(32)}"
    key_hash = hashlib.sha256(raw_key.encode()).hexdigest()
    prefix = raw_key[:12]

    now = datetime.utcnow().isoformat()
    key_id = await execute(
        """
        INSERT INTO api_keys (user_id, name, key_hash, key_prefix, scopes, created_at)
        VALUES (?, ?, ?, ?, ?, ?)
        """,
        (user_id, name, key_hash, prefix, ",".join(scopes or ["read"]), now),
    )

    return raw_key, key_id


async def get_user_api_keys(user_id: int) -> list[dict]:
    """Get all API keys for user (without hashes)."""
    return await fetch_all(
        """
        SELECT id, name, key_prefix, scopes, created_at, last_used_at
        FROM api_keys
        WHERE user_id = ? AND deleted_at IS NULL
        ORDER BY created_at DESC
        """,
        (user_id,),
    )


async def delete_api_key(key_id: int, user_id: int) -> bool:
    """Delete API key (soft delete)."""
    result = await execute(
        """
        UPDATE api_keys
        SET deleted_at = ?
        WHERE id = ? AND user_id = ? AND deleted_at IS NULL
        """,
        (datetime.utcnow().isoformat(), key_id, user_id),
    )
    return result > 0


# =============================================================================
# Routes
# =============================================================================

@bp.route("/")
@login_required
async def index():
    """Coffee analytics dashboard."""
    user = g.user
    stats = await get_user_stats(g.user["id"])
    plan = (g.get("subscription") or {}).get("plan", "free")

    # Fetch all analytics data in parallel (empty lists if DB not available)
    if analytics._conn is not None:
        time_series, top_producers, stu_trend, balance, yoy = await asyncio.gather(
            analytics.get_global_time_series(
                analytics.COFFEE_COMMODITY_CODE,
                ["production", "exports", "imports", "ending_stocks", "total_distribution"],
            ),
            analytics.get_top_countries(analytics.COFFEE_COMMODITY_CODE, "production", limit=10),
            analytics.get_stock_to_use_trend(analytics.COFFEE_COMMODITY_CODE),
            analytics.get_supply_demand_balance(analytics.COFFEE_COMMODITY_CODE),
            analytics.get_production_yoy_by_country(analytics.COFFEE_COMMODITY_CODE, limit=15),
        )
    else:
        time_series, top_producers, stu_trend, balance, yoy = [], [], [], [], []

    # Latest global snapshot for key metric cards
    latest = time_series[-1] if time_series else {}

    # Apply free plan history limit (last 5 years)
    if plan == "free" and time_series:
        max_year = time_series[-1]["market_year"]
        cutoff_year = max_year - 5
        time_series = [r for r in time_series if r["market_year"] >= cutoff_year]
        stu_trend = [r for r in stu_trend if r["market_year"] >= cutoff_year]
        balance = [r for r in balance if r["market_year"] >= cutoff_year]

    return await render_template(
        "index.html",
        user=user,
        stats=stats,
        plan=plan,
        latest=latest,
        time_series=time_series,
        top_producers=top_producers,
        stu_trend=stu_trend,
        balance=balance,
        yoy=yoy,
    )


@bp.route("/countries")
@login_required
async def countries():
    """Country comparison page."""
    user = g.user
    plan = (g.get("subscription") or {}).get("plan", "free")

    # Get available countries for coffee
    all_countries = await analytics.get_top_countries(analytics.COFFEE_COMMODITY_CODE, "production", limit=50)

    # Parse query params
    selected_codes = request.args.getlist("country")
    metric = request.args.get("metric", "production")

    comparison_data = []
    if selected_codes:
        selected_codes = selected_codes[:10]  # cap at 10
        comparison_data = await analytics.get_country_comparison(
            analytics.COFFEE_COMMODITY_CODE, selected_codes, metric
        )

    # HTMX partial: return just the chart data as JSON
    if request.headers.get("HX-Request"):
        return jsonify({"data": comparison_data, "metric": metric})

    return await render_template(
        "countries.html",
        user=user,
        plan=plan,
        all_countries=all_countries,
        selected_codes=selected_codes,
        metric=metric,
        comparison_data=comparison_data,
    )


@bp.route("/settings", methods=["GET", "POST"])
@login_required
@csrf_protect
async def settings():
    """User settings page."""
    if request.method == "POST":
        form = await request.form

        # Update user settings
        await update_user(
            g.user["id"],
            name=form.get("name", "").strip() or None,
            updated_at=datetime.utcnow().isoformat(),
        )

        await flash("Settings saved!", "success")
        return redirect(url_for("dashboard.settings"))

    user = g.user
    subscription = g.get("subscription")
    api_keys = await get_user_api_keys(g.user["id"])

    return await render_template(
        "settings.html",
        user=user,
        subscription=subscription,
        api_keys=api_keys,
    )


@bp.route("/api-keys", methods=["POST"])
@login_required
@csrf_protect
async def create_key():
    """Create new API key."""
    form = await request.form
    name = form.get("name", "").strip() or "Untitled Key"
    scopes = form.getlist("scopes") or ["read"]

    raw_key, key_id = await create_api_key(g.user["id"], name, scopes)

    await flash(f"API key created! Copy it now, it won't be shown again: {raw_key}", "success")
    return redirect(url_for("dashboard.settings") + "#api-keys")


@bp.route("/api-keys/<int:key_id>/delete", methods=["POST"])
@login_required
@csrf_protect
async def delete_key(key_id: int):
    """Delete API key."""
    success = await delete_api_key(key_id, g.user["id"])

    if success:
        await flash("API key deleted.", "success")
    else:
        await flash("Could not delete API key.", "error")

    return redirect(url_for("dashboard.settings") + "#api-keys")


@bp.route("/delete-account", methods=["POST"])
@login_required
@csrf_protect
async def delete_account():
    """Delete user account (soft delete)."""
    from quart import session

    await soft_delete("users", g.user["id"])
    session.clear()

    await flash("Your account has been deleted.", "info")
    return redirect(url_for("public.landing"))
