"""
core/env_detect.py - 运行环境检测
===================================
检测当前运行环境是桌面系统还是容器/Termux 环境，
供浏览器技能、VNC 管理器等模块使用。

桌面环境 (Windows / macOS / Linux with real DISPLAY):
  - 直接调用系统已安装的 Chrome/Chromium
  - 不需要 VNC/Xvfb
  - 不需要 --no-sandbox 等容器参数

容器/Termux 环境 (无 DISPLAY 的 Linux):
  - 需要 VNC/Xvfb 提供虚拟显示
  - 可能需要自动安装 Chromium
  - 需要 --no-sandbox 等容器参数
"""
from __future__ import annotations

import os
import platform
import subprocess
from functools import lru_cache
from typing import Optional

from core.logger import get_logger

logger = get_logger("myagent.env_detect")


@lru_cache(maxsize=1)
def is_desktop() -> bool:
    """
    判断当前是否为桌面环境（有真实显示器）。

    桌面环境判定:
      - Windows → 始终为桌面
      - macOS (Darwin) → 始终为桌面
      - Linux → 检查是否有真实 X11/Wayland 显示（非 Xvfb）

    Returns:
        True = 桌面环境，直接用系统 Chrome
        False = 容器/Termux/无头环境，需要 VNC/Xvfb
    """
    system = platform.system()

    # Windows 和 macOS 一定是桌面环境
    if system in ("Windows", "Darwin"):
        return True

    # Linux: 需要检测是否有真实显示
    if system == "Linux":
        return _linux_has_real_display()

    # 未知系统，保守假设为容器环境
    return False


def _linux_has_real_display() -> bool:
    """
    检测 Linux 是否有真实的 X11/Wayland 显示。

    "真实显示" = 不是 Xvfb 虚拟显示，而是:
      - 物理显示器连接
      - Wayland 合成器
      - 通过 SSH X11 转发
      - xdg-desktop-portal 等桌面服务

    Xvfb 不算真实显示（它只在 /tmp/.X11-unix/ 有 socket，
    但没有 WM 检测、没有 dbus 桌面服务等）。
    """
    # 1. Wayland 检测（Wayland 一定是桌面环境）
    wayland_display = os.environ.get("WAYLAND_DISPLAY", "").strip()
    if wayland_display:
        return True

    # 2. XDG_SESSION_TYPE 检测
    session_type = os.environ.get("XDG_SESSION_TYPE", "").strip()
    if session_type in ("wayland", "x11"):
        # x11 可能是 Xvfb，需要进一步验证
        if session_type == "wayland":
            return True
        # session_type == "x11" → 继续验证是否为 Xvfb

    # 3. DISPLAY 环境变量检查
    display = os.environ.get("DISPLAY", "").strip()
    if not display:
        # 无 DISPLAY → 可能是纯命令行/容器环境
        # 但仍可能通过 VNC 有 Xvfb，检查 socket
        return False

    # 4. 检查是否有桌面会话指示器（排除纯 Xvfb）
    # Xvfb 环境通常没有这些环境变量
    desktop_indicators = [
        "DESKTOP_SESSION",
        "XDG_CURRENT_DESKTOP",
        "XDG_SESSION_DESKTOP",
        "GNOME_DESKTOP_SESSION_ID",
    ]
    for var in desktop_indicators:
        if os.environ.get(var, "").strip():
            return True

    # 5. 检查 dbus 和桌面服务（桌面环境通常有 dbus）
    if os.environ.get("DBUS_SESSION_BUS_ADDRESS", "").strip():
        # 有 dbus 但没有桌面指示器 → 可能是 Xvfb + VNC
        # 继续其他检查
        pass

    # 6. 检查是否有真实窗口管理器（非 Xvfb 自带的 twm/fluxbox）
    try:
        result = subprocess.run(
            ["pgrep", "-f", "(gnome-shell|mutter|kwin|marco|compiz|xfwm4|openbox|fluxbox|icewm|jwm|lxsession)"],
            capture_output=True, text=True, timeout=3,
        )
        if result.returncode == 0 and result.stdout.strip():
            # 有 WM 在运行，但不一定是 Xvfb 上的
            # 检查 DISPLAY 是否指向 Xvfb
            if _is_xvfb_display(display):
                return False  # Xvfb 上的 WM → 不是真实桌面
            return True  # 真实 WM → 桌面环境
    except Exception:
        pass

    # 7. 检查 DISPLAY 是否指向 Xvfb
    if _is_xvfb_display(display):
        return False

    # 8. 检查是否有 xdg-desktop-portal（桌面环境标志性服务）
    try:
        result = subprocess.run(
            ["pgrep", "-f", "xdg-desktop-portal"],
            capture_output=True, text=True, timeout=3,
        )
        if result.returncode == 0 and result.stdout.strip():
            return True
    except Exception:
        pass

    # 9. 默认：有 DISPLAY 但无法确认为真实桌面 → 保守假设不是桌面
    # （宁可多启动 VNC，也不要在有头环境下漏启动）
    return False


def _is_xvfb_display(display: str) -> bool:
    """
    检查 DISPLAY 是否指向 Xvfb 虚拟显示。

    Xvfb 的特征:
      - 进程名包含 "Xvfb"
      - 没有物理 GPU 连接
    """
    try:
        num = display.lstrip(":").split(".")[0]
        # 查找该 display 上的 X server 进程
        result = subprocess.run(
            ["pgrep", "-f", f"Xvfb :{num}"],
            capture_output=True, text=True, timeout=3,
        )
        if result.returncode == 0 and result.stdout.strip():
            return True
    except Exception:
        pass
    return False


@lru_cache(maxsize=1)
def is_termux() -> bool:
    """
    检测是否在 Termux 环境下运行。

    Termux 特征:
      - /data/data/com.termux 目录存在
      - TERMUX_VERSION 环境变量
      - proot-distro 环境
    """
    # 1. 检查 Termux 特有路径
    if os.path.isdir("/data/data/com.termux"):
        return True

    # 2. 检查环境变量
    if os.environ.get("TERMUX_VERSION", "").strip():
        return True

    # 3. 检查 proot 环境（Termux proot-distro）
    if os.environ.get("PROOT_SERVICE", "").strip():
        return True

    # 4. 检查 Android 特征
    if os.path.isfile("/system/bin/app_process"):
        return True

    return False


@lru_cache(maxsize=1)
def needs_container_args() -> bool:
    """
    判断是否需要添加容器相关的 Chrome 启动参数。

    容器参数: --no-sandbox, --disable-setuid-sandbox,
              --disable-dev-shm-usage, --disable-gpu

    桌面环境不需要这些参数，加了反而可能导致问题。

    Returns:
        True = 容器/Termux 环境，需要加容器参数
        False = 桌面环境，不需要加容器参数
    """
    # 桌面环境绝不需要容器参数
    if is_desktop():
        return False

    # 非桌面 Linux / Termux → 需要容器参数
    return True


def get_env_summary() -> dict:
    """返回当前环境检测摘要（用于调试和日志）"""
    return {
        "system": platform.system(),
        "is_desktop": is_desktop(),
        "is_termux": is_termux(),
        "needs_container_args": needs_container_args(),
        "display": os.environ.get("DISPLAY", ""),
        "wayland": os.environ.get("WAYLAND_DISPLAY", ""),
        "xdg_session_type": os.environ.get("XDG_SESSION_TYPE", ""),
        "desktop_session": os.environ.get("DESKTOP_SESSION", ""),
        "xdg_current_desktop": os.environ.get("XDG_CURRENT_DESKTOP", ""),
    }
