from fastapi import APIRouter, Depends, Query, Request
from fastapi.responses import StreamingResponse
from ...core.database import get_db, get_system_db, _has_split_databases
from ...core.permission import get_current_user, is_admin_role
from ...core.cache import invalidate_feature_flag_cache
import json
import io
from ...utils.request_utils import safe_json

router = APIRouter()


async def _system_db():
    """Dependency: system.db when split databases exist, otherwise fallback to get_db()"""
    _db_gen = get_system_db() if _has_split_databases() else get_db()
    async for conn, cur in _db_gen:
        yield conn, cur


def _flag_to_dict(row: dict) -> dict:
    result = dict(row)
    flag_type = result.get("flag_type", "boolean")
    if flag_type == "boolean":
        result["value"] = "true" if result.get("value_boolean") else "false"
    elif flag_type == "percentage":
        result["value"] = str(result.get("value_percentage", 0))
    elif flag_type == "multivariate":
        result["value"] = json.dumps(result.get("value_json", {}), ensure_ascii=False)
    else:
        result["value"] = "false"
    result["key"] = result.get("flag_key", "")
    result["type"] = flag_type
    result["scope"] = result.get("target_edition", "global")
    # 灰度发布相关字段
    result["rollout_type"] = result.get("rollout_type", "all")
    result["rollout_percentage"] = result.get("rollout_percentage", 100)
    result["whitelist_users"] = json.loads(result.get("whitelist_users", "[]")) if isinstance(result.get("whitelist_users"), str) else result.get("whitelist_users", [])
    result["blacklist_users"] = json.loads(result.get("blacklist_users", "[]")) if isinstance(result.get("blacklist_users"), str) else result.get("blacklist_users", [])
    result["version_binding"] = result.get("version_binding", "")
    return result


@router.get("")
async def list_feature_flags(
    request: Request,
    page: int = Query(1, ge=1),
    pageSize: int = Query(25, ge=1, le=100),
    keyword: str = Query(""),
    type: str = Query(""),
    scope: str = Query(""),
    isEnabled: str = Query(""),
    db=Depends(_system_db),
):
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    conn, cur = db

    where = "WHERE 1=1"
    params = []

    if keyword:
        where += " AND (flag_key LIKE %s OR flag_name LIKE %s OR description LIKE %s)"
        params.extend([f"%{keyword}%", f"%{keyword}%", f"%{keyword}%"])

    if type:
        where += " AND flag_type = %s"
        params.append(type)

    if scope:
        where += " AND target_edition = %s"
        params.append(scope)

    if isEnabled is not None and isEnabled != "":
        where += " AND value_boolean = %s"
        params.append(1 if isEnabled == "true" else 0)

    await cur.execute(f"SELECT COUNT(*) as total FROM feature_flags {where}", params)
    count_row = await cur.fetchone()
    total = dict(count_row)["total"]

    offset = (page - 1) * pageSize
    await cur.execute(
        f"SELECT * FROM feature_flags {where} ORDER BY flag_key ASC LIMIT %s OFFSET %s",
        params + [pageSize, offset],
    )
    rows = await cur.fetchall()
    items = [_flag_to_dict(dict(r)) for r in rows]

    return {"list": items, "total": total, "page": page, "pageSize": pageSize}


