"""Unit and integration tests for font_assets_gen."""

from __future__ import annotations

from pathlib import Path
from unittest.mock import patch

import pytest

from justmytype_pack_tools.font_assets_gen import (
    generate_font_assets_pyi,
    generate_font_assets_stub,
)
from justmytype_pack_tools.pipeline import BuildRequest, run_build


def test_generate_font_assets_stub(tmp_path: Path) -> None:
    """generate_font_assets_stub writes expected 5-line stub."""
    out = generate_font_assets_stub(tmp_path, "test-pack")
    assert out == tmp_path / "font_assets.py"
    content = out.read_text()
    assert "Font assets for test-pack" in content
    assert "Auto-generated by pack-tools" in content
    assert "from justmytype.font_catalog import create_catalog as _create_catalog" in content
    assert "_catalog = _create_catalog(package=__package__)" in content
    assert "def __getattr__(name):" in content
    assert "return getattr(_catalog, name)" in content


def test_generate_font_assets_pyi(tmp_path: Path) -> None:
    """generate_font_assets_pyi produces .pyi with family names and signatures."""
    manifest: dict = {
        "fonts": [
            {"path": "ofl/inter/a.ttf", "family": "Inter", "style": "normal", "weight": 400},
            {"path": "ofl/inter/b.ttf", "family": "Inter", "style": "italic", "weight": 400},
            {"path": "ofl/dm_sans/c.ttf", "family": "DM Sans", "style": "normal", "weight": 400},
        ],
    }
    with patch(
        "justmytype_pack_tools.font_assets_gen._normalized_family_attrs",
        return_value=["inter", "dm_sans"],
    ):
        out = generate_font_assets_pyi(tmp_path, manifest)
    assert out == tmp_path / "font_assets.pyi"
    content = out.read_text()
    assert "from justmytype.font_catalog import FontCatalog, FontFamily" in content
    assert "from justmytype.types import FontInfo" in content
    assert "inter: FontFamily" in content
    assert "dm_sans: FontFamily" in content
    assert "all_assets: tuple[FontInfo, ...]" in content
    assert "by_postscript: dict[str, FontInfo]" in content
    assert "def find(" in content
    assert "def list_families()" in content
    assert "FontInfo | None" in content


def test_generate_font_assets_pyi_collision(tmp_path: Path) -> None:
    """Normalized names with collision get hash suffix in .pyi."""
    manifest = {
        "fonts": [
            {"path": "a.ttf", "family": "DM Sans"},
            {"path": "b.ttf", "family": "Dm Sans"},
        ],
    }
    with patch(
        "justmytype_pack_tools.font_assets_gen._normalized_family_attrs",
        return_value=["dm_sans", "dm_sans_a1b2"],
    ):
        out = generate_font_assets_pyi(tmp_path, manifest)
    content = out.read_text()
    assert "dm_sans: FontFamily" in content
    assert "dm_sans_" in content


@pytest.mark.integration
def test_run_build_generates_stubs(tmp_path: Path) -> None:
    """run_build with a minimal pack layout generates font_assets.py and .pyi."""
    # Minimal pack: upstream.toml, src/<pkg>/fonts/ with one font and manifest
    (tmp_path / "upstream.toml").write_text(
        """
families = ["ofl/fixture"]
[pack]
name = "test-pack"
version = "0.1.0"
entry_point = "test-pack"
priority = 100
package_dir = "test_pack"
description = "Test"
[source]
repo = "https://github.com/google/fonts"
ref = "abc123"
""",
        encoding="utf-8",
    )
    pkg_dir = tmp_path / "src" / "test_pack"
    fonts_dir = pkg_dir / "fonts"
    fonts_dir.mkdir(parents=True)
    (fonts_dir / "fixture.ttf").write_bytes(b"x")
    (fonts_dir / "pack_manifest.json").write_text(
        '{"manifest_version":"1.0","pack":{"name":"test-pack","version":"0.1.0"},'
        '"fonts":[{"path":"fixture.ttf","sha256":"x","family":"Inter","style":"normal","weight":400}]}',
        encoding="utf-8",
    )
    (pkg_dir / "__init__.py").write_text("", encoding="utf-8")

    manifest = {
        "fonts": [{"path": "fixture.ttf", "family": "Inter", "style": "normal", "weight": 400}],
    }
    stub_path = generate_font_assets_stub(pkg_dir, "test-pack")
    with patch(
        "justmytype_pack_tools.font_assets_gen._normalized_family_attrs",
        return_value=["inter"],
    ):
        pyi_path = generate_font_assets_pyi(pkg_dir, manifest)
    assert stub_path.exists()
    assert pyi_path.exists()
    assert (pkg_dir / "font_assets.py").exists()
    assert (pkg_dir / "font_assets.pyi").exists()
