"""
YAML Schema Loader - Load and validate YAML configuration files.

This module provides utilities for loading YAML schema definitions
and validating them against their respective JSONSchema validators.

The loader supports two modes:
1. Raw dict loading: load() returns raw YAML data as dict
2. Typed loading: load_as_schema() returns validated Pydantic schema instances

For typed loading, use:
    from lightwave.schema.loaders.base import load_layouts, load_blueprints

    layouts = load_layouts()  # Returns list[LayoutSchema]
    blueprints = load_blueprints()  # Returns list[PageSchemaDefinition]
"""

from __future__ import annotations

import logging
from functools import lru_cache
from pathlib import Path
from typing import TYPE_CHECKING, Any, TypeVar

import yaml

if TYPE_CHECKING:
    from lightwave.schema.pydantic.models.packages import (
        PackageDefinition,
        PackageEcosystemSchema,
    )
    from lightwave.schema.pydantic.sst import (
        LayoutSchema,
        NavItemSchema,
        PackageResolver,
        PageSchemaDefinition,
        PageSeedSchema,
    )

T = TypeVar("T")

logger = logging.getLogger(__name__)

# Path to schema definitions directory
SCHEMA_DIR = Path(__file__).parent.parent / "definitions"

# =============================================================================
# SST-DRIVEN SCHEMA REGISTRY
# =============================================================================
# Paths are loaded from __index.yaml - NO HARDCODING
# This ensures YAML is the single source of truth for file locations.


@lru_cache(maxsize=1)
def _load_schema_registry() -> dict[str, str]:
    """Load schema paths from __index.yaml (SST-driven, no hardcoding)."""
    index_path = SCHEMA_DIR / "__index.yaml"
    if not index_path.exists():
        logger.warning(f"Schema index not found: {index_path}")
        return {}

    with open(index_path) as f:
        index_data = yaml.safe_load(f)

    schemas = index_data.get("schemas", {})
    aliases = index_data.get("aliases", {})

    # Merge aliases into schemas for backward compatibility
    for alias, path in aliases.items():
        if alias not in schemas:
            schemas[alias] = path

    return schemas


def get_schema_files() -> dict[str, str]:
    """Get schema file mappings (loaded from __index.yaml)."""
    return _load_schema_registry()


# Schemas that use modular directory structure
MODULAR_SCHEMAS = {"journeys", "automation", "user_flows", "workflows"}

# Legacy path aliases for backward compatibility
# Maps old paths to new decision tree paths
LEGACY_ALIASES = {
    # user_flows -> workflows/journeys
    "user_flows/auth/signup": "workflows/journeys/auth/signup",
    "user_flows/auth/login": "workflows/journeys/auth/login",
    "user_flows/auth/logout": "workflows/journeys/auth/logout",
    "user_flows/payments": "workflows/journeys/payments",
    "user_flows/team": "workflows/journeys/team",
    "user_flows/cms": "workflows/journeys/cms",
    "user_flows/webhooks": "workflows/journeys/webhooks",
    "user_flows/compliance": "workflows/compliance",
    "user_flows/platform": "workflows/epics",
    "user_flows/packages": "workflows/infrastructure/packages",
    "user_flows/sync": "workflows/infrastructure/sync",
}

# Model mappings for each schema
# Updated for v2.0 domain-driven app structure (cms -> sites migration)
SCHEMA_MODEL_MAP = {
    "layouts": ("sites", "Layout", "name"),
    "blueprints": ("sites", "PageSchema", "name"),  # Renamed from Blueprint
    "pages": ("sites", "Page", ("site__domain", "path")),
    "routes": ("sites", "Route", "pattern"),
    "navigation": ("sites", "NavItem", ("site__domain", "location", "order")),
    "features": ("tenants", "Tenant", "slug"),
}


