import os
import re
import shutil
import subprocess
import threading
from datetime import datetime

from flask import Blueprint, jsonify

# Blueprint 用于与主 Flask 应用解耦
space_blueprint = Blueprint("space_mgnt", __name__)

CLEAN_SCRIPT_DIR = "/opt/sysb/scripts"
CLEAN_SCRIPT_NAME = "clean_assets.py"

_run_lock = threading.Lock()
_status_lock = threading.Lock()
_clean_status = {
    "status": "idle",  # idle / running / success / failed
    "started": None,
    "finished": None,
    "message": "",
}
SPACE_CHECK_THRESHHOLD=30 * 1024


def _get_mount_point() -> str:
    """
    选取当前工作目录所在磁盘的根路径，兼容 Windows / Linux。
    """
    return os.path.abspath(os.sep)


def _fetch_disk_usage(path: str) -> dict:
    """
    基于给定路径获取磁盘使用情况，单位为 MB。
    """
    usage = shutil.disk_usage(path)
    mb = 1024 * 1024
    return {
        "total_space": round(usage.total / mb, 2),
        "used_space": round(usage.used / mb, 2),
        "free_space": round(usage.free / mb, 2),
    }


@space_blueprint.route("/api/v1/robotconsole/space/info", methods=["GET"])
def get_space_info():
    """
    返回本机磁盘使用信息，总大小/已用/可用，单位为字节。
    """
    mount_point = _get_mount_point()
    data = _fetch_disk_usage(mount_point)
    data["releaseable_space"] = _get_releaseable_space()
    return jsonify({"code": 200, "message": "success", "data": data})


@space_blueprint.route("/api/v1/robotconsole/space/check", methods=["GET"])
def get_space_check():
    """
    返回本机磁盘使用信息，总大小/已用/可用，单位为字节。
    """
    check_result = False;
    mount_point = _get_mount_point()
    data = _fetch_disk_usage(mount_point)
    if  data["free_space"] > SPACE_CHECK_THRESHHOLD:
        check_result = True
    return jsonify({"code": 200, "message": "success", "data": {"check_result": check_result}})


def _get_releaseable_space():
    releaseable_space = ""
    if not os.path.isdir(CLEAN_SCRIPT_DIR):
        return releaseable_space
    script_path = os.path.join(CLEAN_SCRIPT_DIR, CLEAN_SCRIPT_NAME)
    if not os.path.isfile(script_path):
        return releaseable_space
    cmd = ["python3", CLEAN_SCRIPT_NAME, "--dry-run"]
    completed = subprocess.run(
        cmd,
        cwd=CLEAN_SCRIPT_DIR,
        capture_output=True,
        text=True,
        check=False,
    )
    if completed.returncode == 0:
        output = completed.stdout.strip()
        # 解析"本次操作预计共可释放"后面的format_size内容
        # 匹配格式：本次操作预计共可释放 1.5GB。或 本次操作预计共可释放: 500MB 等
        # 支持数字（包括小数）+ 单位（B, KB, MB, GB, TB等，大小写不敏感）
        pattern = r"本次操作预计共可释放[：:\s]+([\d.]+\s*[KMGT]?B)"
        match = re.search(pattern, output, re.IGNORECASE)
        if match:
            releaseable_space = match.group(1).strip()
    return releaseable_space


def _status_snapshot() -> dict:
    with _status_lock:
        return dict(_clean_status)


def _set_status(status: str, message: str = ""):
    with _status_lock:
        _clean_status["status"] = status
        _clean_status["message"] = message
        if status == "running":
            _clean_status["started"] = datetime.utcnow().isoformat() + "Z"
            _clean_status["finished"] = None
        elif status in ("success", "failed"):
            _clean_status["finished"] = datetime.utcnow().isoformat() + "Z"


def _clean_worker():
    try:
        _set_status("running", "clean job started")
        if not os.path.isdir(CLEAN_SCRIPT_DIR):
            raise FileNotFoundError(f"{CLEAN_SCRIPT_DIR} 不存在")
        script_path = os.path.join(CLEAN_SCRIPT_DIR, CLEAN_SCRIPT_NAME)
        if not os.path.isfile(script_path):
            raise FileNotFoundError(f"{script_path} 不存在")
        cmd = ["python3", CLEAN_SCRIPT_NAME]
        completed = subprocess.run(
            cmd,
            cwd=CLEAN_SCRIPT_DIR,
            capture_output=True,
            text=True,
            check=False,
        )
        if completed.returncode == 0:
            _set_status("success",  "clean success")
        else:
            msg = completed.stderr.strip() or f"return code {completed.returncode}"
            _set_status("failed", msg)
    except Exception as exc:
        _set_status("failed", str(exc))


@space_blueprint.route("/api/v1/robotconsole/space/clean", methods=["POST"])
def clean_space():
    with _run_lock:
        current = _status_snapshot()
        if current["status"] == "running":
            return {"code": 409, "message": "success", "data": current}
        thread = threading.Thread(target=_clean_worker, daemon=True)
        _set_status("running", "clean job scheduled")
        thread.start()
    return jsonify({"code": 200, "message": "success", "data": _status_snapshot()})


@space_blueprint.route("/api/v1/robotconsole/space/clean-status", methods=["GET"])
def clean_status():
    return jsonify({"code": 200, "message": "success", "data": _status_snapshot()})
