"""
FFmpeg 工具模块 - 提供 FFmpeg 相关的工具函数，特别是硬件加速检测
优化多平台兼容性，支持渐进式降级和智能错误处理
"""
import os
import platform
import subprocess
import tempfile
from typing import Dict, List, Optional, Tuple, Union
from loguru import logger

# 全局变量，存储检测到的硬件加速信息
_FFMPEG_HW_ACCEL_INFO = {
    "available": False,
    "type": None,
    "encoder": None,
    "hwaccel_args": [],
    "message": "",
    "is_dedicated_gpu": False,
    "fallback_available": False,  # 是否有备用方案
    "fallback_encoder": None,     # 备用编码器
    "platform": None,             # 平台信息
    "gpu_vendor": None,           # GPU厂商
    "tested_methods": []          # 已测试的方法
}

# 硬件加速优先级配置（按平台和GPU类型）
HWACCEL_PRIORITY = {
    "windows": {
        "nvidia": ["cuda", "nvenc", "d3d11va", "dxva2"],
        "amd": ["d3d11va", "dxva2", "amf"],  # 不再完全禁用AMD
        "intel": ["qsv", "d3d11va", "dxva2"],
        "unknown": ["d3d11va", "dxva2"]
    },
    "darwin": {
        "apple": ["videotoolbox"],
        "nvidia": ["cuda", "videotoolbox"],
        "amd": ["videotoolbox"],
        "intel": ["videotoolbox"],
        "unknown": ["videotoolbox"]
    },
    "linux": {
        "nvidia": ["cuda", "nvenc", "vaapi"],
        "amd": ["vaapi", "amf"],
        "intel": ["qsv", "vaapi"],
        "unknown": ["vaapi"]
    }
}

# 编码器映射
ENCODER_MAPPING = {
    "cuda": "h264_nvenc",
    "nvenc": "h264_nvenc",
    "videotoolbox": "h264_videotoolbox",
    "qsv": "h264_qsv",
    "vaapi": "h264_vaapi",
    "amf": "h264_amf",
    "d3d11va": "libx264",  # D3D11VA只用于解码
    "dxva2": "libx264",    # DXVA2只用于解码
    "software": "libx264"
}


def get_null_input() -> str:
    """
    获取平台特定的空输入文件路径

    Returns:
        str: 平台特定的空输入路径
    """
    system = platform.system().lower()
    if system == "windows":
        return "NUL"
    else:
        return "/dev/null"


def create_test_video() -> str:
    """
    创建一个临时的测试视频文件，用于硬件加速测试

    Returns:
        str: 临时测试视频文件路径
    """
    try:
        # 创建临时文件
        temp_file = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
        temp_path = temp_file.name
        temp_file.close()

        # 生成一个简单的测试视频（1秒，黑色画面）
        cmd = [
            'ffmpeg', '-y', '-f', 'lavfi', '-i', 'color=black:size=320x240:duration=1',
            '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-t', '1', temp_path
        ]

        subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        return temp_path
    except Exception as e:
        logger.debug(f"创建测试视频失败: {str(e)}")
        return get_null_input()


def cleanup_test_video(path: str) -> None:
    """
    清理测试视频文件

    Args:
        path: 测试视频文件路径
    """
    try:
        if path != get_null_input() and os.path.exists(path):
            os.unlink(path)
    except Exception as e:
        logger.debug(f"清理测试视频失败: {str(e)}")


