import json
import os
import shutil
import subprocess
from pathlib import Path
from typing import Any

from loguru import logger

# 使用绝对路径，确保无论从哪个目录运行都正确
PROJECT_ROOT = Path(__file__).parent.parent
OUTPUT_FILE = PROJECT_ROOT / "reports" / "result.json"


def run_dirsearch(
    url: str,
    cookies: str | None = None,
    extensions: list[str] | None = None,
    wordlist: str | None = None,
    threads: int | None = None,
    timeout: int | None = None,
    exclude_codes: list[str] | None = None,
    include_codes: list[str] | None = None,
    recursive: bool = False,
    recursion_depth: int | None = None,
) -> None | dict[str, bool | list[Any]] | dict[str, bool | str]:
    """
    运行dirsearch，返回结果
    """
    output = str(OUTPUT_FILE)

    # 【修复1】查找 dirsearch 的绝对路径，防止 MCP 环境找不到命令
    # 在 uv 环境下，这会指向 .venv/Scripts/dirsearch.exe
    executable = shutil.which("dirsearch")
    if not executable:
        return {"success": False, "error": "dirsearch command not found in environment"}

    cmd = [
        executable,
        "-u", url,
        "--format=json",  # 输出为 JSON
        "-o", output,  # 输出文件路径
        "--quiet"  # 减少控制台输出
    ]
    if cookies:
        cmd.extend(["--cookies", cookies])

    # 扩展名
    if extensions:
        cmd.extend(["-e", ",".join(extensions)])

    # 字典文件
    if wordlist:
        cmd.extend(["-w", wordlist])

    # 线程数
    if threads:
        cmd.extend(["-t", str(threads)])

    # 超时时间
    if timeout:
        cmd.extend(["--max-time", str(timeout)])

    # 排除状态码
    if exclude_codes:
        cmd.extend(["-x", ",".join(exclude_codes)])

    # 包含状态码
    if include_codes:
        cmd.extend(["-i", ",".join(include_codes)])

    # 递归扫描
    if recursive:
        cmd.append("-r")
        if recursion_depth:
            cmd.extend(["-R", str(recursion_depth)])

    try:
        # 确保 reports 目录存在
        os.makedirs(OUTPUT_FILE.parent, exist_ok=True)

        if os.path.exists(output):
            os.remove(output)
            logger.info(f"remove {output}")

        logger.info(f"start scan: {cmd}")
        # 开始扫描
        result = subprocess.run(
            cmd,
            timeout=timeout if timeout else 300,
            stdout=subprocess.DEVNULL,  # 丢弃标准输出（解决慢）
            stdin=subprocess.DEVNULL,   # 【修复2】关闭输入流（解决卡死）
            stderr=subprocess.PIPE,     # 【修复3】捕获错误流（解决无法排错）
            text=True                   # 确保 stderr 是字符串
        )
        # 如果 stderr 有内容，打印出来看看（Dirsearch 即使成功也可能在 stderr 打印一些 warning）
        if result.stderr:
            logger.warning(f"dirsearch stderr: {result.stderr[:500]}...") # 只打印前500字防止刷屏

        logger.info(f"finish scan, returncode={result.returncode}")
        if os.path.exists(output):
            with open(output) as f:
                data = json.load(f)
            return {
                "success": True,
                "results": data
            }
        if result.returncode != 0:
            logger.error(f"dirsearch failed: {result.stderr}")
    except subprocess.TimeoutExpired:
        return {
            "success": False,
            "error": f"timeout {timeout}"
        }
    except Exception as e:
        logger.error(f"dirsearch error: {e}")
        return {
            "success": False,
            "error": str(e)
        }
    # 确保总是返回 dict
    return {
        "success": False,
        "error": "unknown error"
    }