@router.post("")
async def create_feature_flag(request: Request, sys_db=Depends(_system_db), user_db=Depends(get_db)):
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    if not is_admin_role(current_user["role"]):
        return {"error": "无权限，仅管理员可创建功能开关", "detail": "admin required"}

    conn, cur = sys_db
    user_conn, user_cur = user_db
    body = await safe_json(request)
    key = body.get("key")
    value = body.get("value")
    flag_type = body.get("type", "boolean")
    description = body.get("description", "")
    target_edition = body.get("scope", body.get("target_edition"))
    flag_name = body.get("flag_name", body.get("name", key))

    if not key:
        return {"error": "key不能为空", "detail": "key required"}

    await cur.execute("SELECT id FROM feature_flags WHERE flag_key = %s", (key,))
    if await cur.fetchone():
        return {"error": "功能开关key已存在", "detail": "key already exists"}

    value_boolean = 1 if str(value).lower() == "true" else 0 if flag_type == "boolean" else None
    value_percentage = float(value) if flag_type == "percentage" and value else None
    value_json = json.loads(value) if flag_type == "multivariate" and value else None

    await cur.execute(
        """INSERT INTO feature_flags (flag_key, flag_name, description, flag_type, value_boolean, value_percentage, value_json, target_edition, created_by)
           VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)""",
        (key, flag_name, description, flag_type, value_boolean, value_percentage, value_json, target_edition, current_user.get("userId")),
    )

    client_ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or "unknown"
    try:
        await user_cur.execute(
            """INSERT INTO audit_logs (user_id, action, target_type, target_id, detail, ip_address, result)
               VALUES (%s, 'CREATE', 'feature_flag', %s, %s, %s, 'success')""",
            (current_user.get("userId"), key, f"创建功能开关 {key}: {value}", client_ip),
        )
    except Exception:
        pass

    return {"success": True, "message": "功能开关创建成功", "key": key, "value": str(value)}


@router.get("/public")
async def public_feature_flags(request: Request, db=Depends(_system_db)):
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    conn, cur = db
    await cur.execute("SELECT flag_key, flag_name, flag_type, description, value_boolean, target_edition FROM feature_flags ORDER BY flag_key ASC")
    rows = await cur.fetchall()
    items = [_flag_to_dict(dict(r)) for r in rows]

    flag_map = {}
    for row in items:
        flag_map[row["key"]] = {
            "value": row["value"],
            "type": row["type"],
            "enabled": row["value"] == "true" if row["type"] == "boolean" else True,
        }

    return {"flags": flag_map, "list": items, "total": len(items)}


@router.get("/export")
async def export_feature_flags(request: Request, db=Depends(_system_db)):
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    if not is_admin_role(current_user["role"]):
        return {"error": "无权限，仅管理员可导出", "detail": "admin required"}

    conn, cur = db
    await cur.execute("SELECT * FROM feature_flags ORDER BY flag_key ASC")
    rows = await cur.fetchall()
    items = [_flag_to_dict(dict(r)) for r in rows]

    yaml_lines = [
        f"exported_at: '{__import__('datetime').datetime.now().isoformat()}'",
        f"exported_by: {current_user.get('username', 'unknown')}",
        f"total_count: {len(items)}",
        "feature_flags:",
    ]
    for row in items:
        yaml_lines.append(f"  - key: \"{row.get('key', '')}\"")
        yaml_lines.append(f"    value: \"{row.get('value', '')}\"")
        yaml_lines.append(f"    type: \"{row.get('type', 'boolean')}\"")
        yaml_lines.append(f"    description: \"{row.get('description', '')}\"")
        yaml_lines.append(f"    scope: \"{row.get('scope', 'global')}\"")

    yaml_content = "\n".join(yaml_lines)

    return StreamingResponse(
        io.BytesIO(yaml_content.encode("utf-8")),
        media_type="application/x-yaml",
        headers={
            "Content-Disposition": f"attachment; filename=feature-flags-export-{__import__('datetime').date.today().isoformat()}.yaml",
        },
    )


@router.get("/change-log")
async def feature_flag_change_log(
    request: Request,
    page: int = Query(1, ge=1),
    pageSize: int = Query(20, ge=1, le=100),
    flagKey: str = Query(""),
    operatorName: str = Query(""),
    db=Depends(get_db),
):
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    conn, cur = db
    try:
        where = "WHERE 1=1"
        params = []

        if flagKey:
            where += " AND flag_key LIKE %s"
            params.append(f"%{flagKey}%")

        if operatorName:
            where += " AND operator_name LIKE %s"
            params.append(f"%{operatorName}%")

        await cur.execute(f"SELECT COUNT(*) as total FROM feature_flag_change_logs {where}", params)
        count_row = await cur.fetchone()
        total = dict(count_row)["total"]

        offset = (page - 1) * pageSize
        await cur.execute(
            f"SELECT * FROM feature_flag_change_logs {where} ORDER BY created_at DESC LIMIT %s OFFSET %s",
            params + [pageSize, offset],
        )
        rows = await cur.fetchall()
        items = [dict(r) for r in rows]

        return {"list": items, "total": total, "page": page, "pageSize": pageSize}
    except Exception:
        return {"list": [], "total": 0, "page": page, "pageSize": pageSize}