def check_ffmpeg_installation() -> bool:
    """
    检查ffmpeg是否已安装

    Returns:
        bool: 如果安装则返回True，否则返回False
    """
    try:
        # 在Windows系统上使用UTF-8编码
        is_windows = os.name == 'nt'
        if is_windows:
            subprocess.run(['ffmpeg', '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', check=True)
        else:
            subprocess.run(['ffmpeg', '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        return True
    except (subprocess.SubprocessError, FileNotFoundError):
        logger.error("ffmpeg未安装或不在系统PATH中，请安装ffmpeg")
        return False


def detect_gpu_vendor() -> str:
    """
    检测GPU厂商

    Returns:
        str: GPU厂商 (nvidia, amd, intel, apple, unknown)
    """
    system = platform.system().lower()

    try:
        if system == "windows":
            gpu_info = _get_windows_gpu_info().lower()
            if 'nvidia' in gpu_info or 'geforce' in gpu_info or 'quadro' in gpu_info:
                return "nvidia"
            elif 'amd' in gpu_info or 'radeon' in gpu_info:
                return "amd"
            elif 'intel' in gpu_info:
                return "intel"
        elif system == "darwin":
            # macOS上检查是否为Apple Silicon
            if platform.machine().lower() in ['arm64', 'aarch64']:
                return "apple"
            else:
                # Intel Mac，可能有独立显卡
                gpu_info = _get_macos_gpu_info().lower()
                if 'nvidia' in gpu_info:
                    return "nvidia"
                elif 'amd' in gpu_info or 'radeon' in gpu_info:
                    return "amd"
                else:
                    return "intel"
        elif system == "linux":
            gpu_info = _get_linux_gpu_info().lower()
            if 'nvidia' in gpu_info:
                return "nvidia"
            elif 'amd' in gpu_info or 'radeon' in gpu_info:
                return "amd"
            elif 'intel' in gpu_info:
                return "intel"
    except Exception as e:
        logger.debug(f"检测GPU厂商失败: {str(e)}")

    return "unknown"


def test_hwaccel_method(method: str, test_input: str) -> bool:
    """
    测试特定的硬件加速方法

    Args:
        method: 硬件加速方法名称
        test_input: 测试输入文件路径

    Returns:
        bool: 是否支持该方法
    """
    try:
        # 构建测试命令
        cmd = ["ffmpeg", "-hide_banner", "-loglevel", "error"]

        # 添加硬件加速参数
        if method == "cuda":
            cmd.extend(["-hwaccel", "cuda", "-hwaccel_output_format", "cuda"])
        elif method == "nvenc":
            cmd.extend(["-hwaccel", "cuda"])
        elif method == "videotoolbox":
            cmd.extend(["-hwaccel", "videotoolbox"])
        elif method == "qsv":
            cmd.extend(["-hwaccel", "qsv"])
        elif method == "vaapi":
            # 尝试找到VAAPI设备
            render_device = _find_vaapi_device()
            if render_device:
                cmd.extend(["-hwaccel", "vaapi", "-vaapi_device", render_device])
            else:
                cmd.extend(["-hwaccel", "vaapi"])
        elif method == "d3d11va":
            cmd.extend(["-hwaccel", "d3d11va"])
        elif method == "dxva2":
            cmd.extend(["-hwaccel", "dxva2"])
        elif method == "amf":
            cmd.extend(["-hwaccel", "auto"])  # AMF通常通过auto检测
        else:
            return False

        # 添加输入和输出
        cmd.extend(["-i", test_input, "-f", "null", "-t", "0.1", "-"])

        # 执行测试
        result = subprocess.run(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            check=False,
            timeout=10  # 10秒超时
        )

        success = result.returncode == 0
        if success:
            logger.debug(f"硬件加速方法 {method} 测试成功")
        else:
            logger.debug(f"硬件加速方法 {method} 测试失败: {result.stderr[:200]}")

        return success

    except subprocess.TimeoutExpired:
        logger.debug(f"硬件加速方法 {method} 测试超时")
        return False
    except Exception as e:
        logger.debug(f"硬件加速方法 {method} 测试异常: {str(e)}")
        return False


def detect_hardware_acceleration() -> Dict[str, Union[bool, str, List[str], None]]:
    """
    检测系统可用的硬件加速器，使用渐进式检测和智能降级

    Returns:
        Dict: 包含硬件加速信息的字典
    """
    global _FFMPEG_HW_ACCEL_INFO

    # 如果已经检测过，直接返回结果
    if _FFMPEG_HW_ACCEL_INFO["type"] is not None:
        return _FFMPEG_HW_ACCEL_INFO

    # 检查ffmpeg是否已安装
    if not check_ffmpeg_installation():
        _FFMPEG_HW_ACCEL_INFO["message"] = "FFmpeg未安装或不在系统PATH中"
        return _FFMPEG_HW_ACCEL_INFO

    # 检测平台和GPU信息
    system = platform.system().lower()
    gpu_vendor = detect_gpu_vendor()

    _FFMPEG_HW_ACCEL_INFO["platform"] = system
    _FFMPEG_HW_ACCEL_INFO["gpu_vendor"] = gpu_vendor

    logger.debug(f"检测硬件加速 - 平台: {system}, GPU厂商: {gpu_vendor}")

    # 获取FFmpeg支持的硬件加速器列表
    try:
        hwaccels_cmd = subprocess.run(
            ['ffmpeg', '-hide_banner', '-hwaccels'],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False
        )
        supported_hwaccels = hwaccels_cmd.stdout.lower() if hwaccels_cmd.returncode == 0 else ""
        logger.debug(f"FFmpeg支持的硬件加速器: {supported_hwaccels}")
    except Exception as e:
        logger.warning(f"获取FFmpeg硬件加速器列表失败: {str(e)}")
        supported_hwaccels = ""

    # 创建测试输入
    test_input = create_test_video()

    try:
        # 根据平台和GPU厂商获取优先级列表
        priority_list = HWACCEL_PRIORITY.get(system, {}).get(gpu_vendor, [])
        if not priority_list:
            priority_list = HWACCEL_PRIORITY.get(system, {}).get("unknown", [])

        logger.debug(f"硬件加速测试优先级: {priority_list}")

        # 按优先级测试硬件加速方法
        for method in priority_list:
            # 检查FFmpeg是否支持该方法
            if method not in supported_hwaccels and method != "nvenc":  # nvenc可能不在hwaccels列表中
                logger.debug(f"跳过不支持的硬件加速方法: {method}")
                continue

            _FFMPEG_HW_ACCEL_INFO["tested_methods"].append(method)

            if test_hwaccel_method(method, test_input):
                # 找到可用的硬件加速方法
                _FFMPEG_HW_ACCEL_INFO["available"] = True
                _FFMPEG_HW_ACCEL_INFO["type"] = method
                _FFMPEG_HW_ACCEL_INFO["encoder"] = ENCODER_MAPPING.get(method, "libx264")

                # 构建硬件加速参数
                if method == "cuda":
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "cuda", "-hwaccel_output_format", "cuda"]
                elif method == "nvenc":
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "cuda"]
                elif method == "videotoolbox":
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "videotoolbox"]
                elif method == "qsv":
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "qsv"]
                elif method == "vaapi":
                    render_device = _find_vaapi_device()
                    if render_device:
                        _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "vaapi", "-vaapi_device", render_device]
                    else:
                        _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "vaapi"]
                elif method in ["d3d11va", "dxva2"]:
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", method]
                elif method == "amf":
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "auto"]

                # 判断是否为独立GPU
                _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = gpu_vendor in ["nvidia", "amd"] or (gpu_vendor == "intel" and "arc" in _get_gpu_info().lower())

                _FFMPEG_HW_ACCEL_INFO["message"] = f"使用 {method} 硬件加速 ({gpu_vendor} GPU)"
                logger.debug(f"硬件加速检测成功: {method} ({gpu_vendor})")
                break

        # 如果没有找到硬件加速，设置软件编码作为备用
        if not _FFMPEG_HW_ACCEL_INFO["available"]:
            _FFMPEG_HW_ACCEL_INFO["fallback_available"] = True
            _FFMPEG_HW_ACCEL_INFO["fallback_encoder"] = "libx264"
            _FFMPEG_HW_ACCEL_INFO["message"] = f"未找到可用的硬件加速，将使用软件编码 (平台: {system}, GPU: {gpu_vendor})"
            logger.debug("未检测到硬件加速，将使用软件编码")

    finally:
        # 清理测试文件
        cleanup_test_video(test_input)

    return _FFMPEG_HW_ACCEL_INFO


