"""Icon font set registry mapping semantic names to font families and glyph codepoints.

Each icon set maps semantic glyph names (check, arrow, warning, etc.) to their
Unicode codepoints in the font's Private Use Area. The subsetter uses these
codepoints to create minimal font subsets (~4-15KB) for template embedding.
"""

from __future__ import annotations

from dataclasses import dataclass, field


@dataclass(frozen=True, slots=True)
class IconSetConfig:
    """Configuration for a vendored icon font."""

    family: str
    """Font family name as it appears in the font's name table."""

    ttf_filename: str
    """Filename within the vendored fonts directory (e.g. ``<set>/font.ttf``)."""

    glyph_map: dict[str, int] = field(default_factory=dict)
    """Mapping of semantic icon names to Unicode codepoints."""

    def characters_for(self, names: list[str] | None = None) -> str:
        """Return a string of Unicode characters for subsetting.

        Args:
            names: Specific icon names to include. If None, includes all.

        Returns:
            String of characters (PUA codepoints) for the subsetter.
        """
        if names is None:
            codepoints = self.glyph_map.values()
        else:
            codepoints = [self.glyph_map[n] for n in names if n in self.glyph_map]
        return "".join(chr(cp) for cp in codepoints)


# Tabler Icons — MIT license, 5,900+ icons
# Codepoints from Tabler Icons v3.x PUA mapping
_TABLER_GLYPHS: dict[str, int] = {
    "check": 0xEA5E,
    "arrow-right": 0xEA9C,
    "alert-triangle": 0xEA06,
    "info-circle": 0xEA4C,
    "star": 0xEB52,
    "phone": 0xEB09,
    "mail": 0xEAC1,
    "map-pin": 0xEAEF,
    "calendar": 0xEA53,
    "chart-bar": 0xEA58,
    "x": 0xEB55,
    "plus": 0xEB0B,
    "minus": 0xEAF2,
    "search": 0xEB1C,
    "settings": 0xEB20,
    "user": 0xEB4D,
    "home": 0xEA8A,
    "file": 0xEA6B,
    "folder": 0xEA74,
    "download": 0xEA4F,
    "upload": 0xEB49,
    "edit": 0xEA5F,
    "trash": 0xEB41,
    "eye": 0xEA67,
    "lock": 0xEAEE,
    "clock": 0xEA70,
    "heart": 0xEA86,
    "bookmark": 0xEA3D,
    "share": 0xEB21,
    "link": 0xEAEB,
}

# Font Awesome 6 Free Solid — SIL OFL license
_FONTAWESOME_GLYPHS: dict[str, int] = {
    "check": 0xF00C,
    "arrow-right": 0xF061,
    "alert-triangle": 0xF071,
    "info-circle": 0xF05A,
    "star": 0xF005,
    "phone": 0xF095,
    "mail": 0xF0E0,
    "map-pin": 0xF3C5,
    "calendar": 0xF133,
    "chart-bar": 0xF080,
    "x": 0xF00D,
    "plus": 0xF067,
    "minus": 0xF068,
    "search": 0xF002,
    "settings": 0xF013,
    "user": 0xF007,
    "home": 0xF015,
    "file": 0xF15B,
    "folder": 0xF07B,
    "download": 0xF019,
    "upload": 0xF093,
    "edit": 0xF044,
    "trash": 0xF1F8,
    "eye": 0xF06E,
    "lock": 0xF023,
    "clock": 0xF017,
    "heart": 0xF004,
    "bookmark": 0xF02E,
    "share": 0xF064,
    "link": 0xF0C1,
}

# Phosphor Icons — MIT license, 6 weights
_PHOSPHOR_GLYPHS: dict[str, int] = {
    "check": 0xE900,
    "arrow-right": 0xE901,
    "alert-triangle": 0xE902,
    "info-circle": 0xE903,
    "star": 0xE904,
    "phone": 0xE905,
    "mail": 0xE906,
    "map-pin": 0xE907,
    "calendar": 0xE908,
    "chart-bar": 0xE909,
    "x": 0xE90A,
    "plus": 0xE90B,
    "minus": 0xE90C,
    "search": 0xE90D,
    "settings": 0xE90E,
    "user": 0xE90F,
    "home": 0xE910,
    "file": 0xE911,
    "folder": 0xE912,
    "download": 0xE913,
    "upload": 0xE914,
    "edit": 0xE915,
    "trash": 0xE916,
    "eye": 0xE917,
    "lock": 0xE918,
    "clock": 0xE919,
    "heart": 0xE91A,
    "bookmark": 0xE91B,
    "share": 0xE91C,
    "link": 0xE91D,
}


ICON_SETS: dict[str, IconSetConfig] = {
    "tabler": IconSetConfig(
        family="Tabler Icons",
        ttf_filename="tabler-icons.ttf",
        glyph_map=_TABLER_GLYPHS,
    ),
    "fontawesome": IconSetConfig(
        family="Font Awesome 6 Free",
        ttf_filename="fa-solid-900.ttf",
        glyph_map=_FONTAWESOME_GLYPHS,
    ),
    "phosphor": IconSetConfig(
        family="Phosphor",
        ttf_filename="Phosphor.ttf",
        glyph_map=_PHOSPHOR_GLYPHS,
    ),
}
"""Registry of available icon font sets."""


def get_icon_set(name: str) -> IconSetConfig:
    """Look up an icon set by name.

    Args:
        name: Icon set name (tabler, fontawesome, phosphor).

    Returns:
        IconSetConfig for the requested set.

    Raises:
        KeyError: If the set name is not registered.
    """
    if name not in ICON_SETS:
        msg = f"Unknown icon set: {name!r}. Available: {', '.join(ICON_SETS)}"
        raise KeyError(msg)
    return ICON_SETS[name]


def resolve_glyph(set_name: str, icon_name: str) -> int:
    """Resolve a semantic icon name to its Unicode codepoint.

    Args:
        set_name: Icon set name.
        icon_name: Semantic icon name (e.g., "check", "arrow-right").

    Returns:
        Unicode codepoint (int).

    Raises:
        KeyError: If the icon set or glyph name is not found.
    """
    config = get_icon_set(set_name)
    if icon_name not in config.glyph_map:
        msg = f"Unknown icon {icon_name!r} in set {set_name!r}"
        raise KeyError(msg)
    return config.glyph_map[icon_name]