@router.get("/{key}")
async def get_feature_flag(key: str, request: Request, sys_db=Depends(_system_db), user_db=Depends(get_db)):
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    conn, cur = sys_db
    user_conn, user_cur = user_db
    await cur.execute("SELECT * FROM feature_flags WHERE flag_key = %s", (key,))
    row = await cur.fetchone()
    if not row:
        return {"error": "功能开关不存在", "detail": "flag not found"}

    flag = _flag_to_dict(dict(row))

    try:
        await user_cur.execute(
            "SELECT * FROM feature_flag_change_logs WHERE flag_key = %s ORDER BY created_at DESC LIMIT 10",
            (key,),
        )
        logs = await user_cur.fetchall()
        flag["recentLogs"] = [dict(r) for r in logs]
    except Exception:
        flag["recentLogs"] = []

    return flag


@router.put("/{key}")
async def update_feature_flag(key: str, request: Request, sys_db=Depends(_system_db), user_db=Depends(get_db)):
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    if not is_admin_role(current_user["role"]):
        return {"error": "无权限，仅管理员可修改功能开关", "detail": "admin required"}

    conn, cur = sys_db
    user_conn, user_cur = user_db
    body = await safe_json(request)
    value = body.get("value")
    change_reason = body.get("changeReason", "")

    if value is None:
        return {"error": "值不能为空", "detail": "value required"}

    await cur.execute("SELECT * FROM feature_flags WHERE flag_key = %s", (key,))
    row = await cur.fetchone()
    if not row:
        return {"error": "功能开关不存在", "detail": "flag not found"}

    current_flag = _flag_to_dict(dict(row))
    old_value = current_flag["value"]

    if old_value == str(value):
        return {"error": "值未发生变化", "detail": "value unchanged"}

    flag_type = current_flag.get("flag_type", "boolean")
    if flag_type == "boolean":
        await cur.execute(
            "UPDATE feature_flags SET value_boolean = %s, updated_at = CURRENT_TIMESTAMP WHERE flag_key = %s",
            (1 if str(value).lower() == "true" else 0, key),
        )
    elif flag_type == "percentage":
        await cur.execute(
            "UPDATE feature_flags SET value_percentage = %s, updated_at = CURRENT_TIMESTAMP WHERE flag_key = %s",
            (float(value), key),
        )
    elif flag_type == "multivariate":
        await cur.execute(
            "UPDATE feature_flags SET value_json = %s, updated_at = CURRENT_TIMESTAMP WHERE flag_key = %s",
            (json.loads(value) if isinstance(value, str) else value, key),
        )

    client_ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or "unknown"

    try:
        await user_cur.execute(
            """INSERT INTO feature_flag_change_logs
               (flag_key, operator_id, operator_name, old_value, new_value, change_reason, ip_address)
               VALUES (%s, %s, %s, %s, %s, %s, %s)""",
            (key, current_user.get("userId"), current_user.get("username"), old_value, str(value), change_reason, client_ip),
        )
    except Exception:
        pass

    try:
        await user_cur.execute(
            """INSERT INTO audit_logs (user_id, action, target_type, target_id, detail, ip_address, result)
               VALUES (%s, 'UPDATE', 'feature_flag', %s, %s, %s, 'success')""",
            (
                current_user.get("userId"),
                key,
                f"修改功能开关 {key}: {old_value} -> {value}" + (f", 原因: {change_reason}" if change_reason else ""),
                client_ip,
            ),
        )
    except Exception:
        pass

    await invalidate_feature_flag_cache(key)

    return {
        "success": True,
        "message": "功能开关更新成功",
        "key": key,
        "oldValue": old_value,
        "newValue": str(value),
    }


