"""Reproduce KelenAI's small synthetic invoice reading demonstration.

Requires reportlab, pypdf, Pillow, pdftoppm and tesseract on PATH.
Run in a fresh directory: python run_demo.py --output-dir ./results
No network calls, real vendor records or AI API usage.
"""

import argparse
import hashlib
import json
import re
import shutil
import subprocess
from pathlib import Path

import PIL
import pypdf
import reportlab
from PIL import Image
from pypdf import PdfReader
from reportlab.lib.colors import HexColor
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas


def make_invoice(path, invoice_number, paid):
    pdf = canvas.Canvas(str(path), pagesize=letter, invariant=1)
    pdf.setTitle("Synthetic invoice - " + invoice_number)
    pdf.setFillColor(HexColor("#183c32"))
    pdf.setFont("Helvetica-Bold", 25)
    pdf.drawString(50, 736, "INVOICE")
    pdf.setFont("Helvetica", 11)
    pdf.drawString(50, 710, "SYNTHETIC DEMONSTRATION - NOT PAYABLE")
    pdf.setFillColor(HexColor("#202c27"))
    lines = [
        ("Supplier", "Example Supply - fictional"),
        ("Customer", "Example Distributor - fictional"),
        ("Invoice Number", invoice_number),
        ("Invoice Date", "2026-10-20"),
        ("Currency", "USD"),
        ("Description", "Sample goods - 10 units at USD 100.00"),
        ("Subtotal", "USD 1,000.00"),
        ("Tax", "USD 80.00"),
        ("Invoice Total", "USD 1,080.00"),
        ("Payment Received", f"USD {paid:,.2f}"),
        ("Amount Due", f"USD {1080-paid:,.2f}"),
    ]
    for index, (label, value) in enumerate(lines):
        y = 656 - index * 37
        pdf.setFont("Helvetica-Bold", 11)
        pdf.drawString(50, y, label + ":")
        pdf.setFont("Helvetica", 11)
        pdf.drawString(205, y, value)
    pdf.setFont("Helvetica", 9)
    pdf.drawString(50, 168, "Two invoice cases in one layout; this is not an accuracy benchmark.")
    pdf.drawString(50, 150, "Tax is an illustrative input. No actual transaction or tax advice.")
    pdf.save()


def parse_fields(text):
    fields = {}
    for field, label in (("invoice_total", "Invoice Total"), ("amount_due", "Amount Due")):
        match = re.search(re.escape(label) + r":\s*USD\s*([\d,]+\.\d{2})", text)
        fields[field] = match.group(1).replace(",", "") if match else None
    match = re.search(r"Invoice Number:\s*(INV-\d+)", text)
    fields["invoice_number"] = match.group(1) if match else None
    amounts = re.findall(r"USD\s*([\d,]+\.\d{2})", text)
    fields["naive_last_amount_as_total"] = amounts[-1].replace(",", "") if amounts else None
    return fields


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--output-dir", type=Path, required=True)
    args = parser.parse_args()
    out = args.output_dir
    out.mkdir(parents=True, exist_ok=True)
    if any(not shutil.which(tool) for tool in ("pdftoppm", "tesseract")):
        raise RuntimeError("pdftoppm and tesseract must be on PATH")
    report = {
        "scope": "Two synthetic invoice cases, one layout, each as native and image-only PDF. No AI model tested.",
        "versions": {
            "reportlab": reportlab.Version,
            "pypdf": pypdf.__version__,
            "Pillow": PIL.__version__,
            "tesseract": subprocess.run(["tesseract", "--version"], capture_output=True, text=True, check=True).stdout.splitlines()[0],
        },
        "settings": {"render_dpi": 200, "ocr_language": "eng", "ocr_engine": 1, "page_segmentation": 6},
        "results": [],
    }
    for name, number, paid in (("unpaid", "INV-1042", 0), ("part-paid", "INV-1043", 300)):
        native = out / (name + "-native.pdf")
        make_invoice(native, number, paid)
        render = out / name
        subprocess.run(["pdftoppm", "-r", "200", "-singlefile", "-png", str(native), str(render)], capture_output=True, check=True)
        image = out / (name + ".png")
        with Image.open(image) as img:
            img.convert("RGB").save(out / (name + "-image-only.pdf"), resolution=200)
        ocr = subprocess.run(["tesseract", str(image), "stdout", "--oem", "1", "-l", "eng", "--psm", "6"], capture_output=True, text=True, check=True).stdout
        (out / (name + "-ocr.txt")).write_text(ocr, encoding="utf-8")
        for source in ("native", "image-only"):
            pdf_path = out / (name + "-" + source + ".pdf")
            text = "\n".join(page.extract_text() or "" for page in PdfReader(pdf_path).pages)
            (out / (name + "-" + source + "-text.txt")).write_text(text, encoding="utf-8")
            expected = {"invoice_number": number, "invoice_total": "1080.00", "amount_due": f"{1080-paid:.2f}"}
            report["results"].append({
                "file": pdf_path.name,
                "sha256": hashlib.sha256(pdf_path.read_bytes()).hexdigest(),
                "expected": expected,
                "native_text_characters": len(text),
                "native_fields": parse_fields(text),
                "ocr_fields": parse_fields(ocr),
                "ocr_shared_page": image.name,
            })
    (out / "results.json").write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8")
    print(json.dumps(report, indent=2))


if __name__ == "__main__":
    main()
