"""
Face Service — LPK TIP (Sprint A3)
Micro-service verifikasi wajah: FastAPI + face_recognition (dlib, embedding 128D).

Menjalankan:
  pip install -r face_service/requirements.txt
  uvicorn main:app --host 0.0.0.0 --port 8001
Env:
  FACE_SERVICE_URL=http://127.0.0.1:8001  (di .env Laravel)
"""
import io

import face_recognition
import numpy as np
from fastapi import FastAPI, File, Form, HTTPException, UploadFile

app = FastAPI(title="Face Service — LPK TIP", version="1.0.0")


def encodings_of(data: bytes) -> list:
    img = face_recognition.load_image_file(io.BytesIO(data))
    return face_recognition.face_encodings(img)


@app.post("/face/embed")
async def face_embed(files: list[UploadFile] = File(...)):
    """Terima beberapa foto wajah (depan/samping/senyum) -> embedding rata-rata 128D."""
    all_enc = []
    for f in files:
        all_enc.extend(encodings_of(await f.read()))
    if not all_enc:
        raise HTTPException(status_code=422, detail="Wajah tidak terdeteksi pada foto")
    mean = np.mean(all_enc, axis=0)
    return {"faces": len(all_enc), "embedding": mean.tolist()}


@app.post("/face/verify")
async def face_verify(
    image: UploadFile = File(...),
    embeddings: str = Form("[]"),
    threshold: float = Form(0.55),
):
    """Verifikasi selfie terhadap embedding terdaftar. Return skor cosine & matched."""
    enc = encodings_of(await image.read())
    if not enc:
        raise HTTPException(status_code=422, detail="Wajah tidak terdeteksi pada selfie")
    target = enc[0]

    refs = [np.array(e) for e in __import__("json").loads(embeddings)]
    if not refs:
        raise HTTPException(status_code=422, detail="Embedding referensi kosong")

    # cosine similarity: skor 1 = sama persis
    best = max(float(np.dot(target, r) / (np.linalg.norm(target) * np.linalg.norm(r))) for r in refs)
    return {"score": round(best, 4), "matched": best >= threshold, "threshold": threshold}