class SchemaLoader:
    """
    Load and parse YAML schema definitions.

    Provides caching, validation, and model mapping for schema files.
    """

    def __init__(self, schema_dir: Path | None = None):
        """
        Initialize the schema loader.

        Args:
            schema_dir: Optional custom directory for schema files.
                       Defaults to the definitions/ directory.
        """
        self.schema_dir = schema_dir or SCHEMA_DIR
        self._cache: dict[str, dict[str, Any]] = {}

    def load(self, schema_name: str, use_cache: bool = True) -> dict[str, Any]:
        """
        Load a schema definition by name.

        Args:
            schema_name: Name of the schema (e.g., 'layouts', 'blueprints')
            use_cache: Whether to use cached data (default: True)

        Returns:
            Parsed YAML data as a dictionary

        Raises:
            ValueError: If schema name is not recognized
            FileNotFoundError: If schema file doesn't exist
            yaml.YAMLError: If YAML parsing fails
        """
        if use_cache and schema_name in self._cache:
            return self._cache[schema_name]

        if schema_name not in get_schema_files():
            available = ", ".join(get_schema_files().keys())
            raise ValueError(f"Unknown schema '{schema_name}'. Available: {available}")

        # Handle modular schemas (e.g., user_flows directory structure)
        if schema_name in MODULAR_SCHEMAS:
            data = self._load_modular_schema(schema_name)
        else:
            file_path = self.schema_dir / get_schema_files()[schema_name]

            if not file_path.exists():
                raise FileNotFoundError(f"Schema file not found: {file_path}")

            with open(file_path) as f:
                data = yaml.safe_load(f)

            logger.debug(f"Loaded schema '{schema_name}' from {file_path}")

        if use_cache:
            self._cache[schema_name] = data

        return data

    def _load_modular_schema(self, schema_name: str) -> dict[str, Any]:
        """
        Load a modular schema from a directory structure.

        For user_flows and workflows:
        - Loads __index.yaml for shared config (platform_urls, api_endpoints, etc.)
        - Scans subdirectories for individual flow files
        - Merges flows into a dict with keys like 'auth/signup' or 'journeys/auth/signup'

        Args:
            schema_name: Name of the modular schema

        Returns:
            Merged schema data with all flows loaded
        """
        index_path = self.schema_dir / get_schema_files()[schema_name]
        schema_dir = index_path.parent

        if not index_path.exists():
            raise FileNotFoundError(f"Schema index not found: {index_path}")

        # Load the index file (shared config)
        with open(index_path) as f:
            data = yaml.safe_load(f)

        logger.debug(f"Loaded schema index '{schema_name}' from {index_path}")

        # For user_flows and workflows, scan subdirectories and load individual flows
        if schema_name in ("user_flows", "workflows"):
            flows = {}
            exclude_patterns = {"__index.yaml", "__schema.yaml", "*.example.yaml"}

            def scan_directory(directory: Path, prefix: str = "") -> None:
                """Recursively scan directories for YAML files."""
                for item in directory.iterdir():
                    if item.is_dir() and not item.name.startswith((".", "_")):
                        # Recurse into subdirectory
                        subprefix = f"{prefix}{item.name}/" if prefix else f"{item.name}/"
                        scan_directory(item, subprefix)
                    elif item.is_file() and item.suffix == ".yaml":
                        if item.name not in exclude_patterns:
                            flow_id = f"{prefix}{item.stem}"
                            try:
                                with open(item) as f:
                                    flow_data = yaml.safe_load(f)
                                if flow_data:
                                    # Extract flow content from the 'flow' key if present
                                    flow_content = flow_data.get("flow", flow_data)
                                    # Add metadata
                                    flow_content["_flow_id"] = flow_id
                                    flow_content["_category"] = prefix.rstrip("/").split("/")[0] if prefix else "root"
                                    flow_content["_file"] = str(item)
                                    flows[flow_id] = flow_content
                                    logger.debug(f"Loaded flow '{flow_id}' from {item}")
                            except yaml.YAMLError as e:
                                logger.warning(f"Failed to parse {item}: {e}")

            scan_directory(schema_dir)

            # Store under appropriate key
            key = "workflows" if schema_name == "workflows" else "user_flows"
            data[key] = flows
            logger.debug(f"Loaded {len(flows)} flows from {schema_dir}")

        return data

    def load_all(self, use_cache: bool = True) -> dict[str, dict[str, Any]]:
        """
        Load all available schema definitions.

        Args:
            use_cache: Whether to use cached data

        Returns:
            Dictionary mapping schema names to their data
        """
        result = {}
        for name in get_schema_files():
            try:
                result[name] = self.load(name, use_cache=use_cache)
            except FileNotFoundError:
                logger.warning(f"Schema file not found: {name}")
        return result

    def clear_cache(self, schema_name: str | None = None) -> None:
        """
        Clear the schema cache.

        Args:
            schema_name: Specific schema to clear, or None for all
        """
        if schema_name:
            self._cache.pop(schema_name, None)
        else:
            self._cache.clear()

    def get_model_info(self, schema_name: str) -> tuple[str, str, str | tuple[str, ...]]:
        """
        Get Django model information for a schema.

        Args:
            schema_name: Name of the schema

        Returns:
            Tuple of (app_label, model_name, key_field)

        Raises:
            ValueError: If schema has no model mapping
        """
        if schema_name not in SCHEMA_MODEL_MAP:
            raise ValueError(f"No model mapping for schema '{schema_name}'")
        return SCHEMA_MODEL_MAP[schema_name]

    def get_items(self, schema_name: str) -> list[dict[str, Any]]:
        """
        Get the list of items from a schema (normalized format).

        Different schemas store items differently (dict vs list).
        This method normalizes to a list of dictionaries.

        Args:
            schema_name: Name of the schema

        Returns:
            List of item dictionaries
        """
        data = self.load(schema_name)

        # Handle different schema structures
        if schema_name == "layouts":
            # layouts.yaml stores items as dict under 'layouts' key
            layouts = data.get("layouts", {})
            return list(layouts.values())

        elif schema_name == "blueprints":
            # blueprints.yaml stores items as dict under 'blueprints' key
            if "blueprints" not in data:
                raise KeyError("blueprints.yaml missing required 'blueprints' key")
            return list(data["blueprints"].values())

        elif schema_name == "pages":
            # pages.yaml has nested tenant structure
            items = []
            for tenant_key, tenant_data in data.get("tenants", {}).items():
                for page in tenant_data.get("pages", []):
                    page["_tenant"] = tenant_key
                    page["_site"] = tenant_data.get("site", f"{tenant_key}.io")
                    items.append(page)
            return items

        elif schema_name == "routes":
            # routes.yaml has categorized routes
            items = []
            for category, routes in data.get("routes", {}).items():
                for route in routes:
                    route["_category"] = category
                    items.append(route)
            return items

        elif schema_name == "navigation":
            # navigation.yaml has site-grouped nav items
            items = []
            for site_key, site_data in data.get("sites", {}).items():
                for location, nav_items in site_data.items():
                    if isinstance(nav_items, list):
                        for item in nav_items:
                            item["_site"] = site_key
                            item["_location"] = location
                            items.append(item)
            return items

        elif schema_name == "features":
            # features.yaml has tenant-keyed feature flags
            tenants = data.get("tenants", {})
            return [{"slug": k, **v} for k, v in tenants.items()]

        elif schema_name == "user_flows":
            # user_flows.yaml stores flows for test generation (not DB-backed)
            flows = data.get("user_flows", {})
            return [{"_flow_id": k, **v} for k, v in flows.items()]

        # Default: return data as-is if it's a list
        if isinstance(data, list):
            return data

        logger.warning(f"Unknown schema structure for '{schema_name}'")
        return []

    # =========================================================================
    # TYPED LOADING METHODS - Return Pydantic schema instances
    # =========================================================================

    def load_layouts(self) -> list["LayoutSchema"]:
        """
        Load layouts as validated Pydantic LayoutSchema instances.

        Returns:
            List of LayoutSchema instances (exactly 5)

        Raises:
            ValueError: If validation fails
        """
        from lightwave.schema.pydantic.sst import LayoutSchema

        return LayoutSchema.get_all_from_sst()

    def load_blueprints(self) -> list["PageSchemaDefinition"]:
        """
        Load blueprints/page schemas as validated Pydantic instances.

        Returns:
            List of PageSchemaDefinition instances
        """
        from lightwave.schema.pydantic.sst import PageSchemaDefinition

        return PageSchemaDefinition.get_all_from_sst()

    def load_navigation(self, domain: str, location: str) -> list["NavItemSchema"]:
        """
        Load navigation items for a specific site and menu location.

        Args:
            domain: Site domain (e.g., "cineos.io")
            location: Menu location (e.g., "header")

        Returns:
            List of NavItemSchema instances sorted by order
        """
        from lightwave.schema.pydantic.sst import NavItemSchema

        return NavItemSchema.get_all_for_site(domain, location)

    def load_pages(self, domain: str) -> list["PageSeedSchema"]:
        """
        Load page seeds for a specific site.

        Args:
            domain: Site domain (e.g., "cineos.io")

        Returns:
            List of PageSeedSchema instances
        """
        from lightwave.schema.pydantic.sst import PageSeedSchema

        return PageSeedSchema.get_all_for_site(domain)

    def get_layout(self, name: str) -> "LayoutSchema":
        """
        Get a specific layout by name.

        Args:
            name: Layout name (e.g., "web")

        Returns:
            LayoutSchema instance

        Raises:
            KeyError: If layout not found
        """
        from lightwave.schema.pydantic.sst import LayoutSchema

        return LayoutSchema.get_by_name(name)

    def get_blueprint(self, name: str) -> "PageSchemaDefinition":
        """
        Get a specific blueprint/page schema by name.

        Args:
            name: Schema name (e.g., "marketing-landing")

        Returns:
            PageSchemaDefinition instance

        Raises:
            KeyError: If schema not found
        """
        from lightwave.schema.pydantic.sst import PageSchemaDefinition

        return PageSchemaDefinition.get_by_name(name)


