"""
配置管理 API
"""

import os
import json
from typing import Optional, List, Dict

import pymysql
from fastapi import APIRouter, Depends, HTTPException, status, Query

from .auth import get_current_admin, get_db_connection, AdminUserInfo
from .schemas import (
    ConfigTemplateResponse,
    TenantConfigResponse,
    TenantConfigCreate,
    TenantConfigUpdate,
    TenantConfigGroupResponse,
    ConfigBatchUpdate,
    ResponseModel,
)

router = APIRouter(prefix="/configs", tags=["配置管理"])

# 配置分组显示名称
CONFIG_GROUP_NAMES = {
    "database": "数据库配置",
    "redis": "Redis配置",
    "security": "安全配置",
    "coze": "Coze配置",
    "ai": "AI服务配置",
    "yanji": "言迹工牌配置",
    "storage": "文件存储配置",
    "basic": "基础配置",
}


def log_operation(cursor, admin: AdminUserInfo, tenant_id: int, tenant_code: str,
                  operation_type: str, resource_type: str, resource_id: int,
                  resource_name: str, old_value: dict = None, new_value: dict = None):
    """记录操作日志"""
    cursor.execute(
        """
        INSERT INTO operation_logs 
        (admin_user_id, admin_username, tenant_id, tenant_code, operation_type, 
         resource_type, resource_id, resource_name, old_value, new_value)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        """,
        (admin.id, admin.username, tenant_id, tenant_code, operation_type,
         resource_type, resource_id, resource_name,
         json.dumps(old_value, ensure_ascii=False) if old_value else None,
         json.dumps(new_value, ensure_ascii=False) if new_value else None)
    )


@router.get("/templates", response_model=List[ConfigTemplateResponse], summary="获取配置模板")
async def get_config_templates(
    config_group: Optional[str] = Query(None, description="配置分组筛选"),
    admin: AdminUserInfo = Depends(get_current_admin),
):
    """
    获取配置模板列表
    
    配置模板定义了所有可配置项的元数据
    """
    conn = get_db_connection()
    try:
        with conn.cursor() as cursor:
            if config_group:
                cursor.execute(
                    """
                    SELECT * FROM config_templates 
                    WHERE config_group = %s 
                    ORDER BY sort_order, id
                    """,
                    (config_group,)
                )
            else:
                cursor.execute(
                    "SELECT * FROM config_templates ORDER BY config_group, sort_order, id"
                )
            
            rows = cursor.fetchall()
            
            result = []
            for row in rows:
                # 解析 options 字段
                options = None
                if row.get("options"):
                    try:
                        options = json.loads(row["options"])
                    except:
                        pass
                
                result.append(ConfigTemplateResponse(
                    id=row["id"],
                    config_group=row["config_group"],
                    config_key=row["config_key"],
                    display_name=row["display_name"],
                    description=row["description"],
                    value_type=row["value_type"],
                    default_value=row["default_value"],
                    is_required=row["is_required"],
                    is_secret=row["is_secret"],
                    options=options,
                    sort_order=row["sort_order"],
                ))
            
            return result
    finally:
        conn.close()


@router.get("/groups", response_model=List[Dict], summary="获取配置分组列表")
async def get_config_groups(admin: AdminUserInfo = Depends(get_current_admin)):
    """获取配置分组列表"""
    conn = get_db_connection()
    try:
        with conn.cursor() as cursor:
            cursor.execute(
                """
                SELECT config_group, COUNT(*) as count 
                FROM config_templates 
                GROUP BY config_group 
                ORDER BY config_group
                """
            )
            rows = cursor.fetchall()
            
            return [
                {
                    "group_name": row["config_group"],
                    "group_display_name": CONFIG_GROUP_NAMES.get(row["config_group"], row["config_group"]),
                    "config_count": row["count"],
                }
                for row in rows
            ]
    finally:
        conn.close()


