#!/usr/bin/env python3
"""Modernize legacy CARBON command reports without inventing missing evidence.

This is deliberately a one-way presentation migration with recoverable backups.
It repairs report-generation defects from early builds: unbounded specialist
rosters, decorative unmeasured-stat cards, and empty WCAG/ACR companions emitted
by broad First Look runs. It never manufactures test results, run manifests, or
criterion outcomes.
"""

from __future__ import annotations

import argparse
import datetime as dt
import os
import re
import shutil
import tempfile
from pathlib import Path

from carbon_command_report import (
    REPORT_FAVICON,
    REPORT_THEME_CSS,
    SPECIALIST_IDENTITY_CSS,
    SPECIALISTS,
    carbon_lockup,
    render_document,
    render_specialists,
)
from carbon_stats import snapshot


MODERNIZED_MARKER = '<meta name="carbon-historical-modernization" content="2026-08-report-cleanup">'
SUPPORT_NAMES = ("-wcag-2-2-", "-accessibility-conformance-report-")
SPECIALIST_CSS = """
.specialist-section{margin:0 0 32px;border:1px solid var(--line);background:var(--panel);box-shadow:var(--shadow)}
.specialist-heading{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:18px 22px;border-bottom:1px solid var(--line)}
.specialist-heading span{color:var(--muted);font-size:10px;font-weight:850;letter-spacing:.11em;text-transform:uppercase}.specialist-heading strong{font-size:13px}
.specialist-deck{display:grid;grid-template-columns:minmax(0,1fr);gap:1px;background:var(--line)}
.specialist-card{display:grid;grid-template-columns:96px 1fr;gap:18px;min-height:154px;padding:20px;background:var(--panel-soft)}
.specialist-card img{width:96px;height:112px;object-fit:cover;filter:grayscale(1);border:1px solid var(--line-bright)}
.specialist-card span{color:var(--muted);font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.specialist-card h3{margin:5px 0 8px;font-size:24px;letter-spacing:-.04em}.specialist-card p{margin:0;color:var(--muted-strong);font-size:12px;line-height:1.52}.specialist-boundary{margin:0;padding:13px 20px;border-top:1px solid var(--line);color:var(--muted);font-size:11px}
.legacy-hero{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(260px,.65fr);gap:1px;margin:0 0 28px;border:1px solid var(--line);background:var(--line);box-shadow:var(--shadow)}.legacy-copy,.legacy-state{padding:clamp(28px,5vw,58px);background:var(--panel)}.legacy-copy h1{margin:10px 0 18px;font-size:clamp(40px,7vw,76px);line-height:.94;letter-spacing:-.06em}.legacy-copy p,.legacy-state p{color:var(--muted-strong);font-size:17px;line-height:1.58}.legacy-state strong{display:block;margin:12px 0;font-size:28px;color:var(--risk)}.legacy-next{margin:30px 0;border-left:3px solid var(--risk);padding:20px;background:var(--risk-soft)}.legacy-next h2{margin:0 0 9px;font-size:22px}.legacy-next p{margin:0;color:var(--muted-strong);line-height:1.55}@media(max-width:760px){.legacy-hero{grid-template-columns:1fr}.specialist-card{grid-template-columns:76px 1fr}.specialist-card img{width:76px;height:88px}}
"""


def atomic_write(path: Path, content: str) -> None:
    with tempfile.NamedTemporaryFile("w", encoding="utf-8", dir=path.parent, delete=False) as handle:
        handle.write(content)
        temporary = Path(handle.name)
    os.replace(temporary, path)


def profile_for(path: Path, source: str) -> tuple[str, list[str]]:
    name = path.name.lower()
    if "-carbon-review-" in name:
        return "jason", []
    if "privacy" in name:
        return "pete", ["privacy"]
    if any(token in name for token in SUPPORT_NAMES):
        return "alejandro", ["accessibility"]
    if "stats" in name:
        return "jason", []
    if "first look" in source.lower() or "carbon-f" in name:
        return "yuki", []
    return "jason", []


def inject_profile(source: str, specialist_id: str, domains: list[str]) -> str:
    profile = render_specialists([SPECIALISTS[specialist_id]], domains)
    source = re.sub(r'<section class="specialist-section"[^>]*>.*?</section>', profile, source, count=1, flags=re.S)
    if profile not in source:
        source = source.replace("</header>", "</header>" + profile, 1)
    source = re.sub(
        r'<section class="visual-section" aria-label="Activity visualizations">.*?</section>',
        lambda match: "" if "not measured" in match.group(0).lower() or "not estimated" in match.group(0).lower() else match.group(0),
        source,
        flags=re.S,
    )
    # A stale host can create companion artifacts with an older renderer. Do
    # not preserve links to files that were safely archived during this repair.
    def keep_existing_artifact(match: re.Match[str]) -> str:
        return match.group(0) if Path(match.group(1)).is_file() else ""

    source = re.sub(r'<a class="artifact-row" href="file://([^\"]+)">.*?</a>', keep_existing_artifact, source, flags=re.S)
    source = re.sub(r'<section class="artifact-section">\s*<div class="section-index">A</div><div class="section-body">.*?<div class="artifact-ledger">\s*</div>\s*</div>\s*</section>', "", source, flags=re.S)
    if "carbon-historical-modernization" not in source:
        source = source.replace("</head>", MODERNIZED_MARKER + "<style>" + SPECIALIST_CSS + "</style></head>", 1)
    return source


