"""Tests for complyform.core.profiles.registry — including error paths."""

from __future__ import annotations

from typing import TYPE_CHECKING
from unittest.mock import patch

if TYPE_CHECKING:
    from pathlib import Path

import pytest

from complyform.core.errors import ProfileBundleError, UnknownFrameworkError
from complyform.core.profiles.registry import (
    _reset_cache,
    get_framework,
    list_frameworks,
    search_frameworks,
)


@pytest.fixture(autouse=True)
def _clear_cache() -> None:
    _reset_cache()


# -------------------------------------------------------------------
# Happy paths
# -------------------------------------------------------------------


class TestListFrameworks:
    def test_all(self) -> None:
        fws = list_frameworks()
        assert len(fws) == 53

    def test_filter_tier_community(self) -> None:
        free = list_frameworks(tier="community")
        assert len(free) == 4
        assert all(f.tier == "community" for f in free)

    def test_filter_tier_pro(self) -> None:
        pro = list_frameworks(tier="pro")
        assert len(pro) > 0
        assert all(f.tier == "pro" for f in pro)

    def test_filter_tier_agency(self) -> None:
        agency = list_frameworks(tier="agency")
        assert len(agency) > 0
        assert all(f.tier == "agency" for f in agency)

    def test_filter_cloud_gcp(self) -> None:
        gcp = list_frameworks(cloud="gcp")
        assert all(f.cloud in ("gcp", "all") for f in gcp)

    def test_filter_cloud_aws(self) -> None:
        aws = list_frameworks(cloud="aws")
        assert all(f.cloud in ("aws", "all") for f in aws)

    def test_filter_cloud_azure(self) -> None:
        azure = list_frameworks(cloud="azure")
        assert all(f.cloud in ("azure", "all") for f in azure)

    def test_filter_category_cis(self) -> None:
        cis = list_frameworks(category="cis")
        assert all(f.category == "cis" for f in cis)

    def test_filter_category_regional(self) -> None:
        regional = list_frameworks(category="regional")
        assert all(f.category == "regional" for f in regional)

    def test_combined_filters(self) -> None:
        results = list_frameworks(tier="community", cloud="gcp")
        assert len(results) >= 1
        assert all(f.tier == "community" and f.cloud in ("gcp", "all") for f in results)

    def test_filter_no_match(self) -> None:
        results = list_frameworks(tier="nonexistent")
        assert results == []


class TestGetFramework:
    def test_existing(self) -> None:
        fw = get_framework("soc2")
        assert fw.id == "soc2"
        assert fw.name == "SOC 2 Type II"

    def test_not_found(self) -> None:
        with pytest.raises(UnknownFrameworkError):
            get_framework("nonexistent_framework_xyz")


class TestSearchFrameworks:
    def test_by_id(self) -> None:
        results = search_frameworks("cis")
        assert len(results) >= 3

    def test_by_name(self) -> None:
        results = search_frameworks("SOC")
        assert any(f.id == "soc2" for f in results)

    def test_case_insensitive(self) -> None:
        upper = search_frameworks("HIPAA")
        lower = search_frameworks("hipaa")
        assert len(upper) == len(lower)

    def test_no_match(self) -> None:
        results = search_frameworks("zzz_nonexistent_query")
        assert results == []


# -------------------------------------------------------------------
# Error / edge paths
# -------------------------------------------------------------------


class TestRegistryMissing:
    def test_registry_yaml_not_found(self, tmp_path: Path) -> None:
        """_load_registry raises when registry.yaml doesn't exist."""
        _reset_cache()
        with (
            patch(
                "complyform.core.profiles.registry._PROFILES_DIR",
                tmp_path,
            ),
            pytest.raises(ProfileBundleError, match="not found"),
        ):
            list_frameworks()


class TestRegistryMalformed:
    def test_invalid_yaml_schema(self, tmp_path: Path) -> None:
        """_load_registry raises when YAML doesn't match the model."""
        _reset_cache()
        reg_file = tmp_path / "framework_registry.yaml"
        reg_file.write_text("schema_version: 1\nframeworks: not_a_list\n")
        with (
            patch(
                "complyform.core.profiles.registry._PROFILES_DIR",
                tmp_path,
            ),
            pytest.raises(ProfileBundleError),
        ):
            list_frameworks()

    def test_missing_schema_version(self, tmp_path: Path) -> None:
        _reset_cache()
        reg_file = tmp_path / "framework_registry.yaml"
        reg_file.write_text("frameworks: []\n")
        with (
            patch(
                "complyform.core.profiles.registry._PROFILES_DIR",
                tmp_path,
            ),
            pytest.raises(ProfileBundleError),
        ):
            list_frameworks()

    def test_bad_framework_entry(self, tmp_path: Path) -> None:
        _reset_cache()
        reg_file = tmp_path / "framework_registry.yaml"
        reg_file.write_text(
            "schema_version: 1\nframeworks:\n  - id: bad\n    name: Bad\n"
            # missing required fields
        )
        with (
            patch(
                "complyform.core.profiles.registry._PROFILES_DIR",
                tmp_path,
            ),
            pytest.raises(ProfileBundleError),
        ):
            list_frameworks()
