from pydantic import BaseModel
from typing import Optional, List

class AadharPerson(BaseModel):
    name: str
    age: Optional[int] = None

class AadharCheckRequest(BaseModel):
    aadhar_files: List[str]
    people: List[AadharPerson]
    name_threshold: Optional[float] = 0.8
    age_tolerance: Optional[int] = 1
    debug: Optional[bool] = False

@app.post("/aadhar_check")
async def aadhar_check(req: AadharCheckRequest = Body(...)):
    name_thresh = max(0.0, min(1.0, float(req.name_threshold or 0.8)))
    age_tol = int(req.age_tolerance or 1)

    tempd = tempfile.mkdtemp(prefix="aadhar_")
    try:
        try:
            downloaded = await download_all(req.aadhar_files, tempd)
        except Exception as e:
            shutil.rmtree(tempd, ignore_errors=True)
            raise HTTPException(status_code=400, detail=f"dl_err: {e}")

        extracted = []
        for file_url, local_path in zip(req.aadhar_files, downloaded):
            # use image OCR helper for images; for PDFs fallback to your pdf OCR
            if is_image_ext(local_path):
                text = ocr_image_file(local_path, lang='eng', dpi=300)
            else:
                # PDF fallback
                text = extract_text_from_pdf(local_path)
                if not text or len(text.strip()) < 80:
                    try:
                        text = ocr_pdf(local_path)
                    except Exception:
                        text = ""
            info = extract_aadhar_fields_from_text(text)
            info["file"] = file_url
            if req.debug:
                info["ocr_text"] = text
            extracted.append(info)

        # matching
        results = []
        for person in req.people:
            best = {"score": 0.0, "file": None, "matched_name": None, "aadhar_age": None, "age_difference": None, "raw_name_line": None, "raw_dob_line": None}
            for info in extracted:
                if not info.get("name"):
                    continue
                name_score = token_score_en(person.name, info["name"]) / 100.0
                a_age = info.get("age")
                age_diff = None
                age_ok = None
                if person.age is not None and a_age is not None:
                    age_diff = abs(int(person.age) - int(a_age))
                    age_ok = age_diff <= age_tol
                if name_score > best["score"] or (name_score == best["score"] and age_ok):
                    best.update({
                        "score": name_score,
                        "file": info.get("file"),
                        "matched_name": info.get("name"),
                        "aadhar_age": a_age,
                        "age_difference": age_diff,
                        "raw_name_line": info.get("raw_name_line"),
                        "raw_dob_line": info.get("raw_dob_line")
                    })
            passed = False
            if best["file"]:
                if best["score"] >= name_thresh:
                    if person.age is not None and best["aadhar_age"] is not None:
                        passed = best["age_difference"] is not None and best["age_difference"] <= age_tol
                    else:
                        passed = True
            results.append({
                "person": {"name": person.name, "expected_age": person.age},
                "match": {
                    "found": bool(best["file"]),
                    "matched_file": best.get("file"),
                    "matched_name": best.get("matched_name"),
                    "name_score": best.get("score"),
                    "aadhar_age": best.get("aadhar_age"),
                    "age_difference": best.get("age_difference"),
                    "passed": passed,
                    "raw_name_line": best.get("raw_name_line"),
                    "raw_dob_line": best.get("raw_dob_line")
                }
            })

        resp = {"results": results}
        if req.debug:
            resp["extracted"] = extracted
        return resp
    finally:
        shutil.rmtree(tempd, ignore_errors=True)
