#!/usr/bin/env python3
"""
Fase A · rename batch (2026-05-19):
  - ente-* → arje-*  (25 crates: protocol/init/runtime/compat)
  - vista  → revista (vista-core/web → revista-core/web)
  - pluma  → fana    (pluma-md → fana-md, pluma-reader-web → fana-md-reader-web)

Reusa el patrón de scripts/reorg.py + rename-chasqui.py.

Uso:
  python3 scripts/rename-fase-a.py --dry-run
  python3 scripts/rename-fase-a.py
"""

import os, re, subprocess, sys
from pathlib import Path

ROOT = Path("/home/sergio/brahman")
DRY = "--dry-run" in sys.argv

# ============================================================
# MOVES — leaf crate dirs, old → new (git_mv crea dirs padre)
# ============================================================
MOVES: dict[str, str] = {}

ENTE = {
    "protocol": ["ente-card"],
    "init":     ["ente-zero", "ente-kernel", "ente-soma",
                 "ente-snapshot", "ente-incarnate"],
    "runtime":  ["ente-bus", "ente-cas", "ente-wasm",
                 "ente-brain", "ente-echo"],
    "compat":   ["ente-logind-compat", "ente-hostnamed-compat",
                 "ente-timedated-compat", "ente-localed-compat",
                 "ente-journald-compat", "ente-resolved-compat",
                 "ente-polkit-compat", "ente-machined-compat",
                 "ente-systemd1-compat", "ente-notify-compat",
                 "ente-timer-compat", "ente-tmpfiles-compat",
                 "ente-binfmt-compat", "ente-policy-provider"],
}
for layer, crates in ENTE.items():
    for c in crates:
        new = c.replace("ente-", "arje-", 1)
        MOVES[f"crates/{layer}/{c}"] = f"crates/{layer}/{new}"

# vista → revista
MOVES["crates/modules/vista/vista-core"] = "crates/modules/revista/revista-core"
MOVES["crates/modules/vista/vista-web"]  = "crates/modules/revista/revista-web"
# pluma → fana
MOVES["crates/modules/pluma/pluma-md"]         = "crates/modules/fana/fana-md"
MOVES["crates/modules/pluma/pluma-reader-web"] = "crates/modules/fana/fana-md-reader-web"

# SDD.md de los módulos renombrados
SDD_MOVES = {
    "crates/modules/vista/SDD.md": "crates/modules/revista/SDD.md",
    "crates/modules/pluma/SDD.md": "crates/modules/fana/SDD.md",
}

# ============================================================
# PKG_RENAMES — nombres de paquete viejo → nuevo
# ============================================================
PKG_RENAMES: dict[str, str] = {}
for layer, crates in ENTE.items():
    for c in crates:
        PKG_RENAMES[c] = c.replace("ente-", "arje-", 1)
PKG_RENAMES["ente-journalctl"] = "arje-journalctl"   # bin name especial
PKG_RENAMES["vista-core"] = "revista-core"
PKG_RENAMES["vista-web"]  = "revista-web"
PKG_RENAMES["pluma-md"]   = "fana-md"
PKG_RENAMES["pluma-reader-web"] = "fana-md-reader-web"

# ============================================================
# Helpers
# ============================================================
def sh(cmd, check=True):
    if DRY:
        print(f"  DRY: {' '.join(cmd)}")
        return None
    return subprocess.run(cmd, check=check, cwd=str(ROOT))

def git_mv(src: str, dst: str):
    src_p, dst_p = ROOT / src, ROOT / dst
    if not src_p.exists():
        print(f"  SKIP {src} (no existe)")
        return
    if dst_p.exists():
        print(f"  WARN {dst} ya existe — saltando")
        return
    dst_p.parent.mkdir(parents=True, exist_ok=True)
    sh(["git", "mv", src, dst])

def all_cargo_tomls():
    return [p for p in (ROOT / "crates").rglob("Cargo.toml") if "target" not in p.parts]

def all_rs():
    return [p for p in (ROOT / "crates").rglob("*.rs") if "target" not in p.parts]

CURRENT_TO_OLD = {new: old for old, new in MOVES.items()}

def owner_old_for(toml: Path) -> str:
    cur = str(toml.parent.relative_to(ROOT))
    return CURRENT_TO_OLD.get(cur, cur)

def resolve_canon(base_dir: str, rel: str):
    try:
        return str((ROOT / base_dir / rel).resolve().relative_to(ROOT))
    except ValueError:
        return None

def map_target(old_tgt: str) -> str:
    return MOVES.get(old_tgt, old_tgt)

