#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations

import database
from app_logger import get_logger
from app_security import is_safe_outbound_url, validate_email
from flask import jsonify, request
from routes.admin_api import admin_api_bp
from routes.decorators import admin_required
from services.browse_types import BROWSE_TYPE_SHOULD_READ, validate_browse_type
from services.tasks import get_task_scheduler

logger = get_logger("app")


@admin_api_bp.route("/system/config", methods=["GET"])
@admin_required
def get_system_config_api():
    """获取系统配置"""
    return jsonify(database.get_system_config())


@admin_api_bp.route("/system/config", methods=["POST"])
@admin_required
def update_system_config_api():
    """更新系统配置"""
    data = request.json or {}

    max_concurrent = data.get("max_concurrent_global")
    schedule_enabled = data.get("schedule_enabled")
    schedule_time = data.get("schedule_time")
    schedule_browse_type = data.get("schedule_browse_type")
    schedule_weekdays = data.get("schedule_weekdays")
    new_max_concurrent_per_account = data.get("max_concurrent_per_account")
    new_max_screenshot_concurrent = data.get("max_screenshot_concurrent")
    db_slow_query_ms = data.get("db_slow_query_ms")
    enable_screenshot = data.get("enable_screenshot")
    auto_approve_enabled = data.get("auto_approve_enabled")
    auto_approve_hourly_limit = data.get("auto_approve_hourly_limit")
    auto_approve_vip_days = data.get("auto_approve_vip_days")
    kdocs_enabled = data.get("kdocs_enabled")
    kdocs_doc_url = data.get("kdocs_doc_url")
    kdocs_default_unit = data.get("kdocs_default_unit")
    kdocs_sheet_name = data.get("kdocs_sheet_name")
    kdocs_sheet_index = data.get("kdocs_sheet_index")
    kdocs_unit_column = data.get("kdocs_unit_column")
    kdocs_image_column = data.get("kdocs_image_column")
    kdocs_admin_notify_enabled = data.get("kdocs_admin_notify_enabled")
    kdocs_admin_notify_email = data.get("kdocs_admin_notify_email")
    kdocs_row_start = data.get("kdocs_row_start")
    kdocs_row_end = data.get("kdocs_row_end")

    if max_concurrent is not None:
        if not isinstance(max_concurrent, int) or max_concurrent < 1:
            return jsonify({"error": "全局并发数必须大于0（建议：小型服务器2-5，中型5-10，大型10-20）"}), 400

    if new_max_concurrent_per_account is not None:
        if not isinstance(new_max_concurrent_per_account, int) or new_max_concurrent_per_account < 1:
            return jsonify({"error": "单账号并发数必须大于0（建议设为1，避免同一用户任务相互影响）"}), 400

    if new_max_screenshot_concurrent is not None:
        if not isinstance(new_max_screenshot_concurrent, int) or new_max_screenshot_concurrent < 1:
            return jsonify({"error": "截图并发数必须大于0（建议根据服务器配置设置，wkhtmltoimage 资源占用较低）"}), 400

    if db_slow_query_ms is not None:
        try:
            db_slow_query_ms = int(db_slow_query_ms)
        except (ValueError, TypeError):
            return jsonify({"error": "慢 SQL 阈值必须是数字（毫秒）"}), 400
        if db_slow_query_ms < 0 or db_slow_query_ms > 60000:
            return jsonify({"error": "慢 SQL 阈值范围应在 0-60000 毫秒之间"}), 400

    if enable_screenshot is not None:
        if isinstance(enable_screenshot, bool):
            enable_screenshot = 1 if enable_screenshot else 0
        if enable_screenshot not in (0, 1):
            return jsonify({"error": "截图开关必须是0或1"}), 400

    if schedule_time is not None:
        import re

        if not re.match(r"^([01]\d|2[0-3]):([0-5]\d)$", schedule_time):
            return jsonify({"error": "时间格式错误，应为 HH:MM"}), 400

    if schedule_browse_type is not None:
        normalized = validate_browse_type(schedule_browse_type, default=BROWSE_TYPE_SHOULD_READ)
        if not normalized:
            return jsonify({"error": "浏览类型无效"}), 400
        schedule_browse_type = normalized

    if schedule_weekdays is not None:
        try:
            days = [int(d.strip()) for d in schedule_weekdays.split(",") if d.strip()]
            if not all(1 <= d <= 7 for d in days):
                return jsonify({"error": "星期数字必须在1-7之间"}), 400
        except (ValueError, AttributeError):
            return jsonify({"error": "星期格式错误"}), 400

    if auto_approve_hourly_limit is not None:
        if not isinstance(auto_approve_hourly_limit, int) or auto_approve_hourly_limit < 1:
            return jsonify({"error": "每小时注册限制必须大于0"}), 400

    if auto_approve_vip_days is not None:
        if not isinstance(auto_approve_vip_days, int) or auto_approve_vip_days < 0:
            return jsonify({"error": "注册赠送VIP天数不能为负数"}), 400

    if kdocs_enabled is not None:
        if isinstance(kdocs_enabled, bool):
            kdocs_enabled = 1 if kdocs_enabled else 0
        if kdocs_enabled not in (0, 1):
            return jsonify({"error": "表格上传开关必须是0或1"}), 400

    if kdocs_doc_url is not None:
        kdocs_doc_url = str(kdocs_doc_url or "").strip()
        if kdocs_doc_url and not is_safe_outbound_url(kdocs_doc_url):
            return jsonify({"error": "文档链接格式不正确"}), 400

    if kdocs_default_unit is not None:
        kdocs_default_unit = str(kdocs_default_unit or "").strip()
        if len(kdocs_default_unit) > 50:
            return jsonify({"error": "默认县区长度不能超过50"}), 400

    if kdocs_sheet_name is not None:
        kdocs_sheet_name = str(kdocs_sheet_name or "").strip()
        if len(kdocs_sheet_name) > 50:
            return jsonify({"error": "Sheet名称长度不能超过50"}), 400

    if kdocs_sheet_index is not None:
        try:
            kdocs_sheet_index = int(kdocs_sheet_index)
        except Exception:
            return jsonify({"error": "Sheet序号必须是数字"}), 400
        if kdocs_sheet_index < 0:
            return jsonify({"error": "Sheet序号不能为负数"}), 400

    if kdocs_unit_column is not None:
        kdocs_unit_column = str(kdocs_unit_column or "").strip().upper()
        if not kdocs_unit_column:
            return jsonify({"error": "县区列不能为空"}), 400
        import re

        if not re.match(r"^[A-Z]{1,3}$", kdocs_unit_column):
            return jsonify({"error": "县区列格式错误"}), 400

    if kdocs_image_column is not None:
        kdocs_image_column = str(kdocs_image_column or "").strip().upper()
        if not kdocs_image_column:
            return jsonify({"error": "图片列不能为空"}), 400
        import re

        if not re.match(r"^[A-Z]{1,3}$", kdocs_image_column):
            return jsonify({"error": "图片列格式错误"}), 400

    if kdocs_admin_notify_enabled is not None:
        if isinstance(kdocs_admin_notify_enabled, bool):
            kdocs_admin_notify_enabled = 1 if kdocs_admin_notify_enabled else 0
        if kdocs_admin_notify_enabled not in (0, 1):
            return jsonify({"error": "管理员通知开关必须是0或1"}), 400

    if kdocs_admin_notify_email is not None:
        kdocs_admin_notify_email = str(kdocs_admin_notify_email or "").strip()
        if kdocs_admin_notify_email:
            is_valid, error_msg = validate_email(kdocs_admin_notify_email)
            if not is_valid:
                return jsonify({"error": error_msg}), 400

    if kdocs_row_start is not None:
        try:
            kdocs_row_start = int(kdocs_row_start)
        except (ValueError, TypeError):
            return jsonify({"error": "起始行必须是数字"}), 400
        if kdocs_row_start < 0:
            return jsonify({"error": "起始行不能为负数"}), 400

    if kdocs_row_end is not None:
        try:
            kdocs_row_end = int(kdocs_row_end)
        except (ValueError, TypeError):
            return jsonify({"error": "结束行必须是数字"}), 400
        if kdocs_row_end < 0:
            return jsonify({"error": "结束行不能为负数"}), 400

    old_config = database.get_system_config() or {}

    if not database.update_system_config(
        max_concurrent=max_concurrent,
        schedule_enabled=schedule_enabled,
        schedule_time=schedule_time,
        schedule_browse_type=schedule_browse_type,
        schedule_weekdays=schedule_weekdays,
        max_concurrent_per_account=new_max_concurrent_per_account,
        max_screenshot_concurrent=new_max_screenshot_concurrent,
        enable_screenshot=enable_screenshot,
        auto_approve_enabled=auto_approve_enabled,
        auto_approve_hourly_limit=auto_approve_hourly_limit,
        auto_approve_vip_days=auto_approve_vip_days,
        kdocs_enabled=kdocs_enabled,
        kdocs_doc_url=kdocs_doc_url,
        kdocs_default_unit=kdocs_default_unit,
        kdocs_sheet_name=kdocs_sheet_name,
        kdocs_sheet_index=kdocs_sheet_index,
        kdocs_unit_column=kdocs_unit_column,
        kdocs_image_column=kdocs_image_column,
        kdocs_admin_notify_enabled=kdocs_admin_notify_enabled,
        kdocs_admin_notify_email=kdocs_admin_notify_email,
        kdocs_row_start=kdocs_row_start,
        kdocs_row_end=kdocs_row_end,
        db_slow_query_ms=db_slow_query_ms,
    ):
        return jsonify({"error": "更新失败"}), 400

    try:
        new_config = database.get_system_config() or {}
        scheduler = get_task_scheduler()
        scheduler.update_limits(
            max_global=int(new_config.get("max_concurrent_global", old_config.get("max_concurrent_global", 2))),
            max_per_user=int(new_config.get("max_concurrent_per_account", old_config.get("max_concurrent_per_account", 1))),
        )

        try:
            import db_pool

            db_pool.configure_slow_query_runtime(threshold_ms=new_config.get("db_slow_query_ms"))
        except Exception as slow_sql_error:
            logger.warning(f"慢 SQL 运行时阈值更新失败: {slow_sql_error}")

        if new_max_screenshot_concurrent is not None:
            try:
                from browser_pool_worker import resize_browser_worker_pool

                if resize_browser_worker_pool(int(new_config.get("max_screenshot_concurrent", new_max_screenshot_concurrent))):
                    logger.info(f"截图线程池并发已更新为: {new_config.get('max_screenshot_concurrent')}")
            except Exception as pool_error:
                logger.warning(f"截图线程池并发更新失败: {pool_error}")
    except Exception:
        pass

    if max_concurrent is not None and max_concurrent != old_config.get("max_concurrent_global"):
        logger.info(f"全局并发数已更新为: {max_concurrent}")
    if new_max_concurrent_per_account is not None and new_max_concurrent_per_account != old_config.get("max_concurrent_per_account"):
        logger.info(f"单用户并发数已更新为: {new_max_concurrent_per_account}")
    if new_max_screenshot_concurrent is not None:
        logger.info(f"截图并发数已更新为: {new_max_screenshot_concurrent}")
    if db_slow_query_ms is not None:
        logger.info(f"慢 SQL 阈值已更新为: {db_slow_query_ms}ms")

    return jsonify({"message": "系统配置已更新"})
