"""
设置模块 - 系统配置
提供轻量级的路由入口，业务逻辑在 SettingsService 中实现
"""
from fastapi import APIRouter, HTTPException, Request, Body
from pydantic import BaseModel, Field
from typing import Dict, Any, Optional
import logging
import traceback

from jettask.schemas import SystemSettingsResponse, DatabaseStatusResponse
from jettask.webui.services.settings_service import SettingsService
from jettask.config import SYSTEM_CONFIG_DEFAULTS

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/settings", tags=["设置"])



class DynamicConfigResponse(BaseModel):
    """动态配置响应"""
    success: bool = True
    data: Dict[str, Any]


class UpdateConfigRequest(BaseModel):
    """更新配置请求"""
    value: Any = Field(..., description="配置值")
    description: Optional[str] = Field(None, description="配置描述")



@router.get(
    "/system",
    summary="获取系统配置信息",
    description="获取系统级别的配置信息，包括 API 版本、服务名称、运行环境、数据库状态等",
    response_model=SystemSettingsResponse,
    responses={
        200: {
            "description": "成功返回系统配置信息"
        },
        500: {
            "description": "服务器内部错误",
            "content": {
                "application/json": {
                    "example": {
                        "detail": "获取系统配置失败: Configuration error"
                    }
                }
            }
        }
    }
)
async def get_system_settings() -> Dict[str, Any]:
    try:
        return SettingsService.get_system_settings()
    except Exception as e:
        logger.error(f"获取系统配置失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.get(
    "/database-status",
    summary="检查数据库连接状态",
    description="检查数据库（PostgreSQL/MySQL）的连接状态和性能指标",
    response_model=DatabaseStatusResponse,
    responses={
        200: {
            "description": "成功返回数据库状态"
        },
        500: {
            "description": "服务器内部错误或数据库连接失败",
            "content": {
                "application/json": {
                    "example": {
                        "detail": "数据库状态检查失败: Connection refused"
                    }
                }
            }
        }
    }
)
async def check_database_status() -> Dict[str, Any]:
    try:
        return await SettingsService.check_database_status()
    except Exception as e:
        logger.error(f"数据库状态检查失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))




async def _get_namespace_manager(request: Request):
    if not hasattr(request.app.state, 'namespace_manager'):
        raise HTTPException(
            status_code=500,
            detail="NamespaceManager 未初始化"
        )
    return request.app.state.namespace_manager


async def _get_system_configs_from_redis(request: Request) -> Dict[str, Any]:
    from jettask.config import DynamicConfig
    import json

    namespace_manager = await _get_namespace_manager(request)
    namespaces = await namespace_manager.list_namespaces(enabled_only=True)

    if not namespaces:
        return {}

    ns = namespaces[0]
    redis_client = await ns.get_redis_client()
    prefix = ns.redis_prefix

    config_key = DynamicConfig.get_system_config_key(prefix)
    data = await redis_client.hgetall(config_key)

    configs = {}
    for k, v in data.items():
        k = k.decode() if isinstance(k, bytes) else k
        v = v.decode() if isinstance(v, bytes) else v
        try:
            configs[k] = json.loads(v)
        except (json.JSONDecodeError, TypeError):
            configs[k] = v

    return configs


@router.get(
    "/configs",
    summary="获取所有动态配置",
    description="获取所有系统级动态配置，包括 DDSketch 精度、指标保留天数等",
    response_model=DynamicConfigResponse,
)
async def get_all_configs(request: Request) -> Dict[str, Any]:
    try:
        configs = dict(SYSTEM_CONFIG_DEFAULTS)
        redis_configs = await _get_system_configs_from_redis(request)
        configs.update(redis_configs)

        return {"success": True, "data": configs}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取动态配置失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.get(
    "/configs/{key}",
    summary="获取单个动态配置",
    description="获取指定键的动态配置值",
    response_model=DynamicConfigResponse,
)
async def get_config(request: Request, key: str) -> Dict[str, Any]:
    try:
        redis_configs = await _get_system_configs_from_redis(request)
        value = redis_configs.get(key) or SYSTEM_CONFIG_DEFAULTS.get(key)

        if value is None:
            raise HTTPException(status_code=404, detail=f"配置 '{key}' 不存在")

        return {"success": True, "data": {key: value}}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取配置 {key} 失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.put(
    "/configs/{key}",
    summary="更新动态配置",
    description="更新指定键的动态配置值",
    response_model=DynamicConfigResponse,
)
async def update_config(
    request: Request,
    key: str,
    body: UpdateConfigRequest
) -> Dict[str, Any]:
    from jettask.config import DynamicConfig
    from jettask.webui.services.config_service import ConfigService

    try:
        if key not in SYSTEM_CONFIG_DEFAULTS:
            raise HTTPException(
                status_code=400,
                detail=f"无效的配置键 '{key}'，有效的配置键: {list(SYSTEM_CONFIG_DEFAULTS.keys())}"
            )

        namespace_manager = await _get_namespace_manager(request)
        namespaces = await namespace_manager.list_namespaces(enabled_only=True)

        for ns in namespaces:
            try:
                redis_client = await ns.get_redis_client()
                prefix = ns.redis_prefix
                await DynamicConfig.set_system_config_to_redis(
                    redis_client, prefix, key, body.value
                )
                logger.debug(f"系统配置 {key} 已同步到命名空间 {ns.name}")
            except Exception as e:
                logger.error(f"同步系统配置到命名空间 {ns.name} 失败: {e}")

        meta_db_session_factory = request.app.state.meta_db_session_factory
        async with meta_db_session_factory() as pg_session:
            await ConfigService.save_system_config_to_pg(
                pg_session, key, body.value, body.description
            )

        return {
            "success": True,
            "data": {key: body.value},
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新配置 {key} 失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.get(
    "/configs-schema",
    summary="获取配置项定义",
    description="获取所有可配置项的定义，包括类型、默认值、说明",
)
async def get_configs_schema() -> Dict[str, Any]:
    schema = {
        "ddsketch_relative_accuracy": {
            "type": "float",
            "default": 0.05,
            "min": 0.01,
            "max": 0.1,
            "description": "DDSketch 相对误差（用于分位数计算），值越小精度越高但存储越大"
        },
        "metrics_retention_days": {
            "type": "int",
            "default": 30,
            "min": 1,
            "max": 365,
            "description": "指标数据保留天数"
        },
        "log_level": {
            "type": "string",
            "default": "INFO",
            "options": ["DEBUG", "INFO", "WARNING", "ERROR"],
            "description": "日志级别"
        }
    }
    return {"success": True, "data": schema}


__all__ = ['router']