"""
API key management — generate, validate, and revoke API keys for programmatic access.
"""
from __future__ import annotations

import hashlib
import secrets
import sqlite3
from datetime import datetime, timedelta, timezone
from typing import Any

from .accounts import ACCOUNTS_DB

API_KEY_PREFIX = "gat_"


def _connect() -> sqlite3.Connection:
    conn = sqlite3.connect(str(ACCOUNTS_DB))
    conn.row_factory = sqlite3.Row
    return conn


def _hash_key(key: str) -> str:
    return hashlib.sha256(key.encode()).hexdigest()


def create_api_key(user_id: int, name: str = "", scopes: str = "trade:view",
                   expires_days: int = 365) -> dict[str, Any]:
    """Generate a new API key. Returns the raw key (shown only once)."""
    raw_key = API_KEY_PREFIX + secrets.token_urlsafe(32)
    key_hash = _hash_key(raw_key)
    key_prefix = raw_key[:12] + "..."
    expires_at = None
    if expires_days > 0:
        expires_at = (datetime.now(timezone.utc) + timedelta(days=expires_days)).isoformat()

    conn = _connect()
    conn.execute(
        "INSERT INTO api_keys (user_id, key_hash, key_prefix, name, scopes, created_at, expires_at) "
        "VALUES (?, ?, ?, ?, ?, ?, ?)",
        (user_id, key_hash, key_prefix, name, scopes, datetime.now(timezone.utc).isoformat(), expires_at),
    )
    conn.commit()
    conn.close()
    return {"ok": True, "api_key": raw_key, "prefix": key_prefix, "name": name,
            "scopes": scopes, "expires_at": expires_at}


def validate_api_key(raw_key: str) -> dict[str, Any] | None:
    """Validate an API key. Returns user dict or None."""
    if not raw_key.startswith(API_KEY_PREFIX):
        return None
    key_hash = _hash_key(raw_key)

    conn = _connect()
    row = conn.execute(
        "SELECT u.*, ak.scopes FROM api_keys ak "
        "JOIN users u ON ak.user_id = u.id "
        "WHERE ak.key_hash = ? AND ak.is_active = 1 AND u.is_active = 1 "
        "AND (ak.expires_at IS NULL OR ak.expires_at > ?)",
        (key_hash, datetime.now(timezone.utc).isoformat()),
    ).fetchone()
    if row:
        # Update last_used
        conn.execute(
            "UPDATE api_keys SET last_used_at = ? WHERE key_hash = ?",
            (datetime.now(timezone.utc).isoformat(), key_hash),
        )
        conn.commit()
    conn.close()
    return dict(row) if row else None


def list_api_keys(user_id: int) -> list[dict[str, Any]]:
    conn = _connect()
    rows = conn.execute(
        "SELECT id, key_prefix, name, scopes, created_at, last_used_at, expires_at, is_active "
        "FROM api_keys WHERE user_id = ? ORDER BY created_at DESC",
        (user_id,),
    ).fetchall()
    conn.close()
    return [dict(r) for r in rows]


def revoke_api_key(key_id: int) -> bool:
    conn = _connect()
    conn.execute("UPDATE api_keys SET is_active = 0 WHERE id = ?", (key_id,))
    conn.commit()
    conn.close()
    return True