def _get_gpu_info() -> str:
    """
    获取GPU信息的统一接口

    Returns:
        str: GPU信息字符串
    """
    system = platform.system().lower()

    if system == "windows":
        return _get_windows_gpu_info()
    elif system == "darwin":
        return _get_macos_gpu_info()
    elif system == "linux":
        return _get_linux_gpu_info()
    else:
        return "unknown"


def _get_macos_gpu_info() -> str:
    """
    获取macOS系统的GPU信息

    Returns:
        str: GPU信息字符串
    """
    try:
        # 使用system_profiler获取显卡信息
        result = subprocess.run(
            ['system_profiler', 'SPDisplaysDataType'],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False
        )
        if result.returncode == 0:
            return result.stdout

        # 备用方法：检查是否为Apple Silicon
        if platform.machine().lower() in ['arm64', 'aarch64']:
            return "Apple Silicon GPU"
        else:
            return "Intel Mac GPU"
    except Exception as e:
        logger.debug(f"获取macOS GPU信息失败: {str(e)}")
        return "unknown"


def _find_vaapi_device() -> Optional[str]:
    """
    查找可用的VAAPI设备

    Returns:
        Optional[str]: VAAPI设备路径，如果没有找到则返回None
    """
    try:
        # 常见的VAAPI设备路径
        possible_devices = [
            "/dev/dri/renderD128",
            "/dev/dri/renderD129",
            "/dev/dri/card0",
            "/dev/dri/card1"
        ]

        for device in possible_devices:
            if os.path.exists(device):
                # 测试设备是否可用
                test_cmd = subprocess.run(
                    ["ffmpeg", "-hide_banner", "-loglevel", "error",
                     "-hwaccel", "vaapi", "-vaapi_device", device,
                     "-f", "lavfi", "-i", "color=black:size=64x64:duration=0.1",
                     "-f", "null", "-"],
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False
                )
                if test_cmd.returncode == 0:
                    logger.debug(f"找到可用的VAAPI设备: {device}")
                    return device

        logger.debug("未找到可用的VAAPI设备")
        return None
    except Exception as e:
        logger.debug(f"查找VAAPI设备失败: {str(e)}")
        return None


def _detect_macos_acceleration(supported_hwaccels: str) -> None:
    """
    检测macOS系统的硬件加速

    Args:
        supported_hwaccels: FFmpeg支持的硬件加速器列表
    """
    global _FFMPEG_HW_ACCEL_INFO

    if 'videotoolbox' in supported_hwaccels:
        # 测试videotoolbox
        try:
            test_cmd = subprocess.run(
                ["ffmpeg", "-hwaccel", "videotoolbox", "-i", "/dev/null", "-f", "null", "-"],
                stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
            )
            if test_cmd.returncode == 0:
                _FFMPEG_HW_ACCEL_INFO["available"] = True
                _FFMPEG_HW_ACCEL_INFO["type"] = "videotoolbox"
                _FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_videotoolbox"
                _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "videotoolbox"]
                # macOS的Metal GPU加速通常是集成GPU
                _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = False
                return
        except Exception as e:
            logger.debug(f"测试videotoolbox失败: {str(e)}")

    _FFMPEG_HW_ACCEL_INFO["message"] = "macOS系统未检测到可用的videotoolbox硬件加速"


