"""
Configuration management service for LandPPT
"""

import os
import json
import logging
from typing import Dict, Any, Optional, List
from pathlib import Path
from dotenv import load_dotenv, set_key, unset_key

logger = logging.getLogger(__name__)


class ConfigService:
    """Configuration management service"""
    
    def __init__(self, env_file: str = ".env"):
        self.env_file = env_file
        self.env_path = Path(env_file)
        
        # Ensure .env file exists
        if not self.env_path.exists():
            self.env_path.touch()
        
        # Load environment variables with error handling
        try:
            load_dotenv(self.env_file)
        except (PermissionError, FileNotFoundError) as e:
            logger.warning(f"Could not load .env file {self.env_file}: {e}")
        except Exception as e:
            logger.warning(f"Error loading .env file {self.env_file}: {e}")
        
        # Configuration schema
        self.config_schema = {
            # AI Provider Configuration
            "openai_api_key": {"type": "password", "category": "ai_providers"},
            "openai_base_url": {"type": "url", "category": "ai_providers", "default": "https://api.openai.com/v1"},
            "openai_model": {"type": "select", "category": "ai_providers", "default": "gpt-4.1"},
            
            "anthropic_api_key": {"type": "password", "category": "ai_providers"},
            "anthropic_model": {"type": "select", "category": "ai_providers", "default": "claude-3.5-haiku-20240307"},

            "google_api_key": {"type": "password", "category": "ai_providers"},
            "google_base_url": {"type": "url", "category": "ai_providers", "default": "https://generativelanguage.googleapis.com"},
            "google_model": {"type": "text", "category": "ai_providers", "default": "gemini-2.5-flash"},
            
            "azure_openai_api_key": {"type": "password", "category": "ai_providers"},
            "azure_openai_endpoint": {"type": "url", "category": "ai_providers"},
            "azure_openai_deployment_name": {"type": "text", "category": "ai_providers"},
            "azure_openai_api_version": {"type": "text", "category": "ai_providers", "default": "gpt-4.1"},
            
            "ollama_base_url": {"type": "url", "category": "ai_providers", "default": "http://localhost:11434"},
            "ollama_model": {"type": "text", "category": "ai_providers", "default": "llama2"},
            
            # 302.AI Configuration
            "302ai_api_key": {"type": "password", "category": "ai_providers"},
            "302ai_base_url": {"type": "url", "category": "ai_providers", "default": "https://api.302.ai/v1"},
            "302ai_model": {"type": "text", "category": "ai_providers", "default": "gpt-4o"},
            
            "default_ai_provider": {"type": "select", "category": "ai_providers", "default": "openai"},
            
            # Model Role Overrides
            "default_model_provider": {"type": "select", "category": "model_roles", "default": ""},
            "default_model_name": {"type": "text", "category": "model_roles", "default": ""},
            "outline_model_provider": {"type": "select", "category": "model_roles", "default": ""},
            "outline_model_name": {"type": "text", "category": "model_roles", "default": ""},
            "creative_model_provider": {"type": "select", "category": "model_roles", "default": ""},
            "creative_model_name": {"type": "text", "category": "model_roles", "default": ""},
            "image_prompt_model_provider": {"type": "select", "category": "model_roles", "default": ""},
            "image_prompt_model_name": {"type": "text", "category": "model_roles", "default": ""},
            "slide_generation_model_provider": {"type": "select", "category": "model_roles", "default": ""},
            "slide_generation_model_name": {"type": "text", "category": "model_roles", "default": ""},
            "editor_assistant_model_provider": {"type": "select", "category": "model_roles", "default": ""},
            "editor_assistant_model_name": {"type": "text", "category": "model_roles", "default": ""},
            "template_generation_model_provider": {"type": "select", "category": "model_roles", "default": ""},
            "template_generation_model_name": {"type": "text", "category": "model_roles", "default": ""},
            "speech_script_model_provider": {"type": "select", "category": "model_roles", "default": ""},
            "speech_script_model_name": {"type": "text", "category": "model_roles", "default": ""},
            
            # Generation Parameters
            "max_tokens": {"type": "number", "category": "generation_params", "default": "16384"},
            "temperature": {"type": "number", "category": "generation_params", "default": "0.7"},
            "top_p": {"type": "number", "category": "generation_params", "default": "1.0"},
            
            # Parallel Generation Configuration
            "enable_parallel_generation": {"type": "boolean", "category": "generation_params", "default": "false"},
            "parallel_slides_count": {"type": "number", "category": "generation_params", "default": "3"},
            
            "tavily_api_key": {"type": "password", "category": "generation_params"},
            "tavily_max_results": {"type": "number", "category": "generation_params", "default": "10"},
            "tavily_search_depth": {"type": "select", "category": "generation_params", "default": "advanced"},

            # SearXNG Configuration
            "searxng_host": {"type": "url", "category": "generation_params"},
            "searxng_max_results": {"type": "number", "category": "generation_params", "default": "10"},
            "searxng_language": {"type": "text", "category": "generation_params", "default": "auto"},
            "searxng_timeout": {"type": "number", "category": "generation_params", "default": "30"},

            # Research Configuration
            "research_provider": {"type": "select", "category": "generation_params", "default": "tavily"},
            "research_enable_content_extraction": {"type": "boolean", "category": "generation_params", "default": "true"},
            "research_max_content_length": {"type": "number", "category": "generation_params", "default": "5000"},
            "research_extraction_timeout": {"type": "number", "category": "generation_params", "default": "30"},

            "apryse_license_key": {"type": "password", "category": "generation_params"},
            
            # Feature Flags
            "enable_network_mode": {"type": "boolean", "category": "feature_flags", "default": "true"},
            "enable_local_models": {"type": "boolean", "category": "feature_flags", "default": "false"},
            "enable_streaming": {"type": "boolean", "category": "feature_flags", "default": "true"},
            "log_level": {"type": "select", "category": "feature_flags", "default": "INFO"},
            "log_ai_requests": {"type": "boolean", "category": "feature_flags", "default": "false"},
            "debug": {"type": "boolean", "category": "feature_flags", "default": "true"},
            
            # App Configuration
            "host": {"type": "text", "category": "app_config", "default": "0.0.0.0"},
            "port": {"type": "number", "category": "app_config", "default": "8000"},
            "base_url": {"type": "url", "category": "app_config", "default": "http://localhost:8000"},
            "reload": {"type": "boolean", "category": "app_config", "default": "true"},
            "secret_key": {"type": "password", "category": "app_config", "default": "your-very-secure-secret-key"},
            "access_token_expire_minutes": {"type": "number", "category": "app_config", "default": "30"},
            "max_file_size": {"type": "number", "category": "app_config", "default": "10485760"},
            "upload_dir": {"type": "text", "category": "app_config", "default": "uploads"},
            "cache_ttl": {"type": "number", "category": "app_config", "default": "3600"},
            "database_url": {"type": "text", "category": "app_config", "default": "sqlite:///./landppt.db"},

            # Image Service Configuration
            "enable_image_service": {"type": "boolean", "category": "image_service", "default": "false"},

            # Multi-source Image Configuration
            "enable_local_images": {"type": "boolean", "category": "image_service", "default": "true"},
            "enable_network_search": {"type": "boolean", "category": "image_service", "default": "false"},
            "enable_ai_generation": {"type": "boolean", "category": "image_service", "default": "false"},

            # Local Images Configuration
            "local_images_smart_selection": {"type": "boolean", "category": "image_service", "default": "true"},
            "max_local_images_per_slide": {"type": "number", "category": "image_service", "default": "2"},

            # Network Search Configuration
            "default_network_search_provider": {"type": "select", "category": "image_service", "default": "unsplash"},
            "max_network_images_per_slide": {"type": "number", "category": "image_service", "default": "2"},

            # AI Generation Configuration
            "default_ai_image_provider": {"type": "select", "category": "image_service", "default": "dalle"},
            "max_ai_images_per_slide": {"type": "number", "category": "image_service", "default": "1"},
            "ai_image_quality": {"type": "select", "category": "image_service", "default": "standard"},

            # Global Image Configuration
            "max_total_images_per_slide": {"type": "number", "category": "image_service", "default": "3"},
            "enable_smart_image_selection": {"type": "boolean", "category": "image_service", "default": "true"},

            # Image Generation Providers
            "openai_api_key_image": {"type": "password", "category": "image_service"},
            "stability_api_key": {"type": "password", "category": "image_service"},
            "siliconflow_api_key": {"type": "password", "category": "image_service"},
            "default_ai_image_provider": {"type": "select", "category": "image_service", "default": "dalle"},

            # Pollinations Configuration
            "pollinations_api_token": {"type": "password", "category": "image_service"},
            "pollinations_referrer": {"type": "text", "category": "image_service"},
            "pollinations_model": {"type": "select", "category": "image_service", "default": "flux"},
            "pollinations_enhance": {"type": "boolean", "category": "image_service", "default": "false"},
            "pollinations_safe": {"type": "boolean", "category": "image_service", "default": "false"},
            "pollinations_nologo": {"type": "boolean", "category": "image_service", "default": "false"},
            "pollinations_private": {"type": "boolean", "category": "image_service", "default": "false"},
            "pollinations_transparent": {"type": "boolean", "category": "image_service", "default": "false"},

            # Image Search Providers
            "unsplash_access_key": {"type": "password", "category": "image_service"},
            "pixabay_api_key": {"type": "password", "category": "image_service"},
            "searxng_host": {"type": "url", "category": "image_service"},
            "dalle_image_size": {"type": "select", "category": "image_service", "default": "1792x1024"},
            "dalle_image_quality": {"type": "select", "category": "image_service", "default": "standard"},
            "dalle_image_style": {"type": "select", "category": "image_service", "default": "natural"},
            "siliconflow_image_size": {"type": "select", "category": "image_service", "default": "1024x1024"},
            "siliconflow_steps": {"type": "number", "category": "image_service", "default": 20},
            "siliconflow_guidance_scale": {"type": "number", "category": "image_service", "default": 7.5},
        }
        

    
    def get_all_config(self) -> Dict[str, Any]:
        """Get all configuration values"""
        config = {}
        
        for key, schema in self.config_schema.items():
            env_key = key.upper()
            value = os.getenv(env_key)
            
            if value is None:
                value = schema.get("default", "")
            
            # Convert boolean strings
            if schema["type"] == "boolean":
                if isinstance(value, str):
                    value = value.lower() in ("true", "1", "yes", "on")
            
            config[key] = value
        
        return config
    
    def get_config_by_category(self, category: str) -> Dict[str, Any]:
        """Get configuration values by category"""
        config = {}
        
        for key, schema in self.config_schema.items():
            if schema["category"] == category:
                env_key = key.upper()
                value = os.getenv(env_key)
                
                if value is None:
                    value = schema.get("default", "")
                
                # Convert boolean strings
                if schema["type"] == "boolean":
                    if isinstance(value, str):
                        value = value.lower() in ("true", "1", "yes", "on")
                
                config[key] = value
        
        return config
    
    def update_config(self, config: Dict[str, Any]) -> bool:
        """Update configuration values"""
        try:
            for key, value in config.items():
                if key in self.config_schema:
                    env_key = key.upper()

                    # Convert boolean values to strings
                    if isinstance(value, bool):
                        value = "true" if value else "false"
                    else:
                        value = str(value)

                    # Update .env file (without quotes)
                    set_key(self.env_file, env_key, value, quote_mode="never")

                    # Update current environment
                    os.environ[env_key] = value

            # Reload environment variables with error handling
            try:
                load_dotenv(self.env_file, override=True)
            except (PermissionError, FileNotFoundError) as e:
                logger.warning(f"Could not reload .env file {self.env_file}: {e}")
            except Exception as e:
                logger.warning(f"Error reloading .env file {self.env_file}: {e}")

            # Reload AI configuration if any AI-related config was updated
            ai_related_keys = [k for k in config.keys() if k in self.config_schema and
                             self.config_schema[k]["category"] in ["ai_providers", "generation_params", "model_roles"]]
            if ai_related_keys:
                self._reload_ai_config()

            # Reload app configuration if any app-related config was updated
            app_related_keys = [k for k in config.keys() if k in self.config_schema and
                              self.config_schema[k]["category"] == "app_config"]
            if app_related_keys:
                self._reload_app_config()

            # Reload image service configuration if any image-related config was updated
            image_related_keys = [k for k in config.keys() if k in self.config_schema and
                                self.config_schema[k]["category"] == "image_service"]
            if image_related_keys:
                self._reload_image_config()

            logger.info(f"Updated {len(config)} configuration values")
            return True

        except Exception as e:
            logger.error(f"Failed to update configuration: {e}")
            return False

    def _reload_ai_config(self):
        """Reload AI configuration"""
        try:
            from ..core.config import reload_ai_config, ai_config
            from ..ai.providers import reload_ai_providers
            from .service_instances import reload_services

            logger.info("Starting AI configuration reload process...")

            # Reload AI configuration
            reload_ai_config()
            logger.info(f"AI config reloaded. Tavily API key: {'***' + ai_config.tavily_api_key[-4:] if ai_config.tavily_api_key and len(ai_config.tavily_api_key) > 4 else 'None'}")

            # Clear AI provider cache to force reload with new config
            reload_ai_providers()
            logger.info("AI providers reloaded")

            # Reload service instances to pick up new configuration
            reload_services()
            logger.info("Service instances reloaded")

            logger.info("AI configuration, providers, and services reloaded successfully")
        except Exception as e:
            logger.error(f"Failed to reload AI configuration: {e}")
            import traceback
            logger.error(f"Reload traceback: {traceback.format_exc()}")

    def _reload_app_config(self):
        """Reload application configuration"""
        try:
            from ..core.config import app_config

            # Force reload of app configuration
            app_config.__init__()

            logger.info("Application configuration reloaded successfully")
        except Exception as e:
            logger.error(f"Failed to reload application configuration: {e}")

    def _reload_image_config(self):
        """Reload image service configuration"""
        try:
            from ..services.image.config.image_config import image_config

            # 重新加载环境变量配置
            image_config._load_env_config()

            # 同时更新Pollinations特定配置
            current_config = self.get_all_config()
            pollinations_updates = {}

            # 映射配置项到Pollinations配置
            if 'pollinations_api_token' in current_config:
                pollinations_updates['api_token'] = current_config['pollinations_api_token']
            if 'pollinations_referrer' in current_config:
                pollinations_updates['referrer'] = current_config['pollinations_referrer']
            if 'pollinations_model' in current_config:
                pollinations_updates['model'] = current_config['pollinations_model']
            if 'pollinations_enhance' in current_config:
                value = current_config['pollinations_enhance']
                pollinations_updates['default_enhance'] = value if isinstance(value, bool) else str(value).lower() == 'true'
            if 'pollinations_safe' in current_config:
                value = current_config['pollinations_safe']
                pollinations_updates['default_safe'] = value if isinstance(value, bool) else str(value).lower() == 'true'
            if 'pollinations_nologo' in current_config:
                value = current_config['pollinations_nologo']
                pollinations_updates['default_nologo'] = value if isinstance(value, bool) else str(value).lower() == 'true'
            if 'pollinations_private' in current_config:
                value = current_config['pollinations_private']
                pollinations_updates['default_private'] = value if isinstance(value, bool) else str(value).lower() == 'true'
            if 'pollinations_transparent' in current_config:
                value = current_config['pollinations_transparent']
                pollinations_updates['default_transparent'] = value if isinstance(value, bool) else str(value).lower() == 'true'

            # 如果有Pollinations配置更新，应用它们
            if pollinations_updates:
                image_config.update_config({'pollinations': pollinations_updates})

            logger.info("Image service configuration reloaded")
        except Exception as e:
            logger.error(f"Failed to reload image service configuration: {e}")

    def update_config_by_category(self, category: str, config: Dict[str, Any]) -> bool:
        """Update configuration values for a specific category"""
        # Filter config to only include keys from the specified category
        filtered_config = {}
        
        for key, value in config.items():
            if key in self.config_schema and self.config_schema[key]["category"] == category:
                filtered_config[key] = value
        
        return self.update_config(filtered_config)
    
    def get_config_schema(self) -> Dict[str, Any]:
        """Get configuration schema"""
        return self.config_schema
    
    def validate_config(self, config: Dict[str, Any]) -> Dict[str, List[str]]:
        """Validate configuration values"""
        errors = {}
        
        for key, value in config.items():
            if key not in self.config_schema:
                if "unknown" not in errors:
                    errors["unknown"] = []
                errors["unknown"].append(f"Unknown configuration key: {key}")
                continue
            
            schema = self.config_schema[key]
            field_errors = []
            
            # Type validation
            if schema["type"] == "number":
                try:
                    num_value = float(value)
                    # Special validation for access_token_expire_minutes - allow 0 for never expire
                    if key == "access_token_expire_minutes" and num_value < 0:
                        field_errors.append(f"{key} must be 0 (never expire) or a positive number")
                except (ValueError, TypeError):
                    field_errors.append(f"{key} must be a number")
            
            elif schema["type"] == "boolean":
                if isinstance(value, str):
                    if value.lower() not in ("true", "false", "1", "0", "yes", "no", "on", "off"):
                        field_errors.append(f"{key} must be a boolean value")
            
            elif schema["type"] == "url":
                if value and not (value.startswith("http://") or value.startswith("https://")):
                    field_errors.append(f"{key} must be a valid URL")
            
            if field_errors:
                errors[key] = field_errors
        
        return errors
    
    def reset_to_defaults(self, category: Optional[str] = None) -> bool:
        """Reset configuration to default values"""
        try:
            config_to_reset = {}
            
            for key, schema in self.config_schema.items():
                if category is None or schema["category"] == category:
                    default_value = schema.get("default", "")
                    config_to_reset[key] = default_value
            
            return self.update_config(config_to_reset)
            
        except Exception as e:
            logger.error(f"Failed to reset configuration: {e}")
            return False
    
    def backup_config(self, backup_file: str) -> bool:
        """Backup current configuration"""
        try:
            config = self.get_all_config()
            
            with open(backup_file, 'w') as f:
                json.dump(config, f, indent=2)
            
            logger.info(f"Configuration backed up to {backup_file}")
            return True
            
        except Exception as e:
            logger.error(f"Failed to backup configuration: {e}")
            return False
    
    def restore_config(self, backup_file: str) -> bool:
        """Restore configuration from backup"""
        try:
            with open(backup_file, 'r') as f:
                config = json.load(f)
            
            return self.update_config(config)
            
        except Exception as e:
            logger.error(f"Failed to restore configuration: {e}")
            return False


# Global config service instance
config_service = ConfigService()


def get_config_service() -> ConfigService:
    """Get config service instance"""
    return config_service
