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

import os
import time

import database
from app_config import get_config
from app_logger import get_logger
from app_security import get_rate_limit_ip, require_ip_not_locked
from flask import current_app, jsonify, redirect, request, session, url_for
from routes.admin_api import admin_api_bp
from routes.decorators import admin_required
from services.accounts_service import load_user_accounts
from services.checkpoints import get_checkpoint_mgr
from services.state import (
    safe_get_user_accounts_snapshot,
    safe_verify_and_consume_captcha,
    check_login_ip_user_locked,
    check_login_rate_limits,
    get_login_failure_delay_seconds,
    record_login_username_attempt,
    check_ip_request_rate,
    check_login_captcha_required,
    clear_login_failures,
    record_login_failure,
)
from services.tasks import submit_account_task

logger = get_logger("app")
config = get_config()


def _admin_reauth_required() -> bool:
    try:
        return time.time() > float(session.get("admin_reauth_until", 0) or 0)
    except Exception:
        return True


def _require_admin_reauth():
    if _admin_reauth_required():
        return jsonify({"error": "需要二次确认", "code": "reauth_required"}), 401
    return None

@admin_api_bp.route("/debug-config", methods=["GET"])
@admin_required
def debug_config():
    """调试配置信息（仅管理员可访问，生产环境应禁用）"""
    if not current_app.debug:
        return jsonify({"error": "调试端点已在生产环境禁用"}), 403

    return jsonify(
        {
            "secret_key_set": bool(current_app.secret_key),
            "secret_key_length": len(current_app.secret_key) if current_app.secret_key else 0,
            "session_config": {
                "SESSION_COOKIE_NAME": current_app.config.get("SESSION_COOKIE_NAME"),
                "SESSION_COOKIE_SECURE": current_app.config.get("SESSION_COOKIE_SECURE"),
                "SESSION_COOKIE_HTTPONLY": current_app.config.get("SESSION_COOKIE_HTTPONLY"),
                "SESSION_COOKIE_SAMESITE": current_app.config.get("SESSION_COOKIE_SAMESITE"),
                "PERMANENT_SESSION_LIFETIME": str(current_app.config.get("PERMANENT_SESSION_LIFETIME")),
            },
            "has_session": bool(session),
            "cookies_received": list(request.cookies.keys()),
        }
    )


@admin_api_bp.route("/login", methods=["POST"])
@require_ip_not_locked
def admin_login():
    """管理员登录（支持JSON和form-data两种格式）"""
    if request.is_json:
        data = request.json or {}
    else:
        data = request.form

    username = data.get("username", "").strip()
    password = data.get("password", "").strip()
    captcha_session = data.get("captcha_session", "")
    captcha_code = data.get("captcha", "").strip()
    need_captcha = data.get("need_captcha", False)

    client_ip = get_rate_limit_ip()
    username_key = username

    scan_locked = record_login_username_attempt(client_ip, username_key)
    is_locked, remaining = check_login_ip_user_locked(client_ip, username_key)
    if is_locked:
        wait_hint = f"{remaining // 60 + 1}分钟" if remaining >= 60 else f"{remaining}秒"
        if request.is_json:
            return jsonify({"error": f"账号短时锁定，请{wait_hint}后再试", "need_captcha": True}), 429
        return redirect(url_for("pages.admin_login_page"))

    allowed, error_msg = check_ip_request_rate(client_ip, "login")
    if not allowed:
        if request.is_json:
            return jsonify({"error": error_msg, "need_captcha": True}), 429
        return redirect(url_for("pages.admin_login_page"))

    allowed, error_msg = check_login_rate_limits(client_ip, username_key)
    if not allowed:
        if request.is_json:
            return jsonify({"error": error_msg, "need_captcha": True}), 429
        return redirect(url_for("pages.admin_login_page"))

    captcha_required = check_login_captcha_required(client_ip, username_key) or scan_locked or bool(need_captcha)
    if captcha_required:
        if not captcha_session or not captcha_code:
            if request.is_json:
                return jsonify({"error": "请填写验证码", "need_captcha": True}), 400
            return redirect(url_for("pages.admin_login_page"))
        success, message = safe_verify_and_consume_captcha(captcha_session, captcha_code)
        if not success:
            record_login_failure(client_ip, username_key)
            if request.is_json:
                return jsonify({"error": message, "need_captcha": True}), 400
            return redirect(url_for("pages.admin_login_page"))

    admin = database.verify_admin(username, password)
    if admin:
        clear_login_failures(client_ip, username_key)
        session.pop("admin_id", None)
        session.pop("admin_username", None)
        session["admin_id"] = admin["id"]
        session["admin_username"] = admin["username"]
        session["admin_reauth_until"] = time.time() + int(config.ADMIN_REAUTH_WINDOW_SECONDS)
        session.permanent = True
        session.modified = True

        logger.info(f"[admin_login] 管理员 {username} 登录成功")

        if request.is_json:
            return jsonify({"success": True, "redirect": "/yuyx/admin"})
        return redirect(url_for("pages.admin_page"))

    record_login_failure(client_ip, username_key)
    delay = get_login_failure_delay_seconds(client_ip, username_key)
    if delay > 0:
        time.sleep(delay)
    logger.warning(f"[admin_login] 管理员 {username} 登录失败 - 用户名或密码错误")
    if request.is_json:
        return jsonify({"error": "管理员用户名或密码错误", "need_captcha": check_login_captcha_required(client_ip)}), 401
    return redirect(url_for("pages.admin_login_page"))