def support_notice(path: Path) -> str:
    kind = "Accessibility Conformance Report" if "conformance" in path.name else "WCAG 2.2 companion"
    profile = render_specialists([SPECIALISTS["alejandro"]], ["accessibility"])
    return f'''<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><meta name="color-scheme" content="dark"><link rel="icon" href="{REPORT_FAVICON}">{MODERNIZED_MARKER}<title>CARBON · {kind} · evidence required</title><style>{REPORT_THEME_CSS}{SPECIALIST_IDENTITY_CSS}{SPECIALIST_CSS}</style></head>
<body><main><header class="masthead">{carbon_lockup(kind)}<div class="masthead-meta"><span class="status-pill status-partial">Evidence required</span><span class="updated">Historical artifact modernized</span></div></header>
<section class="legacy-hero"><div class="legacy-copy"><p class="eyebrow">Historical companion artifact</p><h1>Criterion evidence was not captured.</h1><p>This broad First Look did not collect WCAG success-criterion observations, evaluation scope, or assistive-technology evidence. CARBON therefore does not present this file as a completed accessibility assessment or conformance disclosure.</p></div><aside class="legacy-state"><small>Document state</small><strong>Not a result</strong><p>The original scaffold is preserved in the report archive. This replacement prevents an empty template from being mistaken for a conformance claim.</p></aside></section>
{profile}<section class="legacy-next"><h2>What to run next</h2><p>Run <code>/carbon-accessibility</code> against the intended pages and complete flows to create a criterion-level WCAG 2.2 evidence report and a VPAT-aligned ACR working draft.</p></section><footer class="footer"><span>CARBON is a <a href="https://testers.ai">testers.ai</a> product.</span><span>Historical evidence boundary preserved.</span></footer></main></body></html>'''


def modernize(root: Path, apply: bool) -> dict[str, object]:
    reports = root / ".carbon" / "reports" / "commands"
    if not reports.is_dir():
        raise ValueError("no CARBON command report directory found")
    paths = sorted(reports.glob("*.html"))
    changes: list[str] = []
    backup_dir: Path | None = None
    if apply:
        stamp = dt.datetime.now(dt.timezone.utc).strftime("%Y%m%dT%H%M%SZ")
        backup_dir = root / ".carbon" / "reports" / "archive" / f"historical-modernization-{stamp}"
        backup_dir.mkdir(parents=True, exist_ok=True)

    stats_payload = snapshot(root, baseline_input=None, record_current=False)["reportPayload"]
    for path in paths:
        source = path.read_text(encoding="utf-8")
        stale_local_artifact = any(not Path(match).is_file() for match in re.findall(r'<a class="artifact-row" href="file://([^\"]+)">', source))
        if MODERNIZED_MARKER in source and not stale_local_artifact:
            continue
        if any(token in path.name for token in SUPPORT_NAMES):
            updated = support_notice(path)
            label = "replaced empty accessibility scaffold with evidence-required notice"
        elif "-carbon-stats-" in path.name:
            updated = render_document(root, stats_payload)
            updated = updated.replace("</head>", MODERNIZED_MARKER + "</head>", 1)
            label = "regenerated stats report from current project-local counters"
        else:
            specialist_id, domains = profile_for(path, source)
            updated = inject_profile(source, specialist_id, domains)
            label = f"reduced specialist attribution to AI {SPECIALISTS[specialist_id]['name']} and removed empty telemetry visuals"
        if updated == source:
            continue
        changes.append(f"{path.name}: {label}")
        if apply:
            assert backup_dir is not None
            shutil.copy2(path, backup_dir / path.name)
            atomic_write(path, updated)
    return {"root": str(root), "applied": apply, "backupDir": str(backup_dir) if backup_dir else None, "changes": changes}


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--root", default=".")
    parser.add_argument("--apply", action="store_true")
    args = parser.parse_args()
    root = Path(args.root).expanduser().resolve()
    if not root.is_dir():
        raise ValueError("root must be an existing project directory")
    import json
    print(json.dumps(modernize(root, args.apply), indent=2))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
