#!/usr/bin/env python3
"""Public structural/evidence checks for WEB010-LAB1.

This learner-contained checker does not encode the hidden layout solution. It verifies portability,
required lab surfaces, and whether the learner recorded inspectable evidence.
"""
from __future__ import annotations
import json
from pathlib import Path
import sys, argparse
ROOT=Path(__file__).resolve().parent
parser=argparse.ArgumentParser()
parser.add_argument("--structure-only",action="store_true",help="Check lab packaging/probes without requiring completed learner evidence.")
args=parser.parse_args()
STARTER=ROOT/"starter"; TRANSFER=ROOT/"transfer"; EVIDENCE=ROOT/"evidence"/"learner_evidence.json"
checks=[]
def check(name,ok,detail=""): checks.append((name,bool(ok),detail))
for rel in ["starter/index.html","starter/styles.css","starter/app.js","transfer/starter.html","transfer/styles.css","evidence/learner_evidence.json"]:
    check(f"required_file:{rel}",(ROOT/rel).is_file())
combined="\n".join(p.read_text(encoding="utf-8") for p in [STARTER/"index.html",STARTER/"styles.css",STARTER/"app.js",TRANSFER/"starter.html",TRANSFER/"styles.css"] if p.exists())
check("portable:no_external_http_dependency","http://" not in combined and "https://" not in combined)
check("fixture:direction_control_present",'data-action="direction"' in combined)
check("fixture:long_identifier_probe_present",'data-action="long-id"' in combined)
check("fixture:visual_reorder_probe_present",'data-action="reorder"' in combined)
required={"scenario_id","region","source_order_contract","layout_problem","chosen_model","state_constraint","responsive_rule","logical_property_decision","observed_overflow","observed_visual_order","observed_dom_source_order","default_focus_sequence_observation","observation","inference_or_decision","mutation","mutation_result","repair","repair_result","residual_limitation"}
try:
    data=json.loads(EVIDENCE.read_text(encoding="utf-8"))
except Exception as exc:
    check("evidence:valid_json",False,str(exc)); data={}
else: check("evidence:valid_json",True)
rows=data.get("rows",[]) if isinstance(data,dict) else []
if args.structure_only:
    check("evidence:starter_rows_allowed_empty",isinstance(rows,list),f"rows={len(rows)}")
else:
    check("evidence:has_rows",len(rows)>0,f"rows={len(rows)}")
    for i,row in enumerate(rows):
        missing=sorted(required-set(row)); blank=sorted(k for k in required if not str(row.get(k,"")).strip())
        check(f"evidence:row_{i+1}:required_fields",not missing,f"missing={missing}")
        check(f"evidence:row_{i+1}:nonblank_required_fields",not blank,f"blank={blank}")
    completion=data.get("completion",{}) if isinstance(data,dict) else {}
    for key in ["changed_context_completed","independent_decision_recorded","evidence_separates_observation_from_inference"]:
        check(f"evidence:completion:{key}",completion.get(key) is True)
passed=sum(ok for _,ok,_ in checks)
print(f"WEB010-LAB1 public checks: {passed}/{len(checks)} PASS")
for name,ok,detail in checks: print(f"{'PASS' if ok else 'FAIL'} | {name}"+(f" | {detail}" if detail else ""))
sys.exit(0 if passed==len(checks) else 1)
