"""Endpoint de autenticacion local (fallback cuando el cloud no responde)."""
import hashlib
import json
import os
import httpx
from fastapi import APIRouter, Depends
from pydantic import BaseModel
from typing import Optional
from sqlalchemy.orm import Session as DBSession
from database import get_db
from config import CLOUD_SYNC_KEY, VENUE_ID, VENUE_NAME

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

OPERATOR_URL = "https://icebergecuador.com/Cuenca/Operator/api.php"
CLOUD_TIMEOUT = 8  # segundos

# Archivo de usuarios locales (fallback persistente cuando cloud no responde)
_USERS_FILE = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "users.json")


class AuthRequest(BaseModel):
    username: str  # email del cajero
    password: str
    venue_id: Optional[str] = None


class AuthUser(BaseModel):
    id: str | int
    name: str
    email: str
    role: str


class AuthResponse(BaseModel):
    status: str
    user: Optional[AuthUser] = None
    permissions: Optional[list[str]] = None
    venues: Optional[list[dict]] = None
    message: Optional[str] = None


# Cache local de credenciales (en memoria, se pierde al reiniciar)
_auth_cache: dict = {}


@router.post("/auth", response_model=AuthResponse)
async def auth_local(req: AuthRequest):
    """
    Autenticacion local como fallback.
    Intenta validar contra el cloud primero; si falla, usa cache local.
    """
    print(f"[AUTH] Intento login: username='{req.username}', venue_id='{req.venue_id}'")

    # Intentar contra el cloud
    try:
        async with httpx.AsyncClient(timeout=CLOUD_TIMEOUT) as client:
            resp = await client.post(
                f"{OPERATOR_URL}?action=auth_app",
                json={
                    "email": req.username,
                    "password": req.password,
                    "app_key": CLOUD_SYNC_KEY,
                },
            )
            data = resp.json()

            if data.get("status") == "ok":
                # Guardar en cache local para uso offline
                _cache_credentials(req.username, req.password, data)
                return AuthResponse(
                    status="ok",
                    user=AuthUser(**data["user"]),
                    permissions=data.get("permissions", []),
                    venues=data.get("venues", []),
                )
            else:
                return AuthResponse(
                    status="error",
                    message=data.get("message", "Credenciales invalidas"),
                )
    except Exception:
        # Cloud no disponible, usar cache local
        pass

    # Fallback 1: cache en memoria
    cached = _check_cache(req.username, req.password)
    if cached:
        return AuthResponse(
            status="ok",
            user=AuthUser(**cached["user"]),
            permissions=cached.get("permissions", []),
            venues=cached.get("venues", []),
        )

    # Fallback 2: users.json (persistente entre reinicios)
    local_user = _check_users_file(req.username, req.password)
    if local_user:
        return AuthResponse(
            status="ok",
            user=AuthUser(**local_user["user"]),
            permissions=local_user.get("permissions", []),
            venues=local_user.get("venues", []),
        )

    return AuthResponse(
        status="error",
        message="No se puede conectar al servidor cloud y no hay cache local",
    )


def _cache_credentials(email: str, password: str, data: dict):
    """Guarda credenciales validadas en cache (memoria + archivo users.json)."""
    pw_hash = hashlib.sha256(password.encode()).hexdigest()
    entry = {
        "password_hash": pw_hash,
        "user": data["user"],
        "permissions": data.get("permissions", []),
        "venues": data.get("venues", []),
    }
    _auth_cache[email.lower()] = entry

    # Persistir en users.json para sobrevivir reinicios
    try:
        users = {}
        if os.path.exists(_USERS_FILE):
            with open(_USERS_FILE, encoding="utf-8") as f:
                users = json.load(f)
        users[email.lower()] = entry
        os.makedirs(os.path.dirname(_USERS_FILE), exist_ok=True)
        with open(_USERS_FILE, "w", encoding="utf-8") as f:
            json.dump(users, f, indent=2, ensure_ascii=False)
    except Exception:
        pass


def _check_cache(email: str, password: str) -> Optional[dict]:
    """Verifica credenciales contra el cache en memoria."""
    cached = _auth_cache.get(email.lower())
    if not cached:
        return None
    pw_hash = hashlib.sha256(password.encode()).hexdigest()
    if cached["password_hash"] == pw_hash:
        return cached
    return None


def _check_users_file(username: str, password: str) -> Optional[dict]:
    """Verifica credenciales contra users.json (fallback persistente)."""
    try:
        if not os.path.exists(_USERS_FILE):
            return None
        with open(_USERS_FILE, encoding="utf-8") as f:
            users = json.load(f)
    except Exception:
        return None

    pw_hash = hashlib.sha256(password.encode()).hexdigest()

    # Buscar por key exacta (email lowercase)
    entry = users.get(username.lower())
    if entry and entry.get("password_hash") == pw_hash:
        return entry

    # Buscar por nombre de usuario (campo user.name) para soportar login con nombre corto
    for _key, entry in users.items():
        user_info = entry.get("user", {})
        if user_info.get("name", "").lower() == username.lower():
            if entry.get("password_hash") == pw_hash:
                return entry

    return None