def _detect_windows_acceleration(supported_hwaccels: str) -> None:
    """
    检测Windows系统的硬件加速 - 基于实际测试结果优化
    
    重要发现：CUDA硬件解码在视频裁剪场景下会导致滤镜链错误，
    因此优先使用纯NVENC编码器方案，既保证性能又确保兼容性。
    
    Args:
        supported_hwaccels: FFmpeg支持的硬件加速器列表
    """
    global _FFMPEG_HW_ACCEL_INFO
    
    # 在Windows上，首先检查显卡信息
    gpu_info = _get_windows_gpu_info()
    logger.debug(f"Windows GPU信息: {gpu_info}")
    
    # 检查是否为Intel集成显卡
    is_intel_integrated = False
    if 'intel' in gpu_info.lower() and ('hd graphics' in gpu_info.lower() or 'uhd graphics' in gpu_info.lower()):
        logger.info("检测到Intel集成显卡")
        is_intel_integrated = True
    
    # 1. 优先检测NVIDIA硬件加速 - 基于实际测试的最佳方案
    if 'nvidia' in gpu_info.lower() or 'geforce' in gpu_info.lower() or 'quadro' in gpu_info.lower():
        logger.info("检测到NVIDIA显卡，开始测试硬件加速")
        
        # 检查NVENC编码器是否可用
        try:
            encoders_cmd = subprocess.run(
                ["ffmpeg", "-hide_banner", "-encoders"],
                stderr=subprocess.PIPE, stdout=subprocess.PIPE, 
                encoding='utf-8', text=True, check=False
            )
            has_nvenc = "h264_nvenc" in encoders_cmd.stdout.lower()
            logger.debug(f"NVENC编码器检测结果: {'可用' if has_nvenc else '不可用'}")
            
            if has_nvenc:
                # 优先方案：纯NVENC编码器（测试证明最兼容）
                logger.debug("测试纯NVENC编码器（推荐方案，避免滤镜链问题）")
                test_cmd = subprocess.run([
                    "ffmpeg", "-hide_banner", "-loglevel", "error",
                    "-f", "lavfi", "-i", "testsrc=duration=0.1:size=640x480:rate=30",
                    "-c:v", "h264_nvenc", "-preset", "medium", "-cq", "23",
                    "-pix_fmt", "yuv420p", "-f", "null", "-"
                ], stderr=subprocess.PIPE, stdout=subprocess.PIPE, 
                   encoding='utf-8', text=True, check=False)
                
                if test_cmd.returncode == 0:
                    _FFMPEG_HW_ACCEL_INFO["available"] = True
                    _FFMPEG_HW_ACCEL_INFO["type"] = "nvenc"  # 使用nvenc类型标识纯编码器
                    _FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_nvenc"
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = []  # 不使用硬件解码参数
                    _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = True
                    _FFMPEG_HW_ACCEL_INFO["message"] = "纯NVENC编码器（最佳兼容性）"
                    logger.info("✓ 纯NVENC编码器测试成功")
                    return
                
                # 备用方案：如果需要的话，可以测试CUDA硬件解码（但不推荐用于视频裁剪）
                if 'cuda' in supported_hwaccels:
                    logger.debug("测试CUDA硬件解码（仅用于非裁剪场景）")
                    test_cmd = subprocess.run([
                        "ffmpeg", "-hide_banner", "-loglevel", "error",
                        "-hwaccel", "cuda", "-hwaccel_output_format", "cuda",
                        "-f", "lavfi", "-i", "testsrc=duration=0.1:size=640x480:rate=30",
                        "-c:v", "h264_nvenc", "-preset", "medium", "-cq", "23",
                        "-pix_fmt", "yuv420p", "-f", "null", "-"
                    ], stderr=subprocess.PIPE, stdout=subprocess.PIPE, 
                       encoding='utf-8', text=True, check=False)
                    
                    if test_cmd.returncode == 0:
                        _FFMPEG_HW_ACCEL_INFO["available"] = True
                        _FFMPEG_HW_ACCEL_INFO["type"] = "cuda"  # 保留cuda类型用于特殊场景
                        _FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_nvenc"
                        _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "cuda", "-hwaccel_output_format", "cuda"]
                        _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = True
                        _FFMPEG_HW_ACCEL_INFO["message"] = "CUDA+NVENC（限特殊场景使用）"
                        _FFMPEG_HW_ACCEL_INFO["fallback_available"] = True
                        _FFMPEG_HW_ACCEL_INFO["fallback_encoder"] = "h264_nvenc"
                        logger.info("✓ CUDA+NVENC硬件加速测试成功（备用方案）")
                        return
                        
        except Exception as e:
            logger.debug(f"NVIDIA硬件加速测试失败: {str(e)}")
    
    # 2. 检测AMD硬件加速
    if 'amd' in gpu_info.lower() or 'radeon' in gpu_info.lower():
        logger.info("检测到AMD显卡，开始测试硬件加速")
        
        # 检查AMF编码器是否可用
        try:
            encoders_cmd = subprocess.run(
                ["ffmpeg", "-hide_banner", "-encoders"],
                stderr=subprocess.PIPE, stdout=subprocess.PIPE, 
                encoding='utf-8', text=True, check=False
            )
            has_amf = "h264_amf" in encoders_cmd.stdout.lower()
            logger.debug(f"AMF编码器检测结果: {'可用' if has_amf else '不可用'}")
            
            if has_amf:
                # 测试AMF编码器
                logger.debug("测试AMF编码器")
                test_cmd = subprocess.run([
                    "ffmpeg", "-hide_banner", "-loglevel", "error",
                    "-f", "lavfi", "-i", "testsrc=duration=0.1:size=640x480:rate=30",
                    "-c:v", "h264_amf", "-quality", "balanced", "-qp_i", "23",
                    "-pix_fmt", "yuv420p", "-f", "null", "-"
                ], stderr=subprocess.PIPE, stdout=subprocess.PIPE, 
                   encoding='utf-8', text=True, check=False)
                
                if test_cmd.returncode == 0:
                    _FFMPEG_HW_ACCEL_INFO["available"] = True
                    _FFMPEG_HW_ACCEL_INFO["type"] = "amf"
                    _FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_amf"
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = []
                    _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = True
                    _FFMPEG_HW_ACCEL_INFO["message"] = "AMD AMF编码器"
                    logger.info("✓ AMD AMF编码器测试成功")
                    return
                    
        except Exception as e:
            logger.debug(f"AMD硬件加速测试失败: {str(e)}")
    
    # 3. 检测Intel硬件加速
    if 'intel' in gpu_info.lower() and 'qsv' in supported_hwaccels:
        logger.info("检测到Intel显卡，开始测试硬件加速")
        
        try:
            encoders_cmd = subprocess.run(
                ["ffmpeg", "-hide_banner", "-encoders"],
                stderr=subprocess.PIPE, stdout=subprocess.PIPE, 
                encoding='utf-8', text=True, check=False
            )
            has_qsv = "h264_qsv" in encoders_cmd.stdout.lower()
            logger.debug(f"QSV编码器检测结果: {'可用' if has_qsv else '不可用'}")
            
            if has_qsv:
                # 测试QSV编码器
                logger.debug("测试QSV编码器")
                test_cmd = subprocess.run([
                    "ffmpeg", "-hide_banner", "-loglevel", "error",
                    "-f", "lavfi", "-i", "testsrc=duration=0.1:size=640x480:rate=30",
                    "-c:v", "h264_qsv", "-preset", "medium", "-global_quality", "23",
                    "-pix_fmt", "yuv420p", "-f", "null", "-"
                ], stderr=subprocess.PIPE, stdout=subprocess.PIPE, 
                   encoding='utf-8', text=True, check=False)
                
                if test_cmd.returncode == 0:
                    _FFMPEG_HW_ACCEL_INFO["available"] = True
                    _FFMPEG_HW_ACCEL_INFO["type"] = "qsv"
                    _FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_qsv"
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = []
                    _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = not is_intel_integrated
                    _FFMPEG_HW_ACCEL_INFO["message"] = "Intel QSV编码器"
                    logger.info("✓ Intel QSV编码器测试成功")
                    return
                    
        except Exception as e:
            logger.debug(f"Intel硬件加速测试失败: {str(e)}")
    
    # 4. 如果没有硬件编码器，使用软件编码
    logger.info("未检测到可用的硬件编码器，使用软件编码")
    _FFMPEG_HW_ACCEL_INFO["available"] = False
    _FFMPEG_HW_ACCEL_INFO["type"] = "software"
    _FFMPEG_HW_ACCEL_INFO["encoder"] = "libx264"
    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = []
    _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = False
    _FFMPEG_HW_ACCEL_INFO["message"] = "使用软件编码"


