"""Regenera el appicon.ico de todas las apps C++ que declaren bloque icon: en su app.md."""

import os
import sys
from pathlib import Path
from typing import Optional

import yaml

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

from infra.generate_app_icon import generate_app_icon


def _find_registry_root() -> Path:
    env_root = os.environ.get("FN_REGISTRY_ROOT")
    if env_root:
        return Path(env_root).resolve()
    current = Path(__file__).resolve()
    for parent in current.parents:
        if (parent / "registry.db").exists():
            return parent
    raise FileNotFoundError("registry.db no encontrado; define FN_REGISTRY_ROOT")


def _read_frontmatter(md_path: Path) -> Optional[dict]:
    text = md_path.read_text(encoding="utf-8")
    if not text.startswith("---"):
        return None
    end = text.find("\n---", 3)
    if end < 0:
        return None
    try:
        return yaml.safe_load(text[3:end])
    except yaml.YAMLError:
        return None


def _iter_cpp_app_mds(root: Path):
    for pattern in ("apps/*/app.md", "projects/*/apps/*/app.md"):
        for md in sorted(root.glob(pattern)):
            fm = _read_frontmatter(md)
            if not fm or fm.get("lang") != "cpp":
                continue
            yield md, fm


def regenerate_app_icons(
    only: Optional[list[str]] = None,
    style: str = "fill_white",
) -> dict:
    """Recorre apps C++ con bloque icon: en su frontmatter y regenera appicon.ico.

    Args:
        only: Lista opcional de nombres de app a filtrar (campo `name`). Si None,
            procesa todas las apps C++ con `icon:` declarado.
        style: Estilo del icono. "fill_white" (default, glyph blanco) o
            "adaptive_duotone" (glyph duotone con tono claro/oscuro segun
            luminancia del accent). Ver generate_app_icon.

    Returns:
        dict con keys: ok (list[str]), skipped (list[dict]), failed (list[dict]).
    """
    root = _find_registry_root()
    ok, skipped, failed = [], [], []

    for md, fm in _iter_cpp_app_mds(root):
        name = fm.get("name", md.parent.name)
        if only and name not in only:
            continue
        icon = fm.get("icon")
        if not icon or not isinstance(icon, dict):
            skipped.append({"name": name, "reason": "no icon: block"})
            continue
        phosphor = icon.get("phosphor")
        accent = icon.get("accent")
        if not phosphor or not accent:
            skipped.append({"name": name, "reason": "icon: missing phosphor/accent"})
            continue
        out_ico = md.parent / "appicon.ico"
        try:
            generate_app_icon(
                phosphor_icon_name=phosphor,
                accent_hex=accent,
                out_ico_path=str(out_ico),
                style=style,
            )
            ok.append(name)
        except Exception as e:
            failed.append({"name": name, "error": str(e)})

    return {"ok": ok, "skipped": skipped, "failed": failed}


if __name__ == "__main__":
    args = sys.argv[1:]
    style = "fill_white"
    only = []
    for a in args:
        if a.startswith("--style="):
            style = a.split("=", 1)[1]
        elif a == "--adaptive":
            style = "adaptive_duotone"
        elif a == "--white":
            style = "white_duotone"
        else:
            only.append(a)
    only = only or None
    result = regenerate_app_icons(only=only, style=style)
    for name in result["ok"]:
        print(f"OK   {name}")
    for s in result["skipped"]:
        print(f"SKIP {s['name']}: {s['reason']}")
    for f in result["failed"]:
        print(f"FAIL {f['name']}: {f['error']}")
    sys.exit(1 if result["failed"] else 0)
