#!/usr/bin/env python3.12
"""
Verify DESIGN.md files for a batch and mark completion in batch + REGISTRY with locking.
Exit codes: 0=success, 1=verification failed, 2=input error
"""
from __future__ import annotations

import argparse
import datetime
import fcntl
import pathlib
from typing import List, Optional

REQUIRED_HEADINGS = [
    "## Aesthetics and Tone",
    "## Layout Motifs and Structure",
    "## Typography and Palette",
    "## Imagery and Motifs",
    "## Prompts for Implementation",
    "## Uniqueness Notes",
]


def has_required(text: str) -> bool:
    return all(h in text for h in REQUIRED_HEADINGS)


def domain_from_cols(cols: List[str]) -> Optional[str]:
    if not cols:
        return None
    if len(cols) >= 2 and "/" in cols[0]:
        return cols[1] or cols[0]
    return cols[0]


def load_batch_domains(batch_path: pathlib.Path) -> List[str]:
    domains: List[str] = []
    in_main_table = False
    for line in batch_path.read_text(encoding="utf-8").splitlines():
        if line.startswith("| Directory") or line.startswith("| Domain | Theme |") or line.startswith("| Domain |"):
            in_main_table = True
            continue
        if line.startswith("|--------") and in_main_table:
            continue
        if line.strip() == "" or line.startswith("##"):
            in_main_table = False
        if in_main_table and line.startswith("|") and "Directory" not in line and "Domain" not in line:
            cols = [c.strip() for c in line.strip("|").split("|")]
            domain = domain_from_cols(cols)
            if domain:
                domains.append(domain)
    return domains


def update_batch(batch_path: pathlib.Path, domains: List[str]) -> None:
    lines = batch_path.read_text(encoding="utf-8").splitlines()
    updated: List[str] = []
    now = datetime.datetime.now().isoformat(timespec="seconds")
    for line in lines:
        if line.startswith("|") and "Domain" not in line and "--------" not in line:
            cols = [c.strip() for c in line.strip("|").split("|")]
            domain = domain_from_cols(cols) or ""
            if domain in domains:
                while len(cols) < 3:
                    cols.append("-")
                # status assumed at index 2 for both Directory|Domain|Status and Domain|Theme|Status layouts
                cols[2] = "D"
                line = "| " + " | ".join(cols) + " |"
        updated.append(line)
    updated.append(f"\nVerified: {now}")
    batch_path.write_text("\n".join(updated), encoding="utf-8")


def update_registry(registry: pathlib.Path, domains: List[str]) -> None:
    now = datetime.datetime.now().isoformat(timespec="seconds")
    lines = registry.read_text().splitlines()
    new_lines: List[str] = []
    for line in lines:
        if line.startswith("|") and "Domain" not in line and "--------" not in line:
            cols = [c.strip() for c in line.strip("|").split("|")]
            if len(cols) >= 6 and cols[0] in domains:
                cols[3] = "D"
                cols[5] = now
                line = f"| {cols[0]} | {cols[1]} | {cols[2]} | {cols[3]} | {cols[4]} | {cols[5]} |"
        new_lines.append(line)
    registry.write_text("\n".join(new_lines) + "\n")


def main() -> int:
    parser = argparse.ArgumentParser(description="Verify design batch and mark completion")
    parser.add_argument("--batch-id", help="Batch ID (e.g., 001). If omitted, use latest Batch_*.md")
    parser.add_argument("--root", default=".", help="Repo root (default: .)")
    args = parser.parse_args()

    root = pathlib.Path(args.root).resolve()
    batch_dir = root / ".smbatcher" / "batches"
    registry = root / ".smbatcher" / "REGISTRY.md"
    lock_path = root / ".smbatcher" / "REGISTRY.lock"

    batch_files = sorted(list(batch_dir.glob("Batch_*.md")) + list(batch_dir.glob("batch-*-design.md")))
    if not batch_files:
        print("ERROR:no_batch_files:.smbatcher/batches")
        return 2
    batch_path = None
    if args.batch_id:
        candidate = batch_dir / f"Batch_{args.batch_id}.md"
        if candidate.exists():
            batch_path = candidate
    if batch_path is None:
        batch_path = batch_files[-1]

    domains = load_batch_domains(batch_path)
    if not domains:
        print(f"ERROR:no_domains_in_batch:{batch_path}")
        return 2

    ok_domains: List[str] = []
    failed_domains: List[str] = []
    for domain in domains:
        design_path = root / "sites" / f"{domain}-v1" / "DESIGN.md"
        if not design_path.exists():
            print(f"WARN:missing_design:{domain}")
            failed_domains.append(domain)
            continue
        text = design_path.read_text(encoding="utf-8")
        if not has_required(text):
            print(f"WARN:missing_headings:{domain}")
            failed_domains.append(domain)
            continue
        ok_domains.append(domain)

    if not ok_domains:
        print(f"FAIL:no_designs_passed:{len(failed_domains)} failed")
        return 1

    lock_path.parent.mkdir(parents=True, exist_ok=True)
    with lock_path.open("w") as lf:
        fcntl.flock(lf, fcntl.LOCK_EX)
        update_batch(batch_path, ok_domains)
        if registry.exists():
            update_registry(registry, ok_domains)
        fcntl.flock(lf, fcntl.LOCK_UN)

    print(f"OK:verified:{len(ok_domains)} designs ({', '.join(ok_domains)})")
    return 0


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