def _detect_linux_acceleration(supported_hwaccels: str) -> None:
    """
    检测Linux系统的硬件加速

    Args:
        supported_hwaccels: FFmpeg支持的硬件加速器列表
    """
    global _FFMPEG_HW_ACCEL_INFO

    # 获取Linux显卡信息
    gpu_info = _get_linux_gpu_info()
    is_nvidia = 'nvidia' in gpu_info.lower()
    is_intel = 'intel' in gpu_info.lower()
    is_amd = 'amd' in gpu_info.lower() or 'radeon' in gpu_info.lower()

    # 检测NVIDIA CUDA支持
    if 'cuda' in supported_hwaccels and is_nvidia:
        try:
            test_cmd = subprocess.run(
                ["ffmpeg", "-hwaccel", "cuda", "-i", "/dev/null", "-f", "null", "-"],
                stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
            )
            if test_cmd.returncode == 0:
                _FFMPEG_HW_ACCEL_INFO["available"] = True
                _FFMPEG_HW_ACCEL_INFO["type"] = "cuda"
                _FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_nvenc"
                _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "cuda"]
                _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = True
                return
        except Exception as e:
            logger.debug(f"测试CUDA失败: {str(e)}")

    # 检测VAAPI支持
    if 'vaapi' in supported_hwaccels:
        # 检查是否存在渲染设备
        render_devices = ['/dev/dri/renderD128', '/dev/dri/renderD129']
        render_device = None
        for device in render_devices:
            if os.path.exists(device):
                render_device = device
                break

        if render_device:
            try:
                test_cmd = subprocess.run(
                    ["ffmpeg", "-hwaccel", "vaapi", "-vaapi_device", render_device,
                     "-i", "/dev/null", "-f", "null", "-"],
                    stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
                )
                if test_cmd.returncode == 0:
                    _FFMPEG_HW_ACCEL_INFO["available"] = True
                    _FFMPEG_HW_ACCEL_INFO["type"] = "vaapi"
                    _FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_vaapi"
                    _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "vaapi", "-vaapi_device", render_device]
                    # 根据显卡类型判断是否为独立显卡
                    _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = is_nvidia or (is_amd and not is_intel)
                    return
            except Exception as e:
                logger.debug(f"测试VAAPI失败: {str(e)}")

    # 检测Intel QSV支持
    if 'qsv' in supported_hwaccels and is_intel:
        try:
            test_cmd = subprocess.run(
                ["ffmpeg", "-hwaccel", "qsv", "-i", "/dev/null", "-f", "null", "-"],
                stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
            )
            if test_cmd.returncode == 0:
                _FFMPEG_HW_ACCEL_INFO["available"] = True
                _FFMPEG_HW_ACCEL_INFO["type"] = "qsv"
                _FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_qsv"
                _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "qsv"]
                _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = False  # Intel QSV通常是集成GPU
                return
        except Exception as e:
            logger.debug(f"测试QSV失败: {str(e)}")

    _FFMPEG_HW_ACCEL_INFO["message"] = f"Linux系统未检测到可用的硬件加速，显卡信息: {gpu_info}"


