"""Unit tests for build/readers.py."""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any, Dict

import pytest

from byteb4rb1e.sphinxcontrib.h5p.utils.pkg.build.readers import (
    H5PConfig,
    LibraryInfo,
    read_h5p_config,
    read_library_json,
    read_semantics_json,
)


# -------------------------------------------------------------------
# read_h5p_config
# -------------------------------------------------------------------

class TestReadH5PConfig:

    def test_valid_toml(self, true_false_pyproject: Path) -> None:
        cfg = read_h5p_config(true_false_pyproject)
        assert cfg.machine_name == "H5P.TrueFalse"
        assert cfg.vendor_map == {
            "H5P.TrueFalse": "vendor/h5p-true-false",
            "FontAwesome": "vendor/font-awesome",
        }

    def test_missing_tool_h5p(self, tmp_path: Path) -> None:
        path = tmp_path / "pyproject.toml"
        path.write_text(
            '[project]\nname = "test"\n', encoding="utf-8",
        )
        with pytest.raises(KeyError):
            read_h5p_config(path)

    def test_missing_machine_name(self, tmp_path: Path) -> None:
        path = tmp_path / "pyproject.toml"
        path.write_text(
            '[tool.h5p]\nfoo = "bar"\n', encoding="utf-8",
        )
        with pytest.raises(KeyError):
            read_h5p_config(path)

    def test_empty_vendors(self, tmp_path: Path) -> None:
        path = tmp_path / "pyproject.toml"
        path.write_text(
            '[tool.h5p]\nmachine_name = "H5P.Test"\n',
            encoding="utf-8",
        )
        cfg = read_h5p_config(path)
        assert cfg.machine_name == "H5P.Test"
        assert cfg.vendor_map == {}


# -------------------------------------------------------------------
# read_library_json
# -------------------------------------------------------------------

class TestReadLibraryJson:

    def test_runnable_library(
        self, true_false_vendor_dir: Path,
    ) -> None:
        info = read_library_json(true_false_vendor_dir)
        assert info is not None
        assert info.machine_name == "H5P.TrueFalse"
        assert info.major_version == 1
        assert info.minor_version == 8
        assert info.runnable is True
        assert info.preloaded_js == ("js/h5p-true-false.js",)
        assert info.preloaded_css == ("css/h5p-true-false.css",)

    def test_non_runnable_library(
        self,
        tmp_path: Path,
        font_awesome_library_json: Dict[str, Any],
    ) -> None:
        vendor = tmp_path / "vendor" / "font-awesome"
        vendor.mkdir(parents=True)
        (vendor / "library.json").write_text(
            json.dumps(font_awesome_library_json),
            encoding="utf-8",
        )
        info = read_library_json(vendor)
        assert info is not None
        assert info.machine_name == "FontAwesome"
        assert info.runnable is False
        assert info.preloaded_js == ()
        assert info.preloaded_css == (
            "css/font-awesome.min.css",
            "css/override.css",
        )

    def test_missing_file(self, tmp_path: Path) -> None:
        assert read_library_json(tmp_path) is None


# -------------------------------------------------------------------
# read_semantics_json
# -------------------------------------------------------------------

class TestReadSemanticsJson:

    def test_valid_file(
        self, true_false_vendor_dir: Path,
    ) -> None:
        result = read_semantics_json(true_false_vendor_dir)
        assert isinstance(result, list)
        assert len(result) > 0
        names = [f["name"] for f in result]
        assert "question" in names
        assert "behaviour" in names

    def test_missing_file(self, tmp_path: Path) -> None:
        result = read_semantics_json(tmp_path)
        assert result == []
