#!/usr/bin/env bash
# Gate visual + acessibilidade: captura os checkpoints do manifesto com sniffCSS,
# compara contra os baselines (delta) e roda as regras WCAG/UX.
#
# Comportamento:
#   - DELTA visual (changed/added/removed vs baseline) é o GATE RÍGIDO:
#     qualquer mudança falha o script (exit 1).
#   - A11y é REPORTADO por padrão (pass/warn/fail por checkpoint, sem falhar),
#     com SNIFF_A11Y_STRICT=1 vira gate rígido também.
#   - contrast-aaa é sempre ignorado (meta opcional; o mandatório é AA).
#
# Uso: bash scripts/sniff-visuals.sh
# Variáveis: SNIFF_TOLERANCE (default 0.5), SNIFF_IGNORE_PROPS (ex: transform,opacity),
#            SNIFF_A11Y_STRICT (1 para falhar em falhas a11y reais)
set -uo pipefail

DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$DIR"
MANIFEST="$DIR/sniff/manifest.json"
TOLERANCE="${SNIFF_TOLERANCE:-0.5}"
IGNORE="${SNIFF_IGNORE_PROPS:-transform,opacity}"
A11Y_STRICT="${SNIFF_A11Y_STRICT:-0}"

[ -f "$MANIFEST" ] || { echo "Manifesto não encontrado: $MANIFEST (rode o teste primeiro)"; exit 1; }

mkdir -p "$DIR/sniff/current"

python3 - "$MANIFEST" "$DIR" "$TOLERANCE" "$IGNORE" "$A11Y_STRICT" <<'PY'
import json, re, subprocess, sys, os

manifest_path, base_dir, tolerance, ignore, a11y_strict = sys.argv[1:6]
checkpoints = json.load(open(manifest_path))
cap_dir = os.path.join(base_dir, 'sniff', 'current')
base_dir_b = os.path.join(base_dir, 'sniff', 'baselines')
CAPTURE = ['sniffCSS', '--no-summary', '--depth', '12', '--wait', 'network-idle:800']

failures = []
a11y_report = []

for cp in checkpoints:
    label, url, selector = cp['label'], cp['url'], cp['selector']
    baseline = os.path.join(base_dir_b, f'{label}.jsonl')
    current = os.path.join(cap_dir, f'{label}.jsonl')

    if not os.path.exists(baseline):
        print(f'[skip] {label}: sem baseline (rode scripts/sniff-baseline.sh)')
        continue

    print(f'== checkpoint: {label} ({selector}) ==')

    # 1) Delta visual vs baseline — GATE RÍGIDO
    with open(current, 'w') as fh:
        subprocess.run([*CAPTURE, '-u', url, '-s', selector], stdout=fh, check=True)

    diff = subprocess.run(
        ['sniffCSS-diff', baseline, current, '--stats-only', '--tolerance', tolerance,
         '--ignore-props', ignore],
        capture_output=True, text=True)
    stats = (diff.stdout or diff.stderr).strip()
    print('[delta]', stats)
    m = re.search(r'changed:\s*(\d+).*?added:\s*(\d+).*?removed:\s*(\d+).*?actions_changed:\s*(\d+)', stats)
    if m:
        changed, added, removed, actions = map(int, m.groups())
        if changed + added + removed + actions > 0:
            failures.append(f'{label}: delta visual (changed={changed} added={added} removed={removed} actions={actions})')
    else:
        failures.append(f'{label}: não foi possível interpretar o delta')

    # 2) Regras a11y/UX derivadas — reporte (ou gate se SNIFF_A11Y_STRICT=1)
    check = subprocess.run(['sniffCSS-check', '--input', current, '--rules'], capture_output=True, text=True)
    out = (check.stdout or '').strip()
    if out:
        lines = [l for l in out.splitlines() if l.strip().startswith('{')]
        n_fail = 0
        fail_details = []
        for l in lines:
            try:
                d = json.loads(l)
            except json.JSONDecodeError:
                continue
            if d.get('status') == 'fail' and d.get('check') != 'contrast-aaa':
                n_fail += 1
                fail_details.append(f'{d.get("check")}: {d.get("selector")}')
        n_warn = sum(1 for l in lines if '"status":"warn"' in l)
        n_pass = sum(1 for l in lines if '"status":"pass"' in l)
        tag = 'FAIL' if a11y_strict == '1' and n_fail else 'reporte'
        print(f'[a11y] {n_pass} pass, {n_warn} warn, {n_fail} fail ({tag}; AAA opcional ignorado)')
        if n_fail:
            a11y_report.append({'checkpoint': label, 'fails': fail_details})
        if a11y_strict == '1' and n_fail:
            failures.append(f'{label}: {n_fail} regra(s) a11y/UX falhando')

if failures:
    print('\nFALHAS:')
    for f in failures:
        print('  -', f)
    sys.exit(1)

if a11y_report:
    print('\nA11Y (reporte):')
    for r in a11y_report:
        print(f'  - {r["checkpoint"]}: {len(r["fails"])} falha(s)')
        for fd in r['fails'][:5]:
            print(f'      {fd[:160]}')
    print('  (use SNIFF_A11Y_STRICT=1 para tornar estas falhas em gate)')

print('\nGate visual: OK')
PY
exit $?