def _get_windows_gpu_info() -> str:
    """
    获取Windows系统的显卡信息

    Returns:
        str: 显卡信息字符串
    """
    try:
        # 使用PowerShell获取更可靠的显卡信息，并使用UTF-8编码
        gpu_info = subprocess.run(
            ['powershell', '-Command', "Get-WmiObject Win32_VideoController | Select-Object Name | Format-List"],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', text=True, check=False
        )

        # 如果PowerShell失败，尝试使用wmic
        if not gpu_info.stdout.strip():
            gpu_info = subprocess.run(
                ['wmic', 'path', 'win32_VideoController', 'get', 'name'],
                stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', text=True, check=False
            )

        # 记录详细的显卡信息以便调试
        logger.debug(f"Windows显卡信息: {gpu_info.stdout}")
        return gpu_info.stdout
    except Exception as e:
        logger.warning(f"获取Windows显卡信息失败: {str(e)}")
        return "Unknown GPU"


def _get_linux_gpu_info() -> str:
    """
    获取Linux系统的显卡信息

    Returns:
        str: 显卡信息字符串
    """
    try:
        # 尝试使用lspci命令
        gpu_info = subprocess.run(
            ['lspci', '-v', '-nn', '|', 'grep', '-i', 'vga\\|display'],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=False
        )
        if gpu_info.stdout:
            return gpu_info.stdout

        # 如果lspci命令失败，尝试使用glxinfo
        gpu_info = subprocess.run(
            ['glxinfo', '|', 'grep', '-i', 'vendor\\|renderer'],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True, check=False
        )
        if gpu_info.stdout:
            return gpu_info.stdout

        return "Unknown GPU"
    except Exception as e:
        logger.warning(f"获取Linux显卡信息失败: {str(e)}")
        return "Unknown GPU"


def get_ffmpeg_hwaccel_args() -> List[str]:
    """
    获取FFmpeg硬件加速参数

    Returns:
        List[str]: FFmpeg硬件加速参数列表
    """
    # 如果还没有检测过，先进行检测
    if _FFMPEG_HW_ACCEL_INFO["type"] is None:
        detect_hardware_acceleration()

    return _FFMPEG_HW_ACCEL_INFO["hwaccel_args"]


def get_ffmpeg_hwaccel_type() -> Optional[str]:
    """
    获取FFmpeg硬件加速类型

    Returns:
        Optional[str]: 硬件加速类型，如果不支持则返回None
    """
    # 如果还没有检测过，先进行检测
    if _FFMPEG_HW_ACCEL_INFO["type"] is None:
        detect_hardware_acceleration()

    return _FFMPEG_HW_ACCEL_INFO["type"] if _FFMPEG_HW_ACCEL_INFO["available"] else None


def get_ffmpeg_hwaccel_encoder() -> Optional[str]:
    """
    获取FFmpeg硬件加速编码器

    Returns:
        Optional[str]: 硬件加速编码器，如果不支持则返回None
    """
    # 如果还没有检测过，先进行检测
    if _FFMPEG_HW_ACCEL_INFO["type"] is None:
        detect_hardware_acceleration()

    return _FFMPEG_HW_ACCEL_INFO["encoder"] if _FFMPEG_HW_ACCEL_INFO["available"] else None


