#!/usr/bin/env python3
"""
coa-photo-check: check fields an AI read off a COA photo, before anyone uses them.

  python3 check.py samples/extracted-clean.json samples/label.json
  python3 check.py samples/extracted-bad-naive.json samples/label.json
  python3 check.py --self-test

Checks, in plain code (no AI):
  1. Every field is present and none says UNREADABLE.
  2. Total THC adds up: total = d9-THC + 0.877 x THCa (within 0.05 points). A misread digit usually breaks this.
  3. The label matches the COA: same batch, total THC and total CBD within 0.1 points.
Exit code 0 only if nothing is flagged. Standard library only. From Distru's No Bullshit AI Course. MIT.

The 0.877 factor is the standard decarboxylation conversion; check your state's rule for how total THC
must be reported. This script flags; a person decides.
"""
import json, re, sys

REQUIRED = ["sample", "batch", "report_date", "thca_pct", "d9_thc_pct", "total_thc_pct", "total_cbd_pct", "yeast_mold", "overall_result"]


def num(v):
    """'24.81 %' -> 24.81; 'ND' -> 0.0; anything unreadable -> None."""
    if v is None:
        return None
    s = str(v).strip().upper()
    if s in ("ND", "<LOQ"):
        return 0.0
    m = re.search(r"-?\d+(?:\.\d+)?", s.replace(",", ""))
    return float(m.group()) if m else None


def check(coa, label=None):
    flags = []
    for k in REQUIRED:
        v = coa.get(k)
        if v is None or str(v).strip() == "":
            flags.append(f"missing: {k}")
        elif "UNREADABLE" in str(v).upper():
            flags.append(f"unreadable on the photo: {k} (get a clearer photo or the lab's PDF)")
    thca, d9, total = num(coa.get("thca_pct")), num(coa.get("d9_thc_pct")), num(coa.get("total_thc_pct"))
    if None not in (thca, d9, total):
        expected = d9 + 0.877 * thca
        if abs(expected - total) > 0.05:
            flags.append(f"total THC does not add up: {d9} + 0.877 x {thca} = {expected:.2f}, but the photo says {total}. A digit was probably misread.")
    if str(coa.get("overall_result", "")).upper() not in ("PASS", "UNREADABLE", ""):
        flags.append(f"overall result is {coa.get('overall_result')!r}: do not sell until compliance has seen it")
    if label:
        if label.get("batch") and label["batch"] != coa.get("batch"):
            flags.append(f"batch differs: label {label['batch']!r}, COA {coa.get('batch')!r}")
        for k in ("total_thc_pct", "total_cbd_pct"):
            a, b = num(label.get(k)), num(coa.get(k))
            if a is not None and b is not None and abs(a - b) > 0.1:
                flags.append(f"{k} differs: label {a}, COA {b}")
    return flags


def self_test():
    good = {"sample": "x", "batch": "B1", "report_date": "d", "thca_pct": "24.81 %", "d9_thc_pct": "0.87 %",
            "total_thc_pct": "22.63 %", "total_cbd_pct": "0.05 %", "yeast_mold": "<1,000 CFU/g", "overall_result": "PASS"}
    assert check(good, {"batch": "B1", "total_thc_pct": "22.6"}) == [], "clean COA should pass"
    bad = dict(good, thca_pct="24.91", total_thc_pct="22.53")
    assert any("does not add up" in f for f in check(bad)), "misread should break the sum"
    assert any("unreadable" in f for f in check(dict(good, total_cbd_pct="UNREADABLE"))), "unreadable flagged"
    assert any("batch differs" in f for f in check(good, {"batch": "B2"})), "batch mismatch flagged"
    print("self-test ok · sums, unreadable fields, label comparison")


if __name__ == "__main__":
    args = sys.argv[1:]
    if "--self-test" in args:
        self_test(); sys.exit(0)
    if not args:
        print(__doc__); sys.exit(1)
    coa = json.load(open(args[0]))
    label = json.load(open(args[1])) if len(args) > 1 else None
    flags = check(coa, label)
    if flags:
        print(f"{len(flags)} flag(s) for a person to look at:")
        for f in flags:
            print("  - " + f)
        sys.exit(2)
    print("no flags: the fields are complete, add up, and match the label")
