import os
import json
import logging
from datetime import timezone, timedelta
from dotenv import load_dotenv
from urllib.parse import quote_plus
from typing import Any, Optional, Dict
from pathlib import Path

# 加载环境变量（如果文件存在）
try:
    load_dotenv()
except Exception:
    # 如果无法读取 .env 文件（如权限问题），继续使用环境变量和默认值
    pass

# 导入数据库配置模型
from app.models.database.models import SystemConfig as DBSystemConfig

# ==================== 配置类定义（从 app_config.py 合并） ====================
from dataclasses import dataclass
from typing import Optional

@dataclass
class AppConfig:
    """应用配置"""
    secret_key: str
    environment: str = 'development'
    debug: bool = False
    host: str = '0.0.0.0'
    port: int = 5002
    threaded: bool = True
    use_reloader: bool = False
    
    @property
    def is_production(self) -> bool:
        """是否为生产环境"""
        return self.environment == 'production'
    
    @property
    def is_development(self) -> bool:
        """是否为开发环境"""
        return self.environment == 'development'
    
    @classmethod
    def from_env(cls) -> 'AppConfig':
        """从环境变量加载配置"""
        env = os.getenv('FLASK_ENV', 'development')
        is_prod = env == 'production'
        use_reloader = os.getenv('FLASK_USE_RELOADER', 'false').lower() == 'true' if not is_prod else False
        
        return cls(
            secret_key=os.getenv('SECRET_KEY', 'dev-secret-key'),
            environment=env,
            debug=not is_prod,
            host=os.getenv('FLASK_HOST', '0.0.0.0'),
            port=int(os.getenv('FLASK_PORT', '5002')),
            threaded=True,
            use_reloader=use_reloader
        )

@dataclass
class DatabaseConfig:
    """数据库配置"""
    type: str = 'postgresql'
    host: str = 'localhost'
    port: int = 5432
    database: str = 'ctf'
    user: str = 'postgres'
    password: str = ''
    sqlite_db_name: str = 'ctf.db'
    instance_path: Optional[str] = None
    
    @classmethod
    def from_env(cls, base_dir: str) -> 'DatabaseConfig':
        """从环境变量加载配置"""
        db_type = os.getenv('DATABASE_TYPE', 'postgresql')
        
        if db_type == 'postgresql':
            return cls(
                type='postgresql',
                host=os.getenv('POSTGRES_HOST', 'localhost'),
                port=int(os.getenv('POSTGRES_PORT', '5432')),
                database=os.getenv('POSTGRES_DB', 'ctf'),
                user=os.getenv('POSTGRES_USER', 'postgres'),
                password=os.getenv('POSTGRES_PASSWORD', '123456')
            )
        else:
            instance_path = os.path.join(base_dir, 'instance')
            return cls(
                type='sqlite',
                sqlite_db_name=os.getenv('SQLITE_DB_NAME', 'ctf.db'),
                instance_path=instance_path
            )
    
    def get_database_uri(self, base_dir: str) -> str:
        """获取数据库连接URI"""
        if self.type == 'postgresql':
            encoded_user = quote_plus(self.user)
            encoded_password = quote_plus(self.password)
            return f'postgresql://{encoded_user}:{encoded_password}@{self.host}:{self.port}/{self.database}?client_encoding=utf8'
        else:
            if not self.instance_path:
                self.instance_path = os.path.join(base_dir, 'instance')
            os.makedirs(self.instance_path, exist_ok=True)
            db_path = os.path.join(self.instance_path, self.sqlite_db_name)
            return f'sqlite:///{db_path}'

@dataclass
class LoggingConfig:
    """日志配置"""
    level: str = 'INFO'
    format: str = '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
    file: Optional[str] = None
    console: bool = True
    
    @classmethod
    def from_env(cls, environment: str) -> 'LoggingConfig':
        """从环境变量加载配置"""
        is_prod = environment == 'production'
        
        if is_prod:
            return cls(
                level='WARNING',
                format='%(asctime)s [%(levelname)s] %(message)s',
                file='logs/production.log',
                console=False
            )
        else:
            return cls(
                level='INFO',
                format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
                console=True
            )

@dataclass
class SessionConfig:
    """会话配置"""
    type: str = 'filesystem'
    file_dir: Optional[str] = None
    permanent_lifetime: int = 3600  # 1小时
    
    @classmethod
    def from_env(cls, base_dir: str) -> 'SessionConfig':
        """从环境变量加载配置"""
        return cls(
            type='filesystem',
            file_dir=os.path.join(base_dir, 'flask_session'),
            permanent_lifetime=3600
        )

@dataclass
class SystemConfig:
    """系统配置（统一配置类）"""
    app: AppConfig
    database: DatabaseConfig
    logging: LoggingConfig
    session: SessionConfig
    base_dir: str
    
    @classmethod
    def load(cls, base_dir: Optional[str] = None) -> 'SystemConfig':
        """加载所有配置"""
        if base_dir is None:
            base_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
        
        app_config = AppConfig.from_env()
        database_config = DatabaseConfig.from_env(base_dir)
        logging_config = LoggingConfig.from_env(app_config.environment)
        session_config = SessionConfig.from_env(base_dir)
        
        return cls(
            app=app_config,
            database=database_config,
            logging=logging_config,
            session=session_config,
            base_dir=base_dir
        )
# ==================== 配置类定义结束 ====================

logger = logging.getLogger(__name__)

# 加载系统配置
_system_config = SystemConfig.load()

# 加载 JSON 配置文件（统一配置管理器功能）
_config_data_dir = os.path.join(_system_config.base_dir, 'config', 'data')
_json_configs: Dict[str, Dict] = {}