def get_ffmpeg_hwaccel_info() -> Dict[str, Union[bool, str, List[str], None]]:
    """
    获取FFmpeg硬件加速信息

    Returns:
        Dict: 包含硬件加速信息的字典
    """
    # 如果还没有检测过，先进行检测
    if _FFMPEG_HW_ACCEL_INFO["type"] is None:
        detect_hardware_acceleration()

    return _FFMPEG_HW_ACCEL_INFO


def is_ffmpeg_hwaccel_available() -> bool:
    """
    检查是否有可用的FFmpeg硬件加速

    Returns:
        bool: 如果有可用的硬件加速则返回True，否则返回False
    """
    # 如果还没有检测过，先进行检测
    if _FFMPEG_HW_ACCEL_INFO["type"] is None:
        detect_hardware_acceleration()

    return _FFMPEG_HW_ACCEL_INFO["available"]


def is_dedicated_gpu() -> bool:
    """
    检查是否使用独立显卡进行硬件加速

    Returns:
        bool: 如果使用独立显卡则返回True，否则返回False
    """
    # 如果还没有检测过，先进行检测
    if _FFMPEG_HW_ACCEL_INFO["type"] is None:
        detect_hardware_acceleration()

    return _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"]


def get_optimal_ffmpeg_encoder() -> str:
    """
    获取最优的FFmpeg编码器

    Returns:
        str: 编码器名称
    """
    # 如果还没有检测过，先进行检测
    if _FFMPEG_HW_ACCEL_INFO["type"] is None:
        detect_hardware_acceleration()

    if _FFMPEG_HW_ACCEL_INFO["available"]:
        return _FFMPEG_HW_ACCEL_INFO["encoder"]
    elif _FFMPEG_HW_ACCEL_INFO["fallback_available"]:
        return _FFMPEG_HW_ACCEL_INFO["fallback_encoder"]
    else:
        return "libx264"  # 默认软件编码器


def get_ffmpeg_command_with_hwaccel(input_path: str, output_path: str, **kwargs) -> List[str]:
    """
    生成带有硬件加速的FFmpeg命令

    Args:
        input_path: 输入文件路径
        output_path: 输出文件路径
        **kwargs: 其他FFmpeg参数

    Returns:
        List[str]: FFmpeg命令列表
    """
    # 如果还没有检测过，先进行检测
    if _FFMPEG_HW_ACCEL_INFO["type"] is None:
        detect_hardware_acceleration()

    cmd = ["ffmpeg", "-y"]

    # 添加硬件加速参数
    if _FFMPEG_HW_ACCEL_INFO["available"]:
        cmd.extend(_FFMPEG_HW_ACCEL_INFO["hwaccel_args"])

    # 添加输入文件
    cmd.extend(["-i", input_path])

    # 添加编码器
    encoder = get_optimal_ffmpeg_encoder()
    cmd.extend(["-c:v", encoder])

    # 添加其他参数
    for key, value in kwargs.items():
        if key.startswith("_"):  # 跳过内部参数
            continue
        if isinstance(value, list):
            cmd.extend(value)
        else:
            cmd.extend([f"-{key}", str(value)])

    # 添加输出文件
    cmd.append(output_path)

    return cmd


def test_ffmpeg_compatibility() -> Dict[str, any]:
    """
    测试FFmpeg兼容性并返回详细报告

    Returns:
        Dict: 兼容性测试报告
    """
    report = {
        "ffmpeg_installed": False,
        "platform": platform.system().lower(),
        "gpu_vendor": "unknown",
        "hardware_acceleration": {
            "available": False,
            "type": None,
            "encoder": None,
            "tested_methods": []
        },
        "software_fallback": {
            "available": False,
            "encoder": "libx264"
        },
        "recommendations": []
    }

    # 检查FFmpeg安装
    report["ffmpeg_installed"] = check_ffmpeg_installation()
    if not report["ffmpeg_installed"]:
        report["recommendations"].append("请安装FFmpeg并确保其在系统PATH中")
        return report

    # 检测硬件加速
    hwaccel_info = detect_hardware_acceleration()
    report["gpu_vendor"] = hwaccel_info.get("gpu_vendor", "unknown")
    report["hardware_acceleration"]["available"] = hwaccel_info.get("available", False)
    report["hardware_acceleration"]["type"] = hwaccel_info.get("type")
    report["hardware_acceleration"]["encoder"] = hwaccel_info.get("encoder")
    report["hardware_acceleration"]["tested_methods"] = hwaccel_info.get("tested_methods", [])

    # 检查软件备用方案
    report["software_fallback"]["available"] = hwaccel_info.get("fallback_available", True)
    report["software_fallback"]["encoder"] = hwaccel_info.get("fallback_encoder", "libx264")

    # 生成建议
    if not report["hardware_acceleration"]["available"]:
        if report["gpu_vendor"] == "nvidia":
            report["recommendations"].append("建议安装NVIDIA驱动和CUDA工具包以启用硬件加速")
        elif report["gpu_vendor"] == "amd":
            report["recommendations"].append("AMD显卡硬件加速支持有限，建议使用软件编码")
        elif report["gpu_vendor"] == "intel":
            report["recommendations"].append("建议更新Intel显卡驱动以启用QSV硬件加速")
        else:
            report["recommendations"].append("未检测到支持的GPU，将使用软件编码")

    return report


