"""Generate font_assets.py stub and font_assets.pyi type stub for font packs."""

from __future__ import annotations

from pathlib import Path
from typing import Any

STUB_TEMPLATE = '''"""Font assets for {pack_name}. Auto-generated by pack-tools -- do not edit."""
from justmytype.font_catalog import create_catalog as _create_catalog
_catalog = _create_catalog(package=__package__)
def __getattr__(name):
    return getattr(_catalog, name)
'''

PYI_HEADER = """from justmytype.font_catalog import FontCatalog, FontFamily
from justmytype.types import FontInfo

"""

PYI_FIND_SIG = "def find(*, family: str, style: str | None = ..., weight: int | None = ..., postscript_name: str | None = ...) -> FontInfo | None: ..."
PYI_LIST_FAMILIES = "def list_families() -> tuple[str, ...]: ..."


def _unique_families_from_manifest(manifest: dict[str, Any]) -> list[str]:
    """Return unique family names in order of first appearance (matches create_catalog)."""
    seen: set[str] = set()
    result: list[str] = []
    for entry in manifest.get("fonts") or []:
        if not isinstance(entry, dict):
            continue
        family = (entry.get("family") or "").strip()
        if family and family not in seen:
            seen.add(family)
            result.append(family)
    return result


def _normalized_family_attrs(manifest: dict[str, Any]) -> list[str]:
    """Return Python attribute names for each family (same logic as justmytype.font_catalog)."""
    try:
        from justmytype.font_catalog import _normalize_family_with_collisions
    except ImportError as e:
        raise ImportError(
            "justmytype>=0.5.0 is required for font_assets generation. Install with: pip install justmytype>=0.5.0"
        ) from e
    families = _unique_families_from_manifest(manifest)
    seen_norm: dict[str, str] = {}
    return [_normalize_family_with_collisions(fam, seen_norm) for fam in families]


def generate_font_assets_stub(package_dir: Path, pack_name: str) -> Path:
    """Write font_assets.py stub into package_dir. Return path to written file."""
    package_dir = Path(package_dir)
    package_dir.mkdir(parents=True, exist_ok=True)
    out = package_dir / "font_assets.py"
    out.write_text(
        STUB_TEMPLATE.format(pack_name=pack_name).strip() + "\n",
        encoding="utf-8",
    )
    return out


def generate_font_assets_pyi(package_dir: Path, manifest: dict[str, Any]) -> Path:
    """Write font_assets.pyi type stub from manifest. Return path to written file."""
    package_dir = Path(package_dir)
    package_dir.mkdir(parents=True, exist_ok=True)
    lines = [PYI_HEADER]
    for attr in _normalized_family_attrs(manifest):
        lines.append(f"{attr}: FontFamily\n")
    lines.append("all_assets: tuple[FontInfo, ...]\n")
    lines.append("by_postscript: dict[str, FontInfo]\n")
    lines.append(PYI_FIND_SIG + "\n")
    lines.append(PYI_LIST_FAMILIES + "\n")
    out = package_dir / "font_assets.pyi"
    out.write_text("".join(lines), encoding="utf-8")
    return out