# Module-level singleton loader
_default_loader = SchemaLoader()


def load_schema(schema_name: str, use_cache: bool = True) -> dict[str, Any]:
    """
    Load a schema definition by name.

    Convenience function using the default loader.

    Args:
        schema_name: Name of the schema (e.g., 'layouts', 'blueprints')
        use_cache: Whether to use cached data

    Returns:
        Parsed YAML data as a dictionary
    """
    return _default_loader.load(schema_name, use_cache=use_cache)


def get_schema_path(schema_name: str) -> Path:
    """
    Get the file path for a schema.

    Args:
        schema_name: Name of the schema

    Returns:
        Path to the schema file

    Raises:
        ValueError: If schema name is not recognized
    """
    if schema_name not in get_schema_files():
        available = ", ".join(get_schema_files().keys())
        raise ValueError(f"Unknown schema '{schema_name}'. Available: {available}")
    return SCHEMA_DIR / get_schema_files()[schema_name]


def validate_schema(schema_name: str) -> list[str]:
    """
    Validate a schema file for correctness.

    Checks:
    - File exists and is valid YAML
    - Required keys are present
    - Model references are valid (if DB-backed)
    - Schema-specific structure validation

    Args:
        schema_name: Name of the schema to validate

    Returns:
        List of validation errors (empty if valid)
    """
    errors = []

    try:
        data = load_schema(schema_name, use_cache=False)
    except FileNotFoundError:
        return [f"Schema file not found: {schema_name}"]
    except yaml.YAMLError as e:
        return [f"YAML parse error: {e}"]

    # Check for _meta section
    meta = data.get("_meta", {})
    if not meta:
        errors.append(f"Missing _meta section in {schema_name}")
    else:
        # Required for all schemas
        if "version" not in meta:
            errors.append(f"Missing _meta.version in {schema_name}")

        # model can be null for non-DB-backed schemas
        if "model" not in meta:
            errors.append(f"Missing _meta.model in {schema_name}")

        # key_field only required if model is not null (DB-backed schemas)
        model = meta.get("model")
        if model is not None and "key_field" not in meta:
            errors.append(f"Missing _meta.key_field in {schema_name} (required for DB-backed schemas)")

    # Schema-specific validation
    if schema_name == "layouts":
        layouts = data.get("layouts", {})
        expected = {"web", "auth", "app", "app_admin", "error"}
        found = set(layouts.keys())
        if found != expected:
            missing = expected - found
            extra = found - expected
            if missing:
                errors.append(f"Missing required layouts: {missing}")
            if extra:
                errors.append(f"Unexpected layouts (only 5 allowed): {extra}")

    elif schema_name == "blueprints":
        blueprints = data.get("blueprints", {})
        for name, schema_def in blueprints.items():
            if "schema" not in schema_def:
                errors.append(f"Blueprint '{name}' missing JSONSchema definition")

    return errors


