"""
Autenticación del Agent CLI contra el servidor Jama.

Gestiona credenciales almacenadas en ~/.jama/credentials.json
con permisos restrictivos (0o600).
"""
import json
import os
from pathlib import Path
from typing import Any

import httpx

from jama_agent.config import JAMA_DIR, ensure_jama_dir

CREDENTIALS_PATH = JAMA_DIR / "credentials.json"


def load_credentials() -> dict[str, Any] | None:
    """Lee las credenciales almacenadas. Retorna None si no existen."""
    if not CREDENTIALS_PATH.exists():
        return None
    try:
        with open(CREDENTIALS_PATH) as f:
            return json.load(f)
    except (json.JSONDecodeError, OSError):
        return None


def save_credentials(data: dict[str, Any]) -> None:
    """Guarda credenciales en ~/.jama/credentials.json con permisos 0o600."""
    ensure_jama_dir()

    # Escribir con permisos restrictivos
    fd = os.open(
        str(CREDENTIALS_PATH),
        os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
        0o600,
    )
    try:
        with os.fdopen(fd, "w") as f:
            json.dump(data, f, indent=2)
    except Exception:
        os.close(fd)
        raise


def clear_credentials() -> None:
    """Elimina las credenciales almacenadas."""
    if CREDENTIALS_PATH.exists():
        CREDENTIALS_PATH.unlink()


def login(server: str, email: str, password: str) -> dict[str, Any]:
    """Autentica contra el servidor y guarda las credenciales.

    POST /api/v1/auth/login con email+password.
    Guarda access_token, refresh_token, agent_id y server.

    Returns:
        dict con las credenciales guardadas.

    Raises:
        httpx.HTTPStatusError: si el login falla.
        httpx.ConnectError: si el servidor no responde.
    """
    url = f"{server.rstrip('/')}/api/v1/auth/login"

    response = httpx.post(
        url,
        json={"email": email, "password": password},
        timeout=15.0,
    )
    response.raise_for_status()

    data = response.json()
    creds = {
        "server": server.rstrip("/"),
        "email": email,
        "access_token": data.get("access_token", ""),
        "refresh_token": data.get("refresh_token", ""),
        "agent_id": data.get("agent_id", ""),
    }
    save_credentials(creds)
    return creds


def refresh_token(server: str, refresh: str) -> str:
    """Renueva el access_token usando el refresh_token.

    Returns:
        Nuevo access_token.

    Raises:
        httpx.HTTPStatusError: si el refresh falla.
    """
    url = f"{server.rstrip('/')}/api/v1/auth/refresh"
    response = httpx.post(
        url,
        json={"refresh_token": refresh},
        timeout=15.0,
    )
    response.raise_for_status()

    data = response.json()
    new_token = data.get("access_token", "")

    # Actualizar credenciales guardadas
    creds = load_credentials() or {}
    creds["access_token"] = new_token
    save_credentials(creds)

    return new_token


def register_agent(server: str, token: str) -> str:
    """Registra un nuevo agent en el servidor y retorna el agent_id.

    POST /api/v1/agents/register con nombre del host y SO.

    Returns:
        agent_id asignado por el servidor.

    Raises:
        httpx.HTTPStatusError: si el registro falla.
    """
    import platform
    import socket

    url = f"{server.rstrip('/')}/api/v1/agents/register"
    response = httpx.post(
        url,
        json={
            "name": socket.gethostname(),
            "os_type": platform.system().lower(),
            "capabilities": {"tools": []},
        },
        headers={"Authorization": f"Bearer {token}"},
        timeout=15.0,
    )
    response.raise_for_status()

    data = response.json()
    agent_id = data.get("id", "")

    # Actualizar credenciales con agent_id
    creds = load_credentials() or {}
    creds["agent_id"] = agent_id
    save_credentials(creds)

    return agent_id
