"""Ejemplo de integración de FaceID en FastAPI (o como guía para Flask) — kit v2.

    pip install fastapi uvicorn python-multipart requests
    FACEID_API_KEY=xxx uvicorn ejemplo_fastapi:app

Sustituye `usuario_actual` por tu autenticación real: la identidad a verificar
debe salir de TU sesión/token, nunca de un campo que envíe el navegador.

El cliente usa `requests` (síncrono); por eso las llamadas a FaceID se ejecutan
en un hilo (`run_in_threadpool`) para no bloquear el event loop.
"""
import logging
import os

from fastapi import Depends, FastAPI, File, HTTPException, UploadFile
from fastapi.concurrency import run_in_threadpool

from faceid_client import FaceIDClient, FaceIDError

logger = logging.getLogger(__name__)
app = FastAPI()
faceid = FaceIDClient(api_key=os.environ['FACEID_API_KEY'],
                      base_url=os.environ.get('FACEID_URL', 'https://faceapi.epunemi.gob.ec'))

MAX_FOTO_BYTES = 5 * 1024 * 1024


def usuario_actual():
    # Reemplaza por tu dependencia de autenticación (JWT, sesión, etc.).
    raise HTTPException(status_code=401, detail='No autenticado')


async def _leer_foto(foto: UploadFile) -> bytes:
    datos = await foto.read(MAX_FOTO_BYTES + 1)
    if not datos:
        raise FaceIDError('No se recibió la foto.')
    if len(datos) > MAX_FOTO_BYTES:
        raise FaceIDError('La foto supera 5 MB.')
    return datos


def _error(e: FaceIDError):
    if e.status == 403:
        logger.error('FaceID rechazó la API key: %s', e.message)
        return {'isSuccess': False, 'message': 'El servicio de verificación no está disponible.'}
    return {'isSuccess': False, 'message': e.message}


@app.post('/faceid/enrolar/')
async def enrolar(foto: UploadFile = File(...), usuario=Depends(usuario_actual)):
    try:
        datos = await _leer_foto(foto)
        await run_in_threadpool(faceid.enrolar, datos, cod_number=str(usuario.id),
                                username=usuario.username, permite_actualizar=True)
        return {'isSuccess': True, 'message': 'Rostro registrado correctamente.'}
    except FaceIDError as e:
        return _error(e)


@app.post('/faceid/verificar/')
async def verificar(foto: UploadFile = File(...), usuario=Depends(usuario_actual)):
    try:
        datos = await _leer_foto(foto)
        r = await run_in_threadpool(faceid.verificar, datos, cod_number=str(usuario.id))
        ok = bool(r.get('is_same_person'))
        # Si ok: registra aquí tu evento (asistencia, examen…). Nunca en el navegador.
        return {'isSuccess': ok, 'message': 'Identidad verificada.' if ok else 'El rostro no coincide.',
                'aData': {'is_same_person': ok, 'similarity_score': r.get('similarity_score')}}
    except FaceIDError as e:
        if e.no_coincide:
            return {'isSuccess': False, 'message': 'El rostro no coincide con el registrado.'}
        return _error(e)