@lru_cache(maxsize=32)
def get_schema_version(schema_name: str) -> str | None:
    """
    Get the version of a schema file.

    Args:
        schema_name: Name of the schema

    Returns:
        Version string or None if not specified
    """
    try:
        data = load_schema(schema_name)
        return data.get("_meta", {}).get("version")
    except (FileNotFoundError, ValueError):
        return None


# =============================================================================
# TYPED LOADING FUNCTIONS - Return Pydantic schema instances
# =============================================================================


def load_layouts() -> list["LayoutSchema"]:
    """
    Load all layouts as validated Pydantic LayoutSchema instances.

    Returns:
        List of LayoutSchema instances (exactly 5)

    Example:
        from lightwave.schema.loaders.base import load_layouts

        layouts = load_layouts()
        web_layout = next(l for l in layouts if l.name == "web")
        print(web_layout.template_path)  # "layouts/web.html"
    """
    return _default_loader.load_layouts()


def load_blueprints() -> list["PageSchemaDefinition"]:
    """
    Load all blueprints/page schemas as validated Pydantic instances.

    Returns:
        List of PageSchemaDefinition instances

    Example:
        from lightwave.schema.loaders.base import load_blueprints

        schemas = load_blueprints()
        marketing = next(s for s in schemas if s.name == "marketing-landing")
        print(marketing.default_layout)  # "web"
    """
    return _default_loader.load_blueprints()