@router.get("/tenants/{tenant_id}", response_model=List[TenantConfigGroupResponse], summary="获取租户配置")
async def get_tenant_configs(
    tenant_id: int,
    config_group: Optional[str] = Query(None, description="配置分组筛选"),
    admin: AdminUserInfo = Depends(get_current_admin),
):
    """
    获取租户的所有配置
    
    返回按分组整理的配置列表，包含模板信息
    """
    conn = get_db_connection()
    try:
        with conn.cursor() as cursor:
            # 验证租户存在
            cursor.execute("SELECT code FROM tenants WHERE id = %s", (tenant_id,))
            tenant = cursor.fetchone()
            if not tenant:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="租户不存在",
                )
            
            # 查询配置模板和租户配置
            group_filter = "AND ct.config_group = %s" if config_group else ""
            params = [tenant_id, config_group] if config_group else [tenant_id]
            
            cursor.execute(
                f"""
                SELECT 
                    ct.config_group,
                    ct.config_key,
                    ct.display_name,
                    ct.description,
                    ct.value_type,
                    ct.default_value,
                    ct.is_required,
                    ct.is_secret,
                    ct.sort_order,
                    tc.id as config_id,
                    tc.config_value,
                    tc.is_encrypted,
                    tc.created_at,
                    tc.updated_at
                FROM config_templates ct
                LEFT JOIN tenant_configs tc 
                    ON tc.config_group = ct.config_group 
                    AND tc.config_key = ct.config_key 
                    AND tc.tenant_id = %s
                WHERE 1=1 {group_filter}
                ORDER BY ct.config_group, ct.sort_order, ct.id
                """,
                params
            )
            rows = cursor.fetchall()
            
            # 按分组整理
            groups: Dict[str, List] = {}
            for row in rows:
                group = row["config_group"]
                if group not in groups:
                    groups[group] = []
                
                # 如果是敏感信息且有值，隐藏部分内容
                config_value = row["config_value"]
                if row["is_secret"] and config_value:
                    if len(config_value) > 8:
                        config_value = config_value[:4] + "****" + config_value[-4:]
                    else:
                        config_value = "****"
                
                groups[group].append(TenantConfigResponse(
                    id=row["config_id"] or 0,
                    config_group=row["config_group"],
                    config_key=row["config_key"],
                    config_value=config_value if not row["is_secret"] else row["config_value"],
                    value_type=row["value_type"],
                    is_encrypted=row["is_encrypted"] or False,
                    description=row["description"],
                    created_at=row["created_at"] or None,
                    updated_at=row["updated_at"] or None,
                    display_name=row["display_name"],
                    is_required=row["is_required"],
                    is_secret=row["is_secret"],
                ))
            
            return [
                TenantConfigGroupResponse(
                    group_name=group,
                    group_display_name=CONFIG_GROUP_NAMES.get(group, group),
                    configs=configs,
                )
                for group, configs in groups.items()
            ]
    finally:
        conn.close()


@router.put("/tenants/{tenant_id}/{config_group}/{config_key}", response_model=ResponseModel, summary="更新单个配置")
async def update_tenant_config(
    tenant_id: int,
    config_group: str,
    config_key: str,
    data: TenantConfigUpdate,
    admin: AdminUserInfo = Depends(get_current_admin),
):
    """更新租户的单个配置项"""
    conn = get_db_connection()
    try:
        with conn.cursor() as cursor:
            # 验证租户存在
            cursor.execute("SELECT code FROM tenants WHERE id = %s", (tenant_id,))
            tenant = cursor.fetchone()
            if not tenant:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="租户不存在",
                )
            
            # 验证配置模板存在
            cursor.execute(
                """
                SELECT value_type, is_secret FROM config_templates 
                WHERE config_group = %s AND config_key = %s
                """,
                (config_group, config_key)
            )
            template = cursor.fetchone()
            if not template:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="无效的配置项",
                )
            
            # 检查是否已有配置
            cursor.execute(
                """
                SELECT id, config_value FROM tenant_configs 
                WHERE tenant_id = %s AND config_group = %s AND config_key = %s
                """,
                (tenant_id, config_group, config_key)
            )
            existing = cursor.fetchone()
            
            if existing:
                # 更新
                old_value = existing["config_value"]
                cursor.execute(
                    """
                    UPDATE tenant_configs 
                    SET config_value = %s, is_encrypted = %s 
                    WHERE id = %s
                    """,
                    (data.config_value, template["is_secret"], existing["id"])
                )
            else:
                # 插入
                old_value = None
                cursor.execute(
                    """
                    INSERT INTO tenant_configs 
                    (tenant_id, config_group, config_key, config_value, value_type, is_encrypted)
                    VALUES (%s, %s, %s, %s, %s, %s)
                    """,
                    (tenant_id, config_group, config_key, data.config_value,
                     template["value_type"], template["is_secret"])
                )
            
            # 记录操作日志
            log_operation(
                cursor, admin, tenant_id, tenant["code"],
                "update", "config", tenant_id, f"{config_group}.{config_key}",
                old_value={"value": old_value} if old_value else None,
                new_value={"value": data.config_value}
            )
            
            conn.commit()
            
            return ResponseModel(message="配置已更新")
    finally:
        conn.close()