@router.post("/{key}/rollout")
async def configure_rollout(key: str, request: Request, db=Depends(_system_db)):
    """配置灰度发布"""
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    if not is_admin_role(current_user["role"]):
        return {"error": "无权限", "detail": "admin required"}

    conn, cur = db
    body = await safe_json(request)
    
    rollout_type = body.get("rollout_type", "all")
    rollout_percentage = body.get("rollout_percentage", 100)
    whitelist_users = body.get("whitelist_users", [])
    blacklist_users = body.get("blacklist_users", [])
    version_binding = body.get("version_binding", "")

    await cur.execute("SELECT id FROM feature_flags WHERE flag_key = %s", (key,))
    if not await cur.fetchone():
        return {"error": "功能开关不存在", "detail": "flag not found"}

    await cur.execute(
        """UPDATE feature_flags 
           SET rollout_type = %s, 
               rollout_percentage = %s, 
               whitelist_users = %s, 
               blacklist_users = %s, 
               version_binding = %s,
               updated_at = CURRENT_TIMESTAMP 
           WHERE flag_key = %s""",
        (rollout_type, rollout_percentage, json.dumps(whitelist_users), json.dumps(blacklist_users), version_binding, key),
    )

    await invalidate_feature_flag_cache(key)

    return {
        "success": True,
        "message": "灰度发布配置已更新",
        "key": key,
        "rollout_type": rollout_type,
        "rollout_percentage": rollout_percentage,
    }


@router.get("/{key}/rollout-status")
async def get_rollout_status(key: str, request: Request, sys_db=Depends(_system_db), user_db=Depends(get_db)):
    """获取灰度发布状态"""
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    conn, cur = sys_db
    user_conn, user_cur = user_db
    await cur.execute(
        "SELECT rollout_type, rollout_percentage, whitelist_users, blacklist_users, version_binding FROM feature_flags WHERE flag_key = %s",
        (key,),
    )
    row = await cur.fetchone()
    if not row:
        return {"error": "功能开关不存在", "detail": "flag not found"}

    flag = dict(row)
    
    # 获取用户总数（简化版）
    try:
        await user_cur.execute("SELECT COUNT(*) as total FROM users WHERE status = 1")
        total_users = dict(await user_cur.fetchone())["total"]
    except Exception:
        total_users = 0

    # 计算启用用户数
    rollout_percentage = flag.get("rollout_percentage", 100)
    enabled_users = int(total_users * rollout_percentage / 100)

    return {
        "key": key,
        "rollout_type": flag.get("rollout_type", "all"),
        "rollout_percentage": rollout_percentage,
        "total_users": total_users,
        "enabled_users": enabled_users,
        "whitelist_users": json.loads(flag.get("whitelist_users", "[]")) if isinstance(flag.get("whitelist_users"), str) else flag.get("whitelist_users", []),
        "blacklist_users": json.loads(flag.get("blacklist_users", "[]")) if isinstance(flag.get("blacklist_users"), str) else flag.get("blacklist_users", []),
        "version_binding": flag.get("version_binding", ""),
    }


@router.delete("/{key}")
async def delete_feature_flag(key: str, request: Request, sys_db=Depends(_system_db), user_db=Depends(get_db)):
    current_user = get_current_user(request)
    if not current_user:
        return {"error": "未登录", "detail": "unauthorized"}

    if not is_admin_role(current_user["role"]):
        return {"error": "无权限，仅管理员可删除功能开关", "detail": "admin required"}

    conn, cur = sys_db
    user_conn, user_cur = user_db
    await cur.execute("SELECT id FROM feature_flags WHERE flag_key = %s", (key,))
    if not await cur.fetchone():
        return {"error": "功能开关不存在", "detail": "flag not found"}

    await cur.execute("DELETE FROM feature_flags WHERE flag_key = %s", (key,))

    client_ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or "unknown"
    try:
        await user_cur.execute(
            """INSERT INTO audit_logs (user_id, action, target_type, target_id, detail, ip_address, result)
               VALUES (%s, 'DELETE', 'feature_flag', %s, %s, %s, 'success')""",
            (current_user.get("userId"), key, f"删除功能开关 {key}", client_ip),
        )
    except Exception:
        pass

    await invalidate_feature_flag_cache(key)

    return {"success": True, "message": "功能开关删除成功", "key": key}
