#!/usr/bin/env python3
import csv
import datetime
import fcntl
import pathlib
import re
import sys
from typing import Dict, List, Tuple

# Add root directory to path for imports
_current_root = pathlib.Path(sys.argv[1])
if str(_current_root) not in sys.path:
    sys.path.insert(0, str(_current_root))

root = pathlib.Path(sys.argv[1])
registry_path = pathlib.Path(sys.argv[2])
batch_dir = pathlib.Path(sys.argv[3])
sites_dir = pathlib.Path(sys.argv[4])
lock_path = pathlib.Path(sys.argv[5])
target_version = sys.argv[6]
batch_size = int(sys.argv[7])
input_file = pathlib.Path(sys.argv[8])

now = datetime.datetime.now().isoformat(timespec="seconds")


def read_site_themes() -> Dict[str, str]:
    themes = {}
    if input_file.exists():
        with input_file.open() as fh:
            reader = csv.reader(fh)
            for row in reader:
                if not row or not row[0].strip():
                    continue
                domain = row[0].strip()
                theme = row[1].strip() if len(row) > 1 else ""
                themes[domain] = theme
    return themes


def current_version(domain: str) -> int:
    versions = []
    for path in sites_dir.glob(f"{domain}-v*"):
        m = re.search(r"-v(\d+)$", path.name)
        if m:
            versions.append(int(m.group(1)))
    return max(versions) if versions else 0


def parse_registry() -> Dict[str, List[str]]:
    rows = {}
    if registry_path.exists():
        for line in registry_path.read_text().splitlines():
            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:
                    domain, title, desc, status, batch, updated = cols[:6]
                    rows[domain] = [domain, title, desc, status or "-", batch or "-", updated]
    return rows


def write_registry(rows: Dict[str, List[str]]):
    header = [
        "# SMaking Sites Registry (template)\n",
        "\n",
        "| Domain | Title | Description | Status | Batch | Updated |\n",
        "|--------|-------|-------------|--------|-------|---------|\n",
    ]
    body = [f"| {r[0]} | {r[1]} | {r[2]} | {r[3]} | {r[4]} | {r[5]} |\n" for r in sorted(rows.values(), key=lambda r: r[0])]
    footer = [
        "\n",
        "Status codes: none/- → B → d → D → O → i → I → Q\n",
        "\n",
        "Notes:\n",
        "- Status \"-\" means registered but not in design batch.\n",
        "- Design phases use B/d/D; implement phases use O/i/I/Q.\n",
        "- Update timestamps on each transition.\n",
    ]
    registry_path.write_text("".join(header + body + footer))


def next_batch_id() -> str:
    ids = []
    for path in batch_dir.glob("Batch_*.md"):
        m = re.search(r"Batch_(\d+)\.md", path.name)
        if m:
            ids.append(int(m.group(1)))
    for path in batch_dir.glob("batch-*-design.md"):
        m = re.search(r"batch-(\d+)-design\.md", path.name)
        if m:
            ids.append(int(m.group(1)))
    for path in batch_dir.glob("batch-*-implement.md"):
        m = re.search(r"batch-(\d+)-implement\.md", path.name)
        if m:
            ids.append(int(m.group(1)))
    return f"{(max(ids) + 1) if ids else 1:03d}"


target_version_num = int(target_version.lstrip("vV") or "1")
themes = read_site_themes()
lock_path.parent.mkdir(parents=True, exist_ok=True)
batch_dir.mkdir(parents=True, exist_ok=True)
skipped: List[str] = []

with lock_path.open("w") as lf:
    fcntl.flock(lf, fcntl.LOCK_EX)

    rows = parse_registry()
    candidates: List[Tuple[str, List[str]]] = []
    for domain, row in rows.items():
        highest = current_version(domain)
        status = row[3] or "-"
        batch = row[4] or "-"
        if highest >= target_version_num:
            skipped.append(f"{domain}: already at v{highest} (>= target {target_version})")
            continue
        if status != "-":
            skipped.append(f"{domain}: skipped due to existing status {status}")
            continue
        if batch not in ("", "-"):
            skipped.append(f"{domain}: skipped due to existing batch {batch}")
            continue
        candidates.append((domain, row))

    candidates = sorted(candidates, key=lambda x: x[0])[:batch_size]
    if not candidates:
        print("FAIL:no_eligible_sites:no sites available for new batch")
        fcntl.flock(lf, fcntl.LOCK_UN)
        sys.exit(1)

    batch_id = next_batch_id()
    if any(batch_id in (row[4] or "") for row in rows.values()):
        # If current batch id is already in registry, bump until unused
        current = int(batch_id)
        while any(f"{current:03d}" in (row[4] or "") for row in rows.values()):
            current += 1
        batch_id = f"{current:03d}"
    tracker_path = batch_dir / f"Batch_{batch_id}.md"

    tracker_lines = [
        f"# Batch {batch_id}\n",
        f"**Created**: {now}\n",
        f"**Target Version**: {target_version}\n",
        "| Domain | Theme | Status |\n",
        "|--------|-------|--------|\n",
    ]

    for domain, row in candidates:
        title, desc = row[1], row[2]
        row[3] = "B"
        row[4] = batch_id
        row[5] = now
        rows[domain] = row
        theme = themes.get(domain, "")
        tracker_lines.append(f"| {domain} | {theme} | B |\n")
        site_dir = sites_dir / f"{domain}-{target_version}"
        site_dir.mkdir(parents=True, exist_ok=True)

    write_registry(rows)
    tracker_path.write_text("".join(tracker_lines))
    fcntl.flock(lf, fcntl.LOCK_UN)

for msg in skipped:
    print(f"WARN:skip:{msg}")
print(f"OK:batch_created:{batch_id} ({len(candidates)} sites)")
