"""Tests for core domain models (extracted from models/frontmatter.py)."""

import unittest

from pydantic import ValidationError

from gzkit.core.models import (
    AdrFrontmatter,
    ObpiFrontmatter,
    PrdFrontmatter,
    validate_frontmatter_model,
)
from gzkit.traceability import covers


class TestCoreAdrFrontmatter(unittest.TestCase):
    """Verify AdrFrontmatter is importable from core."""

    @covers("REQ-0.0.3-02-04")
    def test_valid_adr_frontmatter(self) -> None:
        fm = AdrFrontmatter(
            id="ADR-0.1.0-test-slug",
            status="Draft",
            semver="0.1.0",
            lane="heavy",
            kind="feature",
            parent="",
            date="2026-01-01",
        )
        self.assertEqual(fm.id, "ADR-0.1.0-test-slug")
        self.assertEqual(fm.lane, "heavy")


class TestAdrIdPatternRequiresSlugOrPool(unittest.TestCase):
    """Bare-semver ADR ids must fail validation; slug-form and pool-form pass.

    The schema's earlier ``(-[a-z0-9-]+)?`` quantifier permitted ``ADR-0.0.27``
    (no slug) to validate clean even when the on-disk canonical identifier
    carried the slug suffix. Tightening the pattern closes the
    canonical-declaration class of failure named in GHI #346: any future
    emission path producing a non-pool ADR with a slug-less ``id:`` must be
    a Gate 1 blocker at the schema layer.
    """

    def _adr_payload(self, adr_id: str) -> dict:
        return {
            "id": adr_id,
            "status": "Draft",
            "semver": "0.0.27",
            "lane": "lite",
            "kind": "foundation",
            "parent": "PRD-GZKIT-1.0.0",
            "date": "2026-04-25",
        }

    def test_bare_semver_id_is_rejected(self) -> None:
        with self.assertRaises(ValidationError):
            AdrFrontmatter(**self._adr_payload("ADR-0.0.27"))

    def test_slug_form_id_is_accepted(self) -> None:
        fm = AdrFrontmatter(**self._adr_payload("ADR-0.0.27-exemplar-corpus-doctrine"))
        self.assertEqual(fm.id, "ADR-0.0.27-exemplar-corpus-doctrine")

    def test_pool_form_id_is_accepted(self) -> None:
        payload = self._adr_payload("ADR-pool.skill-feedback-loop")
        fm = AdrFrontmatter(**payload)
        self.assertEqual(fm.id, "ADR-pool.skill-feedback-loop")

    def test_uppercase_slug_is_rejected(self) -> None:
        with self.assertRaises(ValidationError):
            AdrFrontmatter(**self._adr_payload("ADR-0.0.27-Exemplar"))


class TestCoreObpiFrontmatter(unittest.TestCase):
    """Verify ObpiFrontmatter is importable from core."""

    @covers("REQ-0.0.3-02-04")
    def test_valid_obpi_frontmatter(self) -> None:
        fm = ObpiFrontmatter(
            id="OBPI-0.1.0-01",
            parent="ADR-0.1.0",
            item=1,
            lane="Heavy",
            status="Draft",
        )
        self.assertEqual(fm.parent, "ADR-0.1.0")


class TestCorePrdFrontmatter(unittest.TestCase):
    """Verify PrdFrontmatter is importable from core."""

    @covers("REQ-0.0.3-02-04")
    def test_valid_prd_frontmatter(self) -> None:
        fm = PrdFrontmatter(
            id="PRD-AI-0.1.0",
            status="Draft",
            semver="0.1.0",
            date="2026-01-01",
        )
        self.assertEqual(fm.status, "Draft")


class TestCoreValidateFrontmatterModel(unittest.TestCase):
    """Verify validate_frontmatter_model from core."""

    @covers("REQ-0.0.3-02-04")
    def test_returns_none_for_unknown_schema(self) -> None:
        result = validate_frontmatter_model({}, {"$id": "unknown"}, "test.md")
        self.assertIsNone(result)


class TestCoreReExports(unittest.TestCase):
    """Verify original module re-exports work (backward compat)."""

    @covers("REQ-0.0.3-02-05")
    def test_models_reexports_adr(self) -> None:
        from gzkit.models import AdrFrontmatter as orig

        self.assertIs(orig, AdrFrontmatter)

    @covers("REQ-0.0.3-02-05")
    def test_models_frontmatter_reexports(self) -> None:
        from gzkit.models.frontmatter import ObpiFrontmatter as orig

        self.assertIs(orig, ObpiFrontmatter)


if __name__ == "__main__":
    unittest.main()