def _load_json_configs():
    """加载 JSON 配置文件"""
    global _json_configs
    try:
        # 加载场景映射
        scene_config_path = os.path.join(_config_data_dir, '场景映射.json')
        if os.path.exists(scene_config_path):
            with open(scene_config_path, 'r', encoding='utf-8') as f:
                _json_configs['scene_mapping'] = json.load(f)
        
        # 加载知识分类
        knowledge_taxonomy_path = os.path.join(_config_data_dir, 'knowledge_taxonomy.json')
        if knowledge_taxonomy_path and os.path.exists(knowledge_taxonomy_path):
            with open(knowledge_taxonomy_path, 'r', encoding='utf-8') as f:
                _json_configs['knowledge_taxonomy'] = json.load(f)
    except Exception as e:
        logger.warning(f"加载 JSON 配置失败: {str(e)}")

# 初始化时加载 JSON 配置
_load_json_configs()

def get_config(key: str, default: Any = None, source: Optional[str] = None) -> Any:
    """统一配置获取接口（整合 ConfigManager 功能）
    
    Args:
        key: 配置键
        default: 默认值
        source: 指定配置源 ('env', 'db', 'json', None=自动)
    
    Returns:
        配置值
    """
    # 如果指定了源，只从该源获取
    if source == 'env':
        return os.getenv(key, default)
    elif source == 'db':
        try:
            config = DBSystemConfig.get_config(key)
            return config if config is not None else default
        except Exception as e:
            logger.debug(f"从数据库获取配置失败 {key}: {str(e)}")
            return default
    elif source == 'json':
        key_mapping = {
            'scene_config': 'scene_mapping',
            'knowledge_taxonomy': 'knowledge_taxonomy',
        }
        json_key = key_mapping.get(key, key)
        return _json_configs.get(json_key, default)
    
    # 自动从多个源获取（优先级：环境变量 > 数据库 > JSON > 默认值）
    env_value = os.getenv(key)
    if env_value is not None:
        # 解析环境变量值
        if env_value.lower() == 'true':
            return True
        elif env_value.lower() == 'false':
            return False
        elif env_value.isdigit():
            return int(env_value)
        try:
            return float(env_value)
        except ValueError:
            return env_value
    
    # 从数据库获取
    try:
        db_value = DBSystemConfig.get_config(key)
        if db_value is not None:
            return db_value
    except Exception:
        pass
    
    # 从 JSON 文件获取
    key_mapping = {
        'scene_config': 'scene_mapping',
        'knowledge_taxonomy': 'knowledge_taxonomy',
    }
    json_key = key_mapping.get(key, key)
    if json_key in _json_configs:
        return _json_configs[json_key]
    
    # 返回默认值
    return default

def get_scene_config() -> Dict:
    """获取场景配置"""
    return get_config('scene_config', {}, source='json') or _json_configs.get('scene_mapping', {})

def get_knowledge_taxonomy() -> Dict:
    """获取知识分类配置"""
    return get_config('knowledge_taxonomy', {}, source='json') or _json_configs.get('knowledge_taxonomy', {})

class Config:
    """项目配置类（兼容层）
    
    保持向后兼容，内部使用 SystemConfig
    """
    # 基础配置（从 SystemConfig 读取）
    SECRET_KEY = _system_config.app.secret_key
    SESSION_TYPE = _system_config.session.type

    # 时区配置
    TIMEZONE = timezone(timedelta(hours=8))  # 北京时间 UTC+8
    TIMEZONE_NAME = 'Asia/Shanghai'

    # 路径配置（从 SystemConfig 读取）
    BASE_DIR = _system_config.base_dir
    CONFIG_DIR = os.path.join(BASE_DIR, 'config')
    CONFIG_DATA_DIR = os.path.join(CONFIG_DIR, 'data')

    # 数据库配置（从 SystemConfig 读取）
    DATABASE_TYPE = _system_config.database.type
    
    if DATABASE_TYPE == 'postgresql':
        POSTGRES_HOST = _system_config.database.host
        POSTGRES_PORT = _system_config.database.port
        POSTGRES_DB = _system_config.database.database
        POSTGRES_USER = _system_config.database.user
        POSTGRES_PASSWORD = _system_config.database.password
        SQLALCHEMY_DATABASE_URI = _system_config.database.get_database_uri(BASE_DIR)
        print(SQLALCHEMY_DATABASE_URI)
    else:
        print("使用 SQLite 数据库")
        INSTANCE_PATH = _system_config.database.instance_path or os.path.join(BASE_DIR, 'instance')
        os.makedirs(INSTANCE_PATH, exist_ok=True)
        SQLITE_DB_NAME = _system_config.database.sqlite_db_name
        DB_PATH = os.path.join(INSTANCE_PATH, SQLITE_DB_NAME)
        SQLALCHEMY_DATABASE_URI = _system_config.database.get_database_uri(BASE_DIR)

    SQLALCHEMY_TRACK_MODIFICATIONS = False

    # SQLAlchemy 引擎配置 - 强制使用 UTF-8 编码
    SQLALCHEMY_ENGINE_OPTIONS = {
        'connect_args': {
            'client_encoding': 'utf8'
        } if DATABASE_TYPE == 'postgresql' else {},
        'pool_pre_ping': True,
        'pool_recycle': 3600,
    }

    # 会话配置（从 SystemConfig 读取）
    SESSION_FILE_DIR = _system_config.session.file_dir or os.path.join(BASE_DIR, 'flask_session')
    PERMANENT_SESSION_LIFETIME = _system_config.session.permanent_lifetime