#!/usr/bin/env python3
from pathlib import Path
import argparse,shutil,re

p=argparse.ArgumentParser(description="Create one deliberate WEB019 failure mutation in a disposable copy of a repaired submission. No browser/AT verdict is produced.")
p.add_argument('--mutation',choices=['no-dir','no-isolation','reverse-source'],required=True)
p.add_argument('--source',default='learner/submission')
p.add_argument('--output',default='mutated')
a=p.parse_args()
HERE=Path(__file__).resolve().parent
ROOT=HERE if (HERE/'learner').is_dir() else HERE.parent
src=(ROOT/a.source).resolve(); out=(ROOT/a.output).resolve()
if not src.is_dir(): raise SystemExit('Source directory not found. Copy learner/starter to learner/submission, repair it, then mutate that disposable source.')
if src==out: raise SystemExit('Output must differ from source; mutation is disposable and must never overwrite the repaired submission.')
if out.exists(): shutil.rmtree(out)
shutil.copytree(src,out)
html=out/'index.html'; css=out/'styles.css'; js=out/'app.js'
if not html.is_file() or not js.is_file(): raise SystemExit('Expected index.html and app.js in the submission source.')

if a.mutation=='no-dir':
    t=html.read_text(encoding='utf-8')
    t,n=re.subn(r'\s+dir=["\']rtl["\']','',t,flags=re.I)
    if n<1: raise SystemExit('Mutation no-dir made no change: no dir="rtl" boundary was found.')
    html.write_text(t,encoding='utf-8')
    c=css.read_text(encoding='utf-8') if css.is_file() else ''
    c += '\n/* WEB019 MUTATION no-dir: visual alignment-only compensation; intentionally not a direction repair. */\n.account,.support{ text-align:right; }\n'
    css.write_text(c,encoding='utf-8')
elif a.mutation=='no-isolation':
    t=html.read_text(encoding='utf-8')
    t,n=re.subn(r'<bdi\b[^>]*>(.*?)</bdi>',r'<span>\1</span>',t,flags=re.I|re.S)
    if n<1: raise SystemExit('Mutation no-isolation made no change: no <bdi> isolation boundary was found.')
    html.write_text(t,encoding='utf-8')
elif a.mutation=='reverse-source':
    t=html.read_text(encoding='utf-8')
    if len(re.findall(r'id=["\']notice["\']',t,re.I))!=1:
        raise SystemExit('Mutation reverse-source requires exactly one #notice target.')
    j=js.read_text(encoding='utf-8')
    patch="\n/* WEB019 MUTATION reverse-source: deliberate runtime DOM-order corruption for diagnosis only. */\nwindow.addEventListener('DOMContentLoaded', () => {\n  const notice = document.querySelector('#notice');\n  if (!notice) throw new Error('WEB019 reverse-source target #notice missing');\n  const nodes = Array.from(notice.childNodes);\n  nodes.reverse().forEach((node) => notice.appendChild(node));\n  window.WEB019_MUTATION = 'reverse-source';\n});\n"
    js.write_text(j+patch,encoding='utf-8')

print(f'Created {a.mutation} mutation at {out}')
print('Predict first; then observe in your named environment. This tool proves only that the requested source mutation was applied; it does not certify rendering or AT behavior.')