def rewrite_paths_in_toml(toml: Path):
    text = toml.read_text()
    owner_old = owner_old_for(toml)
    owner_new = str(toml.parent.relative_to(ROOT))

    def repl(m):
        rel_in_file = m.group(1)
        for base in (owner_old, owner_new):
            tgt = resolve_canon(base, rel_in_file)
            if tgt is None:
                continue
            new_tgt = map_target(tgt)
            if (ROOT / new_tgt).exists() or new_tgt != tgt:
                new_rel = os.path.relpath(str(ROOT / new_tgt), str(ROOT / owner_new))
                return f'path = "{new_rel}"'
        return m.group(0)

    new_text = re.sub(r'path\s*=\s*"([^"]+)"', repl, text)
    if new_text != text:
        if DRY: print(f"  DRY paths: {toml.relative_to(ROOT)}")
        else:   toml.write_text(new_text)

def rewrite_pkg_names_in_toml(toml: Path):
    text = toml.read_text()
    orig = text
    for old, new in sorted(PKG_RENAMES.items(), key=lambda kv: -len(kv[0])):
        old_us, new_us = old.replace("-", "_"), new.replace("-", "_")
        # name = "old" / "old_us"  (package, lib, bin)
        text = re.sub(rf'(\bname\s*=\s*)"{re.escape(old)}"', rf'\1"{new}"', text)
        text = re.sub(rf'(\bname\s*=\s*)"{re.escape(old_us)}"', rf'\1"{new_us}"', text)
        text = re.sub(rf'(\bpackage\s*=\s*)"{re.escape(old)}"', rf'\1"{new}"', text)
        # dep key al inicio de línea
        text = re.sub(rf'^([ \t]*){re.escape(old)}(\s*=)', rf'\1{new}\2',
                      text, flags=re.MULTILINE)
        # features / strings
        text = re.sub(rf'"dep:{re.escape(old)}"', f'"dep:{new}"', text)
        text = re.sub(rf'"{re.escape(old)}/', f'"{new}/', text)
        text = re.sub(rf'"{re.escape(old)}"', f'"{new}"', text)
    if text != orig:
        if DRY: print(f"  DRY names: {toml.relative_to(ROOT)}")
        else:   toml.write_text(text)

USE_RENAMES = {k.replace("-", "_"): v.replace("-", "_") for k, v in PKG_RENAMES.items()}

def rewrite_imports_in_rs(rs: Path):
    text = rs.read_text()
    orig = text
    for old, new in sorted(USE_RENAMES.items(), key=lambda kv: -len(kv[0])):
        text = re.sub(rf'(?<![A-Za-z0-9_]){re.escape(old)}(?![A-Za-z0-9_])', new, text)
    if text != orig:
        if DRY: print(f"  DRY imports: {rs.relative_to(ROOT)}")
        else:   rs.write_text(text)

def rewrite_workspace_toml():
    p = ROOT / "Cargo.toml"
    text = p.read_text()
    orig = text
    for old, new in MOVES.items():
        text = text.replace(f'"{old}"', f'"{new}"')
    for old, new in PKG_RENAMES.items():
        text = re.sub(rf'^([ \t]*){re.escape(old)}(\s*=)', rf'\1{new}\2',
                      text, flags=re.MULTILINE)
    # Comentarios de sección
    text = text.replace("(era yahweh)", "(era yahweh)")  # no-op, placeholder
    text = text.replace("# modules/vista/ — Deck horizontal swipe (Flutter PageView)",
                        "# modules/revista/ — Deck horizontal swipe (Flutter PageView)")
    text = text.replace("# modules/pluma/ — Markdown agnóstico + visor web",
                        "# modules/fana/ — Writer DAG editor (absorbe pluma)")
    if text != orig:
        if DRY: print("  DRY workspace toml")
        else:   p.write_text(text)

def cleanup_empty(rel_dir: str):
    d = ROOT / rel_dir
    if d.exists() and d.is_dir() and not any(d.iterdir()):
        if DRY: print(f"  DRY rmdir {rel_dir}")
        else:   d.rmdir()

def run():
    print(f"=== rename-fase-a.py (DRY={DRY}) ===")
    print(f"  {len(MOVES)} moves, {len(PKG_RENAMES)} pkg renames")

    print("\n-- step 1: git mv crates --")
    for old, new in MOVES.items():
        git_mv(old, new)

    print("\n-- step 2: git mv SDDs --")
    for old, new in SDD_MOVES.items():
        git_mv(old, new)

    print("\n-- step 3: cleanup dirs vacíos --")
    cleanup_empty("crates/modules/vista")
    cleanup_empty("crates/modules/pluma")

    print("\n-- step 4: package names --")
    for toml in all_cargo_tomls():
        rewrite_pkg_names_in_toml(toml)

    print("\n-- step 5: paths relativos --")
    for toml in all_cargo_tomls():
        rewrite_paths_in_toml(toml)

    print("\n-- step 6: imports .rs --")
    for rs in all_rs():
        rewrite_imports_in_rs(rs)

    print("\n-- step 7: workspace Cargo.toml --")
    rewrite_workspace_toml()

    print("\nOK")

if __name__ == "__main__":
    run()