def load_navigation(domain: str, location: str) -> list["NavItemSchema"]:
    """
    Load navigation items for a specific site and menu location.

    Args:
        domain: Site domain (e.g., "cineos.io")
        location: Menu location (e.g., "header")

    Returns:
        List of NavItemSchema instances sorted by order

    Example:
        from lightwave.schema.loaders.base import load_navigation

        header_nav = load_navigation("cineos.io", "header")
        for item in header_nav:
            print(f"{item.label}: {item.url}")
    """
    return _default_loader.load_navigation(domain, location)


def load_pages(domain: str) -> list["PageSeedSchema"]:
    """
    Load page seeds for a specific site.

    Args:
        domain: Site domain (e.g., "cineos.io")

    Returns:
        List of PageSeedSchema instances

    Example:
        from lightwave.schema.loaders.base import load_pages

        pages = load_pages("cineos.io")
        for page in pages:
            print(f"{page.path}: {page.title}")
    """
    return _default_loader.load_pages(domain)


def get_layout(name: str) -> "LayoutSchema":
    """
    Get a specific layout by name.

    Args:
        name: Layout name (e.g., "web")

    Returns:
        LayoutSchema instance

    Raises:
        KeyError: If layout not found

    Example:
        from lightwave.schema.loaders.base import get_layout

        web = get_layout("web")
        print(web.template_path)  # "layouts/web.html"
    """
    return _default_loader.get_layout(name)


def get_blueprint(name: str) -> "PageSchemaDefinition":
    """
    Get a specific blueprint/page schema by name.

    Args:
        name: Schema name (e.g., "marketing-landing")

    Returns:
        PageSchemaDefinition instance

    Raises:
        KeyError: If schema not found

    Example:
        from lightwave.schema.loaders.base import get_blueprint

        pricing = get_blueprint("pricing")
        pricing.validate_page_data({"headline": "Our Pricing"})
    """
    return _default_loader.get_blueprint(name)


# =============================================================================
# PACKAGES LOADING FUNCTIONS
# =============================================================================