@router.put("/tenants/{tenant_id}/batch", response_model=ResponseModel, summary="批量更新配置")
async def batch_update_tenant_configs(
    tenant_id: int,
    data: ConfigBatchUpdate,
    admin: AdminUserInfo = Depends(get_current_admin),
):
    """批量更新租户配置"""
    conn = get_db_connection()
    try:
        with conn.cursor() as cursor:
            # 验证租户存在
            cursor.execute("SELECT code FROM tenants WHERE id = %s", (tenant_id,))
            tenant = cursor.fetchone()
            if not tenant:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="租户不存在",
                )
            
            updated_count = 0
            for config in data.configs:
                # 获取模板信息
                cursor.execute(
                    """
                    SELECT value_type, is_secret FROM config_templates 
                    WHERE config_group = %s AND config_key = %s
                    """,
                    (config.config_group, config.config_key)
                )
                template = cursor.fetchone()
                if not template:
                    continue
                
                # 检查是否已有配置
                cursor.execute(
                    """
                    SELECT id FROM tenant_configs 
                    WHERE tenant_id = %s AND config_group = %s AND config_key = %s
                    """,
                    (tenant_id, config.config_group, config.config_key)
                )
                existing = cursor.fetchone()
                
                if existing:
                    cursor.execute(
                        """
                        UPDATE tenant_configs 
                        SET config_value = %s, is_encrypted = %s 
                        WHERE id = %s
                        """,
                        (config.config_value, template["is_secret"], existing["id"])
                    )
                else:
                    cursor.execute(
                        """
                        INSERT INTO tenant_configs 
                        (tenant_id, config_group, config_key, config_value, value_type, is_encrypted)
                        VALUES (%s, %s, %s, %s, %s, %s)
                        """,
                        (tenant_id, config.config_group, config.config_key, config.config_value,
                         template["value_type"], template["is_secret"])
                    )
                
                updated_count += 1
            
            # 记录操作日志
            log_operation(
                cursor, admin, tenant_id, tenant["code"],
                "batch_update", "config", tenant_id, f"批量更新 {updated_count} 项配置"
            )
            
            conn.commit()
            
            return ResponseModel(message=f"已更新 {updated_count} 项配置")
    finally:
        conn.close()


@router.delete("/tenants/{tenant_id}/{config_group}/{config_key}", response_model=ResponseModel, summary="删除配置")
async def delete_tenant_config(
    tenant_id: int,
    config_group: str,
    config_key: str,
    admin: AdminUserInfo = Depends(get_current_admin),
):
    """删除租户的配置项（恢复为默认值）"""
    conn = get_db_connection()
    try:
        with conn.cursor() as cursor:
            # 验证租户存在
            cursor.execute("SELECT code FROM tenants WHERE id = %s", (tenant_id,))
            tenant = cursor.fetchone()
            if not tenant:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="租户不存在",
                )
            
            # 删除配置
            cursor.execute(
                """
                DELETE FROM tenant_configs 
                WHERE tenant_id = %s AND config_group = %s AND config_key = %s
                """,
                (tenant_id, config_group, config_key)
            )
            
            if cursor.rowcount == 0:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="配置不存在",
                )
            
            # 记录操作日志
            log_operation(
                cursor, admin, tenant_id, tenant["code"],
                "delete", "config", tenant_id, f"{config_group}.{config_key}"
            )
            
            conn.commit()
            
            return ResponseModel(message="配置已删除，将使用默认值")
    finally:
        conn.close()


@router.post("/tenants/{tenant_id}/refresh-cache", response_model=ResponseModel, summary="刷新配置缓存")
async def refresh_tenant_config_cache(
    tenant_id: int,
    admin: AdminUserInfo = Depends(get_current_admin),
):
    """刷新租户的配置缓存"""
    conn = get_db_connection()
    try:
        with conn.cursor() as cursor:
            # 获取租户编码
            cursor.execute("SELECT code FROM tenants WHERE id = %s", (tenant_id,))
            tenant = cursor.fetchone()
            if not tenant:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="租户不存在",
                )
            
            # 刷新缓存
            try:
                from app.core.config import DynamicConfig
                import asyncio
                asyncio.create_task(DynamicConfig.refresh_cache(tenant["code"]))
            except Exception as e:
                pass  # 缓存刷新失败不影响主流程
            
            return ResponseModel(message="缓存刷新请求已发送")
    finally:
        conn.close()

