"""
Auth API endpoints — login, register, API key management.
Designed to be mounted in control_api.py.
"""
from __future__ import annotations

import json
from http.server import BaseHTTPRequestHandler
from typing import Any

from .accounts import (
    authenticate,
    create_user,
    deactivate_user,
    get_user,
    init_db as init_auth_db,
    list_users,
    update_user_role,
)
from .session import create_session, destroy_session
from .api_keys import create_api_key, list_api_keys, revoke_api_key
from .middleware import require_auth, require_role

_init_done = False


def ensure_init() -> None:
    global _init_done
    if not _init_done:
        init_auth_db()
        _init_done = True


def _json_response(handler: BaseHTTPRequestHandler, code: int, payload: dict[str, Any]) -> None:
    body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
    handler.send_response(code)
    handler.send_header("Content-Type", "application/json; charset=utf-8")
    handler.send_header("Content-Length", str(len(body)))
    handler.end_headers()
    handler.wfile.write(body)


def _read_json_body(handler: BaseHTTPRequestHandler) -> dict[str, Any]:
    length = int(handler.headers.get("Content-Length", "0"))
    if length == 0:
        return {}
    data = handler.rfile.read(length)
    return json.loads(data.decode("utf-8"))


# ─── Route dispatcher ──────────────────────────────────────────────

def handle_auth_routes(handler: BaseHTTPRequestHandler, path: str) -> bool:
    """Handle auth-related routes. Returns True if route was handled."""
    ensure_init()

    # Public endpoints (no auth required)
    if path == "/auth/register" and handler.command == "POST":
        _register(handler)
        return True
    if path == "/auth/login" and handler.command == "POST":
        _login(handler)
        return True

    # Authenticated endpoints
    if path == "/auth/logout" and handler.command == "POST":
        _logout(handler)
        return True
    if path == "/auth/me" and handler.command == "GET":
        _me(handler)
        return True
    if path == "/auth/api-keys" and handler.command == "GET":
        _list_api_keys(handler)
        return True
    if path == "/auth/api-keys" and handler.command == "POST":
        _create_api_key(handler)
        return True
    if path == "/auth/api-keys/revoke" and handler.command == "POST":
        _revoke_api_key(handler)
        return True

    # Admin endpoints
    if path == "/auth/users" and handler.command == "GET":
        _list_users(handler)
        return True

    return False


# ─── Handlers ──────────────────────────────────────────────────────

def _register(handler: BaseHTTPRequestHandler) -> None:
    body = _read_json_body(handler)
    email = str(body.get("email", "")).strip()
    password = str(body.get("password", "")).strip()
    display_name = str(body.get("display_name", "")).strip()

    if not email or not password:
        _json_response(handler, 400, {"ok": False, "error": "MISSING_FIELDS"})
        return
    if len(password) < 8:
        _json_response(handler, 400, {"ok": False, "error": "WEAK_PASSWORD",
                                      "message": "Password must be at least 8 characters."})
        return

    result = create_user(email, password, role="trader", display_name=display_name)
    if result["ok"]:
        user = result["user"]
        session = create_session(user["id"])
        _json_response(handler, 201, {"ok": True, "user": user, "session": session})
    else:
        _json_response(handler, 409, result)


def _login(handler: BaseHTTPRequestHandler) -> None:
    body = _read_json_body(handler)
    email = str(body.get("email", "")).strip()
    password = str(body.get("password", "")).strip()

    if not email or not password:
        _json_response(handler, 400, {"ok": False, "error": "MISSING_FIELDS"})
        return

    result = authenticate(email, password)
    if result["ok"]:
        user = result["user"]
        session = create_session(user["id"])
        _json_response(handler, 200, {"ok": True, "user": user, "session": session})
    else:
        _json_response(handler, 401, result)


def _logout(handler: BaseHTTPRequestHandler) -> None:
    auth_header = handler.headers.get("Authorization", "")
    if auth_header.startswith("Bearer "):
        destroy_session(auth_header[7:])
    _json_response(handler, 200, {"ok": True})


def _me(handler: BaseHTTPRequestHandler) -> None:
    user = require_auth(handler)
    if not user:
        return
    _json_response(handler, 200, {"ok": True, "user": user})


def _list_api_keys(handler: BaseHTTPRequestHandler) -> None:
    user = require_auth(handler)
    if not user:
        return
    keys = list_api_keys(user["id"])
    _json_response(handler, 200, {"ok": True, "api_keys": keys})


def _create_api_key(handler: BaseHTTPRequestHandler) -> None:
    user = require_auth(handler)
    if not user:
        return
    body = _read_json_body(handler)
    name = str(body.get("name", "API Key"))
    scopes = str(body.get("scopes", "trade:view"))
    result = create_api_key(user["id"], name=name, scopes=scopes)
    _json_response(handler, 201, result)


def _revoke_api_key(handler: BaseHTTPRequestHandler) -> None:
    user = require_auth(handler)
    if not user:
        return
    body = _read_json_body(handler)
    key_id = int(body.get("key_id", 0))
    if not key_id:
        _json_response(handler, 400, {"ok": False, "error": "MISSING_FIELDS"})
        return
    revoke_api_key(key_id)
    _json_response(handler, 200, {"ok": True})


def _list_users(handler: BaseHTTPRequestHandler) -> None:
    if not require_role(handler, "admin"):
        return
    users = list_users()
    _json_response(handler, 200, {"ok": True, "users": users})
