"""
Unified configuration manager.

Provides centralized access to all configuration across the MarkiTect project.
"""

import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import Dict, Any, Optional, List, Union

from .base import BaseConfig
from .exceptions import ConfigurationError
from .loaders import resolve_path


@dataclass
class MarkitectConfig(BaseConfig):
    """Main MarkiTect configuration.

    Consolidates configuration for all MarkiTect components with standardized
    MARKITECT_ environment variable prefix.
    """

    # Repository settings
    gitea_url: str = "http://localhost:3000"
    repo_owner: str = ""
    repo_name: str = ""
    api_token: str = ""

    # Workspace and directory settings
    workspace_dir: Path = field(default_factory=lambda: Path(".markitect_workspace"))
    database_path: Path = field(default_factory=lambda: Path.home() / ".markitect" / "markitect.db")
    cache_dir: Path = field(default_factory=lambda: Path(".ast_cache"))

    # Test settings
    tests_dir: Path = field(default_factory=lambda: Path("tests"))
    test_file_pattern: str = "test_issue_{issue_num}_{scenario}.py"

    # AI and command settings
    claude_code_command: str = "claude"

    # Legacy compatibility
    _legacy_loaded: bool = field(default=False, init=False)

    def get_env_prefix(self) -> str:
        """Get environment variable prefix."""
        return "MARKITECT_"

    def get_config_files(self) -> List[Union[str, Path]]:
        """Get configuration files to load."""
        return [
            ".markitect.env",      # New unified config
            ".env.markitect",      # Alternative naming
            ".env.tddai",          # Legacy TDDAI config
            ".env"                 # General environment file
        ]

    def validate(self) -> None:
        """Validate configuration."""
        # Always ensure legacy environment variables are loaded before validation
        self.load_legacy_environment()
        self._legacy_loaded = True

        # Validate required fields
        self.validate_required_fields('gitea_url', 'repo_owner', 'repo_name')

        # Validate URLs
        self.validate_url('gitea_url')

        # Ensure directories exist or can be created
        self.validate_path_exists('workspace_dir', create_if_missing=True)
        self.validate_path_exists('cache_dir', create_if_missing=True)
        self.validate_path_exists('tests_dir', create_if_missing=True)

        # Ensure database directory exists
        if self.database_path:
            self.validate_path_exists(
                str(self.database_path.parent),
                create_if_missing=True
            )

    def get_legacy_mapping(self) -> Dict[str, str]:
        """Get legacy environment variable mapping."""
        return {
            # TDDAI legacy variables
            'TDDAI_GITEA_URL': 'gitea_url',
            'TDDAI_REPO_OWNER': 'repo_owner',
            'TDDAI_REPO_NAME': 'repo_name',
            'TDDAI_WORKSPACE_DIR': 'workspace_dir',
            'TDDAI_TESTS_DIR': 'tests_dir',
            'TDDAI_TEST_FILE_PATTERN': 'test_file_pattern',
            'TDDAI_CLAUDE_CODE_COMMAND': 'claude_code_command',

            # Gitea legacy variables
            'GITEA_API_TOKEN': 'api_token',
            'GITEA_BASE_URL': 'gitea_url',
            'GITEA_REPO_OWNER': 'repo_owner',
            'GITEA_REPO_NAME': 'repo_name',

            # Cache legacy variables
            'XDG_CACHE_HOME': 'cache_dir',
        }

    def get_tddai_compatible_dict(self) -> Dict[str, Any]:
        """Get configuration in TDDAI-compatible format.

        Returns configuration that can be used to create TddaiConfig
        objects for backward compatibility.
        """
        return {
            'workspace_dir': self.workspace_dir,
            'gitea_url': self.gitea_url,
            'repo_owner': self.repo_owner,
            'repo_name': self.repo_name,
            'tests_dir': self.tests_dir,
            'test_file_pattern': self.test_file_pattern,
            'claude_code_command': self.claude_code_command
        }

    def get_gitea_compatible_dict(self) -> Dict[str, Any]:
        """Get configuration in Gitea-compatible format.

        Returns configuration that can be used to create GiteaConfig
        objects for backward compatibility.
        """
        return {
            'base_url': self.gitea_url,
            'repo_owner': self.repo_owner,
            'repo_name': self.repo_name,
            'auth_token': self.api_token
        }


class UnifiedConfigManager:
    """Centralized configuration manager.

    Provides singleton access to unified configuration and manages
    backward compatibility with existing configuration systems.
    """

    _instance: Optional['UnifiedConfigManager'] = None
    _config: Optional[MarkitectConfig] = None

    def __new__(cls) -> 'UnifiedConfigManager':
        """Ensure singleton instance."""
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self):
        """Initialize configuration manager."""
        if self._config is None:
            self._config = MarkitectConfig()

    @property
    def config(self) -> MarkitectConfig:
        """Get the unified configuration."""
        if self._config is None:
            self._config = MarkitectConfig()
        return self._config

    def reload(self) -> None:
        """Reload configuration from environment and files."""
        self._config = MarkitectConfig()

    def validate_all(self) -> None:
        """Validate all configuration."""
        self.config.validate()

    def get_status(self) -> Dict[str, Any]:
        """Get configuration status for debugging.

        Returns:
            Dictionary with configuration status information
        """
        try:
            self.validate_all()
            valid = True
            errors = []
        except ConfigurationError as e:
            valid = False
            errors = [str(e)]

        return {
            'valid': valid,
            'errors': errors,
            'config_files_found': [
                str(f) for f in self.config.get_config_files()
                if Path(f).exists()
            ],
            'environment_variables': {
                key: '***' if 'token' in key.lower() or 'password' in key.lower() else value
                for key, value in os.environ.items()
                if key.startswith('MARKITECT_') or key.startswith('TDDAI_') or key.startswith('GITEA_')
            },
            'resolved_paths': {
                'workspace_dir': str(self.config.workspace_dir),
                'database_path': str(self.config.database_path),
                'cache_dir': str(self.config.cache_dir),
                'tests_dir': str(self.config.tests_dir)
            }
        }


# Global configuration manager instance
_manager: Optional[UnifiedConfigManager] = None


def get_unified_config() -> MarkitectConfig:
    """Get the unified configuration instance.

    Returns:
        The global MarkitectConfig instance

    Raises:
        ConfigurationError: If configuration is invalid
    """
    global _manager
    if _manager is None:
        _manager = UnifiedConfigManager()
    return _manager.config


def reload_config() -> None:
    """Reload configuration from environment and files."""
    global _manager
    if _manager is not None:
        _manager.reload()
    else:
        _manager = UnifiedConfigManager()


def get_config_status() -> Dict[str, Any]:
    """Get configuration status for debugging."""
    global _manager
    if _manager is None:
        _manager = UnifiedConfigManager()
    return _manager.get_status()