def force_software_encoding() -> None:
    """
    强制使用软件编码，禁用硬件加速
    """
    global _FFMPEG_HW_ACCEL_INFO

    _FFMPEG_HW_ACCEL_INFO.update({
        "available": False,
        "type": "software",
        "encoder": "libx264",
        "hwaccel_args": [],
        "message": "强制使用软件编码",
        "is_dedicated_gpu": False,
        "fallback_available": True,
        "fallback_encoder": "libx264"
    })

    logger.info("已强制切换到软件编码模式")


def reset_hwaccel_detection() -> None:
    """
    重置硬件加速检测结果，强制重新检测
    
    这在以下情况下很有用：
    1. 驱动程序更新后
    2. 系统配置改变后
    3. 需要重新测试硬件加速时
    """
    global _FFMPEG_HW_ACCEL_INFO
    
    logger.info("🔄 重置硬件加速检测，将重新检测...")
    _FFMPEG_HW_ACCEL_INFO = {
        "available": False,
        "type": None,
        "encoder": None,
        "hwaccel_args": [],
        "message": "",
        "is_dedicated_gpu": False,
        "fallback_available": False,
        "fallback_encoder": None,
        "platform": None,
        "gpu_vendor": None,
        "tested_methods": []
    }


def test_nvenc_directly() -> bool:
    """
    直接测试NVENC编码器是否可用（无硬件解码）
    
    Returns:
        bool: NVENC是否可用
    """
    try:
        logger.info("🧪 直接测试NVENC编码器...")
        
        # 测试纯NVENC编码器
        test_cmd = subprocess.run([
            "ffmpeg", "-hide_banner", "-loglevel", "error",
            "-f", "lavfi", "-i", "testsrc=duration=1:size=640x480:rate=30",
            "-c:v", "h264_nvenc", "-preset", "fast", "-profile:v", "main",
            "-pix_fmt", "yuv420p", "-t", "1", "-f", "null", "-"
        ], stderr=subprocess.PIPE, stdout=subprocess.PIPE, 
           encoding='utf-8', text=True, check=False)
        
        if test_cmd.returncode == 0:
            logger.info("✅ NVENC编码器测试成功！")
            return True
        else:
            logger.warning(f"❌ NVENC编码器测试失败: {test_cmd.stderr}")
            return False
            
    except Exception as e:
        logger.error(f"NVENC测试异常: {str(e)}")
        return False


def force_use_nvenc_pure() -> None:
    """
    强制使用纯NVENC编码器模式
    
    当自动检测失败但你确定NVENC可用时使用
    """
    global _FFMPEG_HW_ACCEL_INFO
    
    logger.info("🎯 强制启用纯NVENC编码器模式...")
    
    # 先测试NVENC是否真的可用
    if test_nvenc_directly():
        _FFMPEG_HW_ACCEL_INFO["available"] = True
        _FFMPEG_HW_ACCEL_INFO["type"] = "nvenc_pure"
        _FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_nvenc"
        _FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = []
        _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = True
        _FFMPEG_HW_ACCEL_INFO["message"] = "强制启用纯NVENC编码器"
        logger.info("✅ 已强制启用纯NVENC编码器模式")
    else:
        logger.error("❌ NVENC编码器不可用，无法强制启用")


def get_hwaccel_status() -> Dict[str, any]:
    """
    获取当前硬件加速状态的详细信息
    
    Returns:
        Dict: 硬件加速状态信息
    """
    hwaccel_info = get_ffmpeg_hwaccel_info()
    
    status = {
        "available": hwaccel_info.get("available", False),
        "type": hwaccel_info.get("type", "software"),
        "encoder": hwaccel_info.get("encoder", "libx264"),
        "message": hwaccel_info.get("message", ""),
        "is_dedicated_gpu": hwaccel_info.get("is_dedicated_gpu", False),
        "platform": platform.system(),
        "gpu_vendor": detect_gpu_vendor(),
        "ffmpeg_available": check_ffmpeg_installation()
    }
    
    return status


# 自动重置检测（在模块导入时执行）
def _auto_reset_on_import():
    """模块导入时自动重置硬件加速检测"""
    try:
        # 只在平台真正改变时才重置，而不是初始化时
        current_platform = platform.system()
        cached_platform = _FFMPEG_HW_ACCEL_INFO.get("platform")

        # 只有当已经有缓存的平台信息，且平台改变了，才需要重置
        if cached_platform is not None and cached_platform != current_platform:
            reset_hwaccel_detection()
    except Exception as e:
        logger.debug(f"自动重置检测失败: {str(e)}")

# 执行自动重置
_auto_reset_on_import()