def get_package_resolver() -> "PackageResolver":
    """
    Get the PackageResolver for package ecosystem queries.

    This is the PREFERRED API for package-related operations. It reads
    version and path information from pyproject.toml (not YAML) and only
    uses packages.yaml for publication state and criteria.

    Returns:
        PackageResolver instance

    Example:
        from lightwave.schema.loaders.base import get_package_resolver

        resolver = get_package_resolver()
        version = resolver.get_version("lightwave-core")  # From pyproject.toml
        method = resolver.get_ci_mode("lightwave-core")   # "git_clone"
        ready, issues = resolver.check_publish_ready("lightwave-core")
    """
    from lightwave.schema.pydantic.sst import PackageResolver

    return PackageResolver()


def load_packages() -> "PackageEcosystemSchema":
    """
    Load and validate packages.yaml as PackageEcosystemSchema.

    Returns:
        Validated PackageEcosystemSchema instance

    Example:
        from lightwave.schema.loaders.base import load_packages

        ecosystem = load_packages()
        method = ecosystem.get_ci_mode("lightwave-core")  # "git_clone"
    """
    from lightwave.schema.pydantic.models.packages import PackageEcosystemSchema

    return PackageEcosystemSchema.load()


def get_package(name: str) -> "PackageDefinition":
    """
    Get a specific package definition by name.

    Args:
        name: Package name (e.g., "lightwave-core")

    Returns:
        PackageDefinition instance

    Raises:
        KeyError: If package not found

    Example:
        from lightwave.schema.loaders.base import get_package

        pkg = get_package("lightwave-core")
        print(pkg.publication_state)  # "development"
    """
    ecosystem = load_packages()
    return ecosystem.get_package(name)


def get_ci_mode(package_name: str) -> str:
    """
    Get the CI install method for a package.

    Args:
        package_name: Package name

    Returns:
        CI install method string ("git_clone", "pypi_pinned", "pypi_semver")

    Example:
        from lightwave.schema.loaders.base import get_ci_mode

        method = get_ci_mode("lightwave-core")  # "git_clone"
    """
    ecosystem = load_packages()
    return ecosystem.get_ci_mode(package_name)


# =============================================================================
# WORKFLOW LOADING FUNCTIONS
# =============================================================================


def load_workflows() -> dict[str, Any]:
    """
    Load all workflows from the unified workflows/ directory.

    Returns:
        Dictionary with workflow data including all flows

    Example:
        from lightwave.schema.loaders.base import load_workflows

        workflows = load_workflows()
        signup = workflows["workflows"]["journeys/auth/signup"]
    """
    return _default_loader.load("workflows")


def load_workflow(path: str, use_cache: bool = True) -> dict[str, Any]:
    """
    Load a specific workflow by path.

    Supports both new workflow paths and legacy user_flows paths.

    Args:
        path: Workflow path (e.g., "journeys/auth/signup" or "auth/signup")
        use_cache: Whether to use cached data

    Returns:
        Workflow data dictionary

    Raises:
        KeyError: If workflow not found

    Example:
        from lightwave.schema.loaders.base import load_workflow

        # New path
        signup = load_workflow("journeys/auth/signup")

        # Legacy path (deprecated, still works)
        signup = load_workflow("auth/signup")
    """
    import warnings

    # Check for legacy aliases
    full_legacy_path = f"user_flows/{path}"
    if full_legacy_path in LEGACY_ALIASES:
        new_path = LEGACY_ALIASES[full_legacy_path]
        warnings.warn(
            f"'{path}' is a legacy path. Use '{new_path}' instead.",
            DeprecationWarning,
            stacklevel=2,
        )
        path = new_path.replace("workflows/", "")

    workflows_data = _default_loader.load("workflows", use_cache=use_cache)
    flows = workflows_data.get("workflows", {})

    if path in flows:
        return flows[path]

    # Try with trailing slash variations
    for key in flows:
        if key.endswith(f"/{path}") or key == path:
            return flows[key]

    available = list(flows.keys())[:10]
    raise KeyError(f"Workflow '{path}' not found. Available: {available}...")


