"""
Config Resolution Engine - 4-Level Hierarchy

Resolution order (most specific wins):
1. Connector Defaults - connectors/{name}/defaults.yml
2. Source - sources/{source_name}.yml (including default_sync)
3. Group - Optional grouping within source config
4. Resource - Per-table overrides in source config

Priority: Resource > Group > Source > Connector Defaults
"""

import os
from typing import Any, Dict, List, Optional
from .utils import (
    deep_merge,
    load_yaml,
    get_connectors_path,
    get_configs_path,
    file_exists,
)


class ConfigResolver:
    """
    Resolves configuration from the 4-level hierarchy.

    Usage:
        resolver = ConfigResolver()
        source_config = resolver.load_source_config("notion_wiki")
        resource_config = resolver.resolve_resource_config(source_config, "database_rows")
    """

    def __init__(self, base_path: Optional[str] = None):
        """
        Initialize config resolver.

        Args:
            base_path: Base path for configs (default: from environment)
        """
        if base_path:
            self.connectors_path = f"{base_path}/connectors"
            self.configs_path = f"{base_path}/configs"
        else:
            self.connectors_path = get_connectors_path()
            self.configs_path = get_configs_path()

        self._connector_cache: Dict[str, Dict] = {}

    def load_connector_defaults(self, connector_name: str) -> Dict[str, Any]:
        """
        Load connector defaults (Level 1).

        Args:
            connector_name: Name of the connector (e.g., "notion")

        Returns:
            Connector defaults dictionary
        """
        if connector_name in self._connector_cache:
            return self._connector_cache[connector_name]

        defaults_path = f"{self.connectors_path}/{connector_name}/defaults.yml"
        if file_exists(defaults_path):
            defaults = load_yaml(defaults_path)
        else:
            defaults = {}

        self._connector_cache[connector_name] = defaults
        return defaults

    def load_connector_manifest(self, connector_name: str) -> Dict[str, Any]:
        """
        Load connector manifest (metadata).

        Args:
            connector_name: Name of the connector

        Returns:
            Connector manifest dictionary
        """
        manifest_path = f"{self.connectors_path}/{connector_name}/manifest.yml"
        if file_exists(manifest_path):
            return load_yaml(manifest_path)
        return {}

    def load_source_config(self, source_name: str) -> Dict[str, Any]:
        """
        Load source config (Level 2).

        Args:
            source_name: Name of the source (e.g., "notion_wiki")

        Returns:
            Source config dictionary

        Raises:
            FileNotFoundError: If source config doesn't exist
        """
        source_path = f"{self.configs_path}/sources/{source_name}.yml"
        if not file_exists(source_path):
            raise FileNotFoundError(f"Source config not found: {source_path}")

        return load_yaml(source_path)

    def get_group_for_resource(
        self, source_config: Dict[str, Any], resource_name: str
    ) -> Optional[Dict[str, Any]]:
        """
        Find the group config for a resource (Level 3).

        Args:
            source_config: Source configuration
            resource_name: Name of the resource

        Returns:
            Group config if resource belongs to a group, None otherwise
        """
        groups = source_config.get("groups", {})
        for group_name, group_config in groups.items():
            if resource_name in group_config.get("resources", []):
                # Return group settings without the 'resources' list
                return {k: v for k, v in group_config.items() if k != "resources"}
        return None

    def resolve_resource_config(
        self, source_config: Dict[str, Any], resource_name: str
    ) -> Dict[str, Any]:
        """
        Resolve effective config for a resource.

        Applies the 4-level hierarchy:
        Priority: Resource > Group > Source > Connector Defaults

        Args:
            source_config: Source configuration (from load_source_config)
            resource_name: Name of the resource to resolve

        Returns:
            Fully resolved configuration for the resource
        """
        connector_name = source_config.get("connector", "rest_api_generic")

        # Level 1: Start with connector defaults
        connector_defaults = self.load_connector_defaults(connector_name)
        effective = deep_merge({}, connector_defaults.get("defaults", {}))

        # Apply resource-specific connector defaults if exists
        resource_connector_defaults = connector_defaults.get("resource_defaults", {}).get(resource_name, {})
        effective = deep_merge(effective, resource_connector_defaults)

        # Level 2: Apply source-level config (including default_sync)
        source_level = {
            k: v for k, v in source_config.items()
            if k not in ["groups", "resources", "source_name", "connector",
                        "connector_version", "secrets"]
        }
        effective = deep_merge(effective, source_level)

        # Level 3: Apply group config (if resource belongs to a group)
        group_config = self.get_group_for_resource(source_config, resource_name)
        if group_config:
            effective = deep_merge(effective, group_config)

        # Level 4: Apply resource-specific overrides
        # Handle both list format (new) and dict format (legacy)
        resources = source_config.get("resources", [])
        resource_config = {}
        if isinstance(resources, list):
            for res in resources:
                if res.get("name") == resource_name:
                    resource_config = {k: v for k, v in res.items() if k != "name"}
                    break
        elif isinstance(resources, dict):
            resource_config = resources.get(resource_name, {})
        effective = deep_merge(effective, resource_config)

        # Add metadata
        effective["_resource_name"] = resource_name
        effective["_source_name"] = source_config.get("source_name", "unknown")
        effective["_connector"] = connector_name

        return effective

    def get_enabled_resources(self, source_config: Dict[str, Any]) -> List[str]:
        """
        Get list of enabled resources from source config.

        Supports both list format (new) and dict format (legacy):
        - List: [{"name": "projects", "enabled": true}, ...]
        - Dict: {"projects": {"enabled": true}, ...}

        Args:
            source_config: Source configuration

        Returns:
            List of enabled resource names
        """
        resources = source_config.get("resources", [])
        enabled = []

        if isinstance(resources, list):
            # New list format
            for resource in resources:
                if resource.get("enabled", True):
                    name = resource.get("name")
                    if name:
                        enabled.append(name)
        elif isinstance(resources, dict):
            # Legacy dict format
            for name, config in resources.items():
                if isinstance(config, dict) and config.get("enabled", True):
                    enabled.append(name)
                elif config is None or config == {}:
                    enabled.append(name)

        return enabled


def resolve_resource_config(
    source_name: str,
    resource_name: str,
    base_path: Optional[str] = None,
) -> Dict[str, Any]:
    """
    Convenience function to resolve resource config.

    Args:
        source_name: Name of the source
        resource_name: Name of the resource
        base_path: Optional base path override

    Returns:
        Resolved resource configuration
    """
    resolver = ConfigResolver(base_path)
    source_config = resolver.load_source_config(source_name)
    return resolver.resolve_resource_config(source_config, resource_name)