@admin_api_bp.route("/logout", methods=["POST"])
@admin_required
def admin_logout():
    """管理员登出"""
    session.pop("admin_id", None)
    session.pop("admin_username", None)
    session.pop("admin_reauth_until", None)
    return jsonify({"success": True})


@admin_api_bp.route("/admin/reauth", methods=["POST"])
@admin_required
def admin_reauth():
    """管理员敏感操作二次确认"""
    data = request.json or {}
    password = (data.get("password") or "").strip()
    if not password:
        return jsonify({"error": "密码不能为空"}), 400

    username = session.get("admin_username")
    if not username:
        return jsonify({"error": "未登录"}), 401

    admin = database.verify_admin(username, password)
    if not admin:
        return jsonify({"error": "密码错误"}), 401

    session["admin_reauth_until"] = time.time() + int(config.ADMIN_REAUTH_WINDOW_SECONDS)
    session.modified = True
    return jsonify({"success": True, "expires_in": int(config.ADMIN_REAUTH_WINDOW_SECONDS)})

@admin_api_bp.route("/docker/restart", methods=["POST"])
@admin_required
def restart_docker_container():
    """重启Docker容器"""
    import subprocess

    try:
        reauth_response = _require_admin_reauth()
        if reauth_response:
            return reauth_response
        if not os.path.exists("/.dockerenv"):
            return jsonify({"error": "当前不在Docker容器中运行"}), 400

        logger.info("[系统] 管理员触发Docker容器重启")

        restart_script = """
import os
import time

time.sleep(3)
os._exit(0)
"""

        with open("/tmp/restart_container.py", "w") as f:
            f.write(restart_script)

        subprocess.Popen(
            ["python3", "/tmp/restart_container.py"],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            start_new_session=True,
        )

        return jsonify({"success": True, "message": "容器将在3秒后重启，请稍后刷新页面"})
    except Exception as e:
        logger.error(f"[系统] Docker容器重启失败: {str(e)}")
        return jsonify({"error": f"重启失败: {str(e)}"}), 500


# ==================== 断点续传（管理员） ====================


@admin_api_bp.route("/checkpoint/paused")
@admin_required
def checkpoint_get_paused():
    try:
        user_id = request.args.get("user_id", type=int)
        tasks = get_checkpoint_mgr().get_paused_tasks(user_id=user_id)
        return jsonify({"success": True, "tasks": tasks})
    except Exception as e:
        logger.error(f"获取暂停任务失败: {e}")
        return jsonify({"success": False, "message": str(e)}), 500


@admin_api_bp.route("/checkpoint/<task_id>/resume", methods=["POST"])
@admin_required
def checkpoint_resume(task_id):
    try:
        checkpoint_mgr = get_checkpoint_mgr()
        checkpoint = checkpoint_mgr.get_checkpoint(task_id)
        if not checkpoint:
            return jsonify({"success": False, "message": "任务不存在"}), 404
        if checkpoint["status"] != "paused":
            return jsonify({"success": False, "message": "任务未暂停"}), 400
        if checkpoint_mgr.resume_task(task_id):
            user_id = checkpoint["user_id"]
            if not safe_get_user_accounts_snapshot(user_id):
                load_user_accounts(user_id)
            ok, msg = submit_account_task(
                user_id=user_id,
                account_id=checkpoint["account_id"],
                browse_type=checkpoint["browse_type"],
                enable_screenshot=True,
                source="resumed",
            )
            if not ok:
                return jsonify({"success": False, "message": msg}), 400
            return jsonify({"success": True})
        return jsonify({"success": False}), 500
    except Exception as e:
        logger.error(f"恢复任务失败: {e}")
        return jsonify({"success": False, "message": str(e)}), 500


@admin_api_bp.route("/checkpoint/<task_id>/abandon", methods=["POST"])
@admin_required
def checkpoint_abandon(task_id):
    try:
        if get_checkpoint_mgr().abandon_task(task_id):
            return jsonify({"success": True})
        return jsonify({"success": False}), 404
    except Exception as e:
        return jsonify({"success": False, "message": str(e)}), 500
