"""
Pytest fixtures powered by the Single Source of Truth.

These fixtures provide typed access to SST values in tests, ensuring
tests never hardcode configuration values.

Usage:
    # In conftest.py
    pytest_plugins = ["lightwave.schema.testing"]

    # In tests
    def test_login_redirects(sst_routes, client):
        login_url = sst_routes.get_url("login")
        response = client.get(login_url)
        assert response.status_code == 200

    def test_webhooks_require_verification(sst_webhooks):
        for webhook in sst_webhooks.all():
            assert webhook.verification is not None
"""

from __future__ import annotations

from typing import TYPE_CHECKING

import pytest

from lightwave.schema.core.registry import build_registry, clear_registry_cache

if TYPE_CHECKING:
    from lightwave.schema.core.registry import (
        BlueprintsRegistry,
        LayoutsRegistry,
        RoutesRegistry,
        SSTRegistry,
        TenantsRegistry,
        UserFlowsRegistry,
        UserTypesRegistry,
        WebhooksRegistry,
    )


@pytest.fixture(scope="session")
def sst_registry() -> "SSTRegistry":
    """
    Session-scoped SST registry for tests.

    Uses YAML-only mode (use_db=False) for deterministic test behavior.
    The registry is loaded once per test session for performance.

    Usage:
        def test_registry_loaded(sst_registry):
            assert sst_registry.is_loaded()
    """
    # Clear any cached registry from application code
    clear_registry_cache()

    # Build fresh registry from YAML only (no DB)
    return build_registry(use_db=False)


@pytest.fixture(scope="session")
def sst_routes(sst_registry: "SSTRegistry") -> "RoutesRegistry":
    """
    Routes registry fixture.

    Usage:
        def test_login_url(sst_routes):
            assert sst_routes.get_url("login") == "/login/"

        def test_all_auth_routes_use_auth_layout(sst_routes):
            for route in sst_routes.by_layout("auth"):
                assert "login" in route.pattern or "signup" in route.pattern
    """
    return sst_registry.routes


@pytest.fixture(scope="session")
def sst_webhooks(sst_registry: "SSTRegistry") -> "WebhooksRegistry":
    """
    Webhooks registry fixture.

    Usage:
        def test_stripe_webhook_endpoint(sst_webhooks):
            endpoint = sst_webhooks.get_endpoint("stripe")
            assert endpoint == "/webhooks/stripe/"

        def test_all_webhooks_have_verification(sst_webhooks):
            for webhook in sst_webhooks.all():
                assert webhook.verification is not None
    """
    return sst_registry.webhooks


@pytest.fixture(scope="session")
def sst_tenants(sst_registry: "SSTRegistry") -> "TenantsRegistry":
    """
    Tenants registry fixture.

    Usage:
        def test_cineos_has_primary_domain(sst_tenants):
            domains = sst_tenants.get_domains("cineos")
            assert "cineos.io" in domains

        def test_all_tenants_have_primary_domain(sst_tenants):
            for tenant in sst_tenants.all():
                assert tenant.get_domain("primary") is not None
    """
    return sst_registry.tenants


@pytest.fixture(scope="session")
def sst_layouts(sst_registry: "SSTRegistry") -> "LayoutsRegistry":
    """
    Layouts registry fixture.

    Usage:
        def test_five_layouts_exist(sst_layouts):
            assert len(sst_layouts.all()) == 5

        def test_all_layouts_have_templates(sst_layouts):
            for layout in sst_layouts.all():
                assert layout.template_path.endswith(".html")
    """
    return sst_registry.layouts


@pytest.fixture(scope="session")
def sst_blueprints(sst_registry: "SSTRegistry") -> "BlueprintsRegistry":
    """
    Blueprints registry fixture.

    Usage:
        def test_marketing_landing_blueprint_exists(sst_blueprints):
            bp = sst_blueprints.get("marketing-landing")
            assert bp is not None
            assert "web" in bp.allowed_layouts

        def test_all_blueprints_have_schemas(sst_blueprints):
            for bp in sst_blueprints.all():
                assert bp.schema is not None
    """
    return sst_registry.blueprints


@pytest.fixture(scope="session")
def sst_user_types(sst_registry: "SSTRegistry") -> "UserTypesRegistry":
    """
    User types registry fixture.

    Usage:
        def test_platform_admin_exists(sst_user_types):
            admin = sst_user_types.get("platform_admin")
            assert admin is not None

        def test_user_type_valid(sst_user_types):
            assert sst_user_types.is_valid("team_owner")
            assert not sst_user_types.is_valid("fake_type")
    """
    return sst_registry.user_types


@pytest.fixture(scope="session")
def sst_user_flows(sst_registry: "SSTRegistry") -> "UserFlowsRegistry":
    """
    User flows registry fixture.

    Usage:
        def test_auth_signup_flow_exists(sst_user_flows):
            flow = sst_user_flows.get("auth_signup")
            assert flow is not None
            assert len(flow.steps) > 0

        def test_all_flows_have_entry_points(sst_user_flows):
            for flow in sst_user_flows.all():
                # Not all flows have entry points (some are sub-flows)
                if flow.entry_points:
                    assert len(flow.entry_points) > 0
    """
    return sst_registry.user_flows


# =============================================================================
# Function-scoped fixtures for tests that need fresh state
# =============================================================================


@pytest.fixture
def fresh_sst_registry() -> "SSTRegistry":
    """
    Function-scoped SST registry for tests that need isolation.

    Unlike sst_registry (session-scoped), this creates a fresh
    registry for each test function.
    """
    clear_registry_cache()
    return build_registry(use_db=False)


# =============================================================================
# Convenience fixtures for common test patterns
# =============================================================================


@pytest.fixture(scope="session")
def all_route_names(sst_routes: "RoutesRegistry") -> list[str]:
    """List of all route names for parametrization."""
    return [r.name for r in sst_routes.all() if r.name]


@pytest.fixture(scope="session")
def all_tenant_slugs(sst_tenants: "TenantsRegistry") -> list[str]:
    """List of all tenant slugs for parametrization."""
    return sst_tenants.slugs()


@pytest.fixture(scope="session")
def all_layout_names(sst_layouts: "LayoutsRegistry") -> list[str]:
    """List of all layout names for parametrization."""
    return sst_layouts.names()


@pytest.fixture(scope="session")
def all_blueprint_names(sst_blueprints: "BlueprintsRegistry") -> list[str]:
    """List of all blueprint names for parametrization."""
    return sst_blueprints.names()


@pytest.fixture(scope="session")
def all_user_type_names(sst_user_types: "UserTypesRegistry") -> list[str]:
    """List of all user type names for parametrization."""
    return sst_user_types.names()


@pytest.fixture(scope="session")
def all_flow_names(sst_user_flows: "UserFlowsRegistry") -> list[str]:
    """List of all user flow names for parametrization."""
    return sst_user_flows.names()