def load_user_flows(path: str | None = None) -> dict[str, Any]:
    """
    Load user flows (deprecated, use load_workflow instead).

    This function is maintained for backward compatibility.
    New code should use load_workflow() with the new paths.

    Args:
        path: Optional specific flow path (e.g., "auth/signup")

    Returns:
        User flow data dictionary

    Example:
        from lightwave.schema.loaders.base import load_user_flows

        # Load all flows
        flows = load_user_flows()

        # Load specific flow (deprecated)
        signup = load_user_flows("auth/signup")
    """
    import warnings

    warnings.warn(
        "load_user_flows is deprecated. Use load_workflow() instead.",
        DeprecationWarning,
        stacklevel=2,
    )

    if path is None:
        return _default_loader.load("user_flows")

    data = _default_loader.load("user_flows")
    flows = data.get("user_flows", {})

    if path in flows:
        return flows[path]

    raise KeyError(f"User flow '{path}' not found")


# =============================================================================
# SITE TYPE BLUEPRINTS LOADING FUNCTIONS
# =============================================================================


@lru_cache(maxsize=1)
def load_site_type_blueprints() -> dict[str, Any]:
    """
    Load site type blueprints defining required pages per site type.

    Returns:
        Dictionary containing:
        - universal_legal_pages: Pages required by ALL site types
        - site_type_blueprints: Per-type requirements (portfolio, ecommerce, etc.)
        - eu_specific_pages: Additional EU compliance pages

    Example:
        from lightwave.schema.loaders import load_site_type_blueprints

        blueprints = load_site_type_blueprints()
        subscription = blueprints["site_type_blueprints"]["subscription"]
        required_pages = subscription["required_pages"]

        # Get universal legal pages
        universal = blueprints["universal_legal_pages"]
        # [{"path": "/privacy/", ...}, {"path": "/terms/", ...}, ...]
    """
    return _default_loader.load("site_type_blueprints")


def get_site_type_blueprint(site_type: str) -> dict[str, Any]:
    """
    Get the blueprint for a specific site type.

    Args:
        site_type: One of "portfolio", "ecommerce", "marketing", "subscription"

    Returns:
        Dictionary containing required_pages, optional_pages, features, etc.

    Raises:
        KeyError: If site_type not found

    Example:
        from lightwave.schema.loaders import get_site_type_blueprint

        subscription = get_site_type_blueprint("subscription")
        print(subscription["required_pages"])  # List of required page definitions
        print(subscription["features"])  # {"use_teams": True, ...}
    """
    data = load_site_type_blueprints()
    blueprints = data.get("site_type_blueprints", {})

    if site_type not in blueprints:
        available = list(blueprints.keys())
        raise KeyError(f"Site type '{site_type}' not found. Available: {available}")

    return blueprints[site_type]


def get_required_pages_for_site_type(site_type: str, include_universal: bool = True) -> list[dict[str, Any]]:
    """
    Get all required pages for a specific site type.

    Convenience function that combines universal legal pages with
    site-type-specific requirements.

    Args:
        site_type: One of "portfolio", "ecommerce", "marketing", "subscription"
        include_universal: Whether to include universal legal pages (default: True)

    Returns:
        List of page definitions (path, blueprint, title, regulations, etc.)

    Example:
        from lightwave.schema.loaders import get_required_pages_for_site_type

        # Get all required pages for subscription SaaS
        pages = get_required_pages_for_site_type("subscription")
        paths = [p["path"] for p in pages]
        # ["/privacy/", "/terms/", "/cookies/", "/contact/", "/", "/pricing/", ...]
    """
    data = load_site_type_blueprints()
    pages = []

    # Get universal legal pages if requested
    if include_universal:
        blueprint = data.get("site_type_blueprints", {}).get(site_type, {})
        if blueprint.get("inherits_universal", True):
            pages.extend(data.get("universal_legal_pages", []))

    # Get site-type-specific pages
    blueprint = get_site_type_blueprint(site_type)
    pages.extend(blueprint.get("required_pages", []))

    return pages
