#!/usr/bin/env python3
from pathlib import Path
import argparse, json, re, sys
parser=argparse.ArgumentParser(description="WEB013-LAB1 public structural/evidence checker. It does not certify browser accessibility.")
parser.add_argument("--structure-only", action="store_true", help="Validate the untouched starter package before repair; empty evidence is allowed.")
a=parser.parse_args()
ROOT=Path(__file__).resolve().parent.parent
required=[
"learner/starter/index.html","learner/starter/styles.css","learner/starter/app.js",
"learner/transfer/starter.html","learner/transfer/styles.css","learner/transfer/app.js",
"learner/evidence/learner_evidence.json"]
fields=[
"scenario_id","contract_step","primitive","expected_keyboard_path","semantic_mechanism",
"focus_before","focus_after","focus_visible_observation","keyboard_observation","dom_or_browser_observation",
"mutation","prediction","observed_failure","diagnosis","repair","post_repair_observation",
"changed_context","observation_vs_inference","environment","residual_limitation"]
checks=[]
def add(name,ok,detail=""): checks.append((name,bool(ok),detail))
def meaningful(v):
    if v is None: return False
    if isinstance(v,str): return bool(v.strip())
    if isinstance(v,dict): return bool(v) and any(meaningful(x) for x in v.values())
    if isinstance(v,(list,tuple)): return bool(v) and any(meaningful(x) for x in v)
    return True
for rel in required: add("required_file:"+rel,(ROOT/rel).is_file())
blob="\n".join((ROOT/r).read_text(encoding="utf-8") for r in required if (ROOT/r).is_file() and (ROOT/r).suffix in {".html",".css",".js"})
add("portable:no_external_http_dependency",not re.search(r"https?://",blob,re.I))
starter=(ROOT/'learner/starter/index.html').read_text(encoding='utf-8')
add("fixture:native_invoker_present",'id="open-filters"' in starter)
add("fixture:dialog_present",'<dialog' in starter)
if a.structure_only:
    add("fixture:intentional_pointer_only_probe_present",'role="button"' in starter)
try:
    data=json.loads((ROOT/'learner/evidence/learner_evidence.json').read_text(encoding='utf-8'))
    add("evidence:valid_json",True)
    rows=data.get("rows")
    add("evidence:rows_is_list",isinstance(rows,list))
    if a.structure_only:
        add("evidence:starter_rows_allowed_empty",isinstance(rows,list) and len(rows)==0,"rows="+str(len(rows) if isinstance(rows,list) else 'not-list'))
    else:
        add("evidence:submission_rows_present",isinstance(rows,list) and len(rows)>0,"rows="+str(len(rows) if isinstance(rows,list) else 'not-list'))
        if isinstance(rows,list) and rows:
            missing=[]
            for i,row in enumerate(rows):
                for f in fields:
                    if not meaningful(row.get(f)): missing.append(f"row {i}:{f}")
            add("evidence:all_required_fields_meaningful",not missing,", ".join(missing[:12]))
            add("evidence:mutation_row_present",any(meaningful(r.get('mutation')) and meaningful(r.get('observed_failure')) and meaningful(r.get('repair')) and meaningful(r.get('post_repair_observation')) for r in rows))
            add("evidence:changed_context_row_present",any(meaningful(r.get('changed_context')) for r in rows))
        env=data.get('environment',{})
        add("evidence:top_level_environment_recorded",isinstance(env,dict) and all(meaningful(env.get(k)) for k in ['browser','version','os','input_mode']))
except Exception as e:
    add("evidence:valid_json",False,str(e))
print(f"WEB013-LAB1 public checks: {sum(ok for _,ok,_ in checks)}/{len(checks)} PASS")
for n,ok,d in checks: print(("PASS" if ok else "FAIL")+" | "+n+(" | "+d if d else ""))
print("NOTE | Structural/evidence checks only; direct browser observations remain learner evidence and are not certified by this script.")
raise SystemExit(0 if all(ok for _,ok,_ in checks) else 1)
