"""
Copyleft (C) 2026 Stefy Lanza <stefy@nexlab.net>

AISBF - AI Service Broker Framework || AI Should Be Free

Configuration management for AISBF.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

Why did the programmer quit his job? Because he didn't get arrays!

Configuration management for AISBF.
"""
from typing import Dict, List, Optional
from pydantic import BaseModel, Field
import json
import shutil
from pathlib import Path

class ProviderConfig(BaseModel):
    id: str
    name: str
    endpoint: str
    type: str
    api_key_required: bool
    rate_limit: float = 0.0

class RotationConfig(BaseModel):
    providers: List[Dict]

class AutoselectModelInfo(BaseModel):
    model_id: str
    description: str

class AutoselectConfig(BaseModel):
    model_name: str
    description: str
    fallback: str
    available_models: List[AutoselectModelInfo]

class AppConfig(BaseModel):
    providers: Dict[str, ProviderConfig]
    rotations: Dict[str, RotationConfig]
    autoselect: Dict[str, AutoselectConfig]
    error_tracking: Dict[str, Dict]

class Config:
    def __init__(self):
        self._ensure_config_directory()
        self._load_providers()
        self._load_rotations()
        self._load_autoselect()
        self._initialize_error_tracking()

    def _get_config_source_dir(self):
        """Get the directory containing default config files"""
        # Try installed location first
        installed_dirs = [
            Path('/usr/share/aisbf'),
            Path.home() / '.local' / 'share' / 'aisbf',
        ]
        
        for installed_dir in installed_dirs:
            if installed_dir.exists() and (installed_dir / 'providers.json').exists():
                return installed_dir
        
        # Fallback to source tree config directory
        # This is for development mode
        source_dir = Path(__file__).parent.parent / 'config'
        if source_dir.exists() and (source_dir / 'providers.json').exists():
            return source_dir
        
        # Last resort: try the old location in the package directory
        package_dir = Path(__file__).parent
        if (package_dir / 'providers.json').exists():
            return package_dir
        
        raise FileNotFoundError("Could not find configuration files")

    def _ensure_config_directory(self):
        """Ensure ~/.aisbf/ directory exists and copy default config files if needed"""
        config_dir = Path.home() / '.aisbf'
        
        # Create config directory if it doesn't exist
        config_dir.mkdir(exist_ok=True)
        
        # Get the source directory for default config files
        try:
            source_dir = self._get_config_source_dir()
        except FileNotFoundError:
            print("Warning: Could not find default configuration files")
            return
        
        # Copy default config files if they don't exist
        for config_file in ['providers.json', 'rotations.json', 'autoselect.json']:
            src = source_dir / config_file
            dst = config_dir / config_file
            
            if not dst.exists() and src.exists():
                shutil.copy2(src, dst)
                print(f"Created default config file: {dst}")

    def _load_providers(self):
        import logging
        logger = logging.getLogger(__name__)
        logger.info(f"=== Config._load_providers START ===")
        
        providers_path = Path.home() / '.aisbf' / 'providers.json'
        logger.info(f"Looking for providers at: {providers_path}")
        
        if not providers_path.exists():
            logger.info(f"User config not found, falling back to source config")
            # Fallback to source config if user config doesn't exist
            try:
                source_dir = self._get_config_source_dir()
                providers_path = source_dir / 'providers.json'
                logger.info(f"Using source config at: {providers_path}")
            except FileNotFoundError:
                logger.error("Could not find providers.json configuration file")
                raise FileNotFoundError("Could not find providers.json configuration file")
        
        logger.info(f"Loading providers from: {providers_path}")
        with open(providers_path) as f:
            data = json.load(f)
            self.providers = {k: ProviderConfig(**v) for k, v in data['providers'].items()}
            logger.info(f"Loaded {len(self.providers)} providers: {list(self.providers.keys())}")
            for provider_id, provider_config in self.providers.items():
                logger.info(f"  - {provider_id}: type={provider_config.type}, endpoint={provider_config.endpoint}")
            logger.info(f"=== Config._load_providers END ===")

    def _load_rotations(self):
        import logging
        logger = logging.getLogger(__name__)
        logger.info(f"=== Config._load_rotations START ===")
        
        rotations_path = Path.home() / '.aisbf' / 'rotations.json'
        logger.info(f"Looking for rotations at: {rotations_path}")
        
        if not rotations_path.exists():
            logger.info(f"User config not found, falling back to source config")
            # Fallback to source config if user config doesn't exist
            try:
                source_dir = self._get_config_source_dir()
                rotations_path = source_dir / 'rotations.json'
                logger.info(f"Using source config at: {rotations_path}")
            except FileNotFoundError:
                logger.error("Could not find rotations.json configuration file")
                raise FileNotFoundError("Could not find rotations.json configuration file")
        
        logger.info(f"Loading rotations from: {rotations_path}")
        with open(rotations_path) as f:
            data = json.load(f)
            self.rotations = {k: RotationConfig(**v) for k, v in data['rotations'].items()}
            logger.info(f"Loaded {len(self.rotations)} rotations: {list(self.rotations.keys())}")
            
            # Validate that all providers referenced in rotations exist
            logger.info(f"=== VALIDATING ROTATION PROVIDERS ===")
            available_providers = list(self.providers.keys())
            logger.info(f"Available providers: {available_providers}")
            
            for rotation_id, rotation_config in self.rotations.items():
                logger.info(f"Validating rotation: {rotation_id}")
                for provider in rotation_config.providers:
                    provider_id = provider['provider_id']
                    if provider_id not in self.providers:
                        logger.warning(f"!!! CONFIGURATION WARNING !!!")
                        logger.warning(f"Rotation '{rotation_id}' references provider '{provider_id}' which is NOT defined in providers.json")
                        logger.warning(f"Available providers: {available_providers}")
                        logger.warning(f"This provider will be SKIPPED during rotation requests")
                        logger.warning(f"Please add the provider to providers.json or remove it from the rotation configuration")
                        logger.warning(f"!!! END WARNING !!!")
                    else:
                        logger.info(f"  ✓ Provider '{provider_id}' is available")
            
            logger.info(f"=== Config._load_rotations END ===")

    def _load_autoselect(self):
        autoselect_path = Path.home() / '.aisbf' / 'autoselect.json'
        if not autoselect_path.exists():
            # Fallback to source config if user config doesn't exist
            try:
                source_dir = self._get_config_source_dir()
                autoselect_path = source_dir / 'autoselect.json'
            except FileNotFoundError:
                raise FileNotFoundError("Could not find autoselect.json configuration file")
        
        with open(autoselect_path) as f:
            data = json.load(f)
            self.autoselect = {k: AutoselectConfig(**v) for k, v in data.items()}

    def _initialize_error_tracking(self):
        self.error_tracking = {}
        for provider_id in self.providers:
            self.error_tracking[provider_id] = {
                'failures': 0,
                'last_failure': None,
                'disabled_until': None
            }

    def get_provider(self, provider_id: str) -> ProviderConfig:
        import logging
        logger = logging.getLogger(__name__)
        logger.info(f"Config.get_provider called with provider_id: {provider_id}")
        logger.info(f"Available providers: {list(self.providers.keys())}")
        result = self.providers.get(provider_id)
        if result:
            logger.info(f"Found provider: {result}")
        else:
            logger.warning(f"Provider {provider_id} not found!")
        return result

    def get_rotation(self, rotation_id: str) -> RotationConfig:
        return self.rotations.get(rotation_id)

    def get_autoselect(self, autoselect_id: str) -> AutoselectConfig:
        return self.autoselect.get(autoselect_id)

config = Config()
