# ESP32 固件烧录工具
# 支持选择文件并自动下载到 ESP32

param(
    [Parameter(Mandatory=$false)]
    [string]$BootloaderPath = "",
    
    [Parameter(Mandatory=$false)]
    [string]$PartitionsPath = "",
    
    [Parameter(Mandatory=$false)]
    [string]$FirmwarePath = "",
    
    [Parameter(Mandatory=$false)]
    [string]$Port = "",
    
    [Parameter(Mandatory=$false)]
    [switch]$AutoFind = $false,
    
    [Parameter(Mandatory=$false)]
    [switch]$NoConfirm = $false,
    
    [Parameter(Mandatory=$false)]
    [switch]$ShowDebug = $false
)

$ErrorActionPreference = "Stop"

# 设置控制台编码
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

# Debug 输出函数
function Write-DebugInfo {
    param([string]$Message)
    if ($ShowDebug) {
        Write-Host "[DEBUG] $Message" -ForegroundColor DarkGray
    }
}

Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "  ESP32 固件烧录工具" -ForegroundColor Cyan
Write-Host "  模拟 VSCode/PlatformIO 下载过程" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""

Write-DebugInfo "脚本启动时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-DebugInfo "PowerShell 版本: $($PSVersionTable.PSVersion)"
Write-DebugInfo "工作目录: $PWD"
Write-DebugInfo "脚本目录: $(Split-Path -Parent $MyInvocation.MyCommand.Path)"
Write-DebugInfo "参数: BootloaderPath=$BootloaderPath, PartitionsPath=$PartitionsPath, FirmwarePath=$FirmwarePath, Port=$Port, AutoFind=$AutoFind, NoConfirm=$NoConfirm, ShowDebug=$ShowDebug"
Write-Host ""

# 获取脚本所在目录
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
Write-DebugInfo "脚本目录: $scriptDir"

# 自动查找文件
if ($AutoFind -or (-not $BootloaderPath -and -not $PartitionsPath -and -not $FirmwarePath)) {
    Write-Host "正在自动查找固件文件..." -ForegroundColor Cyan
    Write-DebugInfo "开始自动查找文件..."
    
    # 在当前目录和脚本目录查找
    $searchPaths = @($scriptDir, $PWD, "$env:USERPROFILE\Desktop", "$env:USERPROFILE\Downloads")
    Write-DebugInfo "搜索路径: $($searchPaths -join ', ')"
    
    foreach ($searchPath in $searchPaths) {
        Write-DebugInfo "搜索路径: $searchPath"
        if (Test-Path $searchPath) {
            # 查找 bootloader
            if (-not $BootloaderPath) {
                Write-DebugInfo "查找 bootloader 文件..."
                $bootloader = Get-ChildItem -Path $searchPath -Filter "bootloader*.bin" -ErrorAction SilentlyContinue | 
                    Where-Object { $_.Name -like "*qio*80m*" } | Select-Object -First 1
                if ($bootloader) {
                    $BootloaderPath = $bootloader.FullName
                    Write-Host "  找到 Bootloader: $BootloaderPath" -ForegroundColor Green
                    Write-DebugInfo "找到 bootloader: $BootloaderPath (大小: $([math]::Round($bootloader.Length/1KB, 2)) KB)"
                }
            }
            
            # 查找 partitions
            if (-not $PartitionsPath) {
                Write-DebugInfo "查找 partitions 文件..."
                $partitions = Get-ChildItem -Path $searchPath -Filter "partitions.bin" -ErrorAction SilentlyContinue | Select-Object -First 1
                if ($partitions) {
                    $PartitionsPath = $partitions.FullName
                    Write-Host "  找到 Partitions: $PartitionsPath" -ForegroundColor Green
                    Write-DebugInfo "找到 partitions: $PartitionsPath (大小: $([math]::Round($partitions.Length/1KB, 2)) KB)"
                }
            }
            
            # 查找 firmware
            if (-not $FirmwarePath) {
                Write-DebugInfo "查找 firmware 文件..."
                $firmware = Get-ChildItem -Path $searchPath -Filter "firmware.bin" -ErrorAction SilentlyContinue | Select-Object -First 1
                if ($firmware) {
                    $FirmwarePath = $firmware.FullName
                    Write-Host "  找到 Firmware: $FirmwarePath" -ForegroundColor Green
                    Write-DebugInfo "找到 firmware: $FirmwarePath (大小: $([math]::Round($firmware.Length/1KB, 2)) KB)"
                }
            }
        } else {
            Write-DebugInfo "路径不存在: $searchPath"
        }
    }
    Write-Host ""
}

# 验证文件是否存在
Write-DebugInfo "开始验证文件..."
$filesToFlash = @()

if ($BootloaderPath -and (Test-Path $BootloaderPath)) {
    $fileInfo = Get-Item $BootloaderPath
    $filesToFlash += @{
        Path = $BootloaderPath
        Address = "0x1000"
        Name = "Bootloader"
    }
    Write-Host "✓ Bootloader: $BootloaderPath" -ForegroundColor Green
    $bootloaderDate = $fileInfo.LastWriteTime
    $bootloaderAge = (Get-Date) - $bootloaderDate
    Write-DebugInfo "Bootloader 文件验证通过: 路径=$BootloaderPath, 大小=$([math]::Round($fileInfo.Length/1KB, 2)) KB, 修改时间=$bootloaderDate"
    
    # 检查 bootloader 文件是否过旧（超过6个月）
    if ($bootloaderAge.TotalDays -gt 180) {
        Write-Host "  ⚠ 警告: Bootloader 文件较旧 ($([math]::Round($bootloaderAge.TotalDays)) 天前)，可能与新固件不兼容" -ForegroundColor Yellow
        Write-Host "  建议: 使用最新的 bootloader.bin" -ForegroundColor Yellow
    }
} else {
    Write-Host "⚠ Bootloader: 未找到（将跳过）" -ForegroundColor Yellow
    Write-DebugInfo "Bootloader 未提供或文件不存在: $BootloaderPath"
}

if ($PartitionsPath -and (Test-Path $PartitionsPath)) {
    $fileInfo = Get-Item $PartitionsPath
    $filesToFlash += @{
        Path = $PartitionsPath
        Address = "0x8000"
        Name = "Partitions"
    }
    Write-Host "✓ Partitions: $PartitionsPath" -ForegroundColor Green
    Write-DebugInfo "Partitions 文件验证通过: 路径=$PartitionsPath, 大小=$([math]::Round($fileInfo.Length/1KB, 2)) KB, 修改时间=$($fileInfo.LastWriteTime)"
} else {
    Write-Host "✗ Partitions: 未找到（必需）" -ForegroundColor Red
    Write-Host "请指定 partitions.bin 文件路径" -ForegroundColor Yellow
    Write-DebugInfo "错误: Partitions 文件未找到: $PartitionsPath"
    exit 1
}

if ($FirmwarePath -and (Test-Path $FirmwarePath)) {
    $fileInfo = Get-Item $FirmwarePath
    $filesToFlash += @{
        Path = $FirmwarePath
        Address = "0x10000"
        Name = "Firmware"
    }
    Write-Host "✓ Firmware: $FirmwarePath" -ForegroundColor Green
    Write-DebugInfo "Firmware 文件验证通过: 路径=$FirmwarePath, 大小=$([math]::Round($fileInfo.Length/1KB, 2)) KB, 修改时间=$($fileInfo.LastWriteTime)"
} else {
    Write-Host "✗ Firmware: 未找到（必需）" -ForegroundColor Red
    Write-Host "请指定 firmware.bin 文件路径" -ForegroundColor Yellow
    Write-DebugInfo "错误: Firmware 文件未找到: $FirmwarePath"
    exit 1
}

Write-DebugInfo "共找到 $($filesToFlash.Count) 个文件需要下载"
Write-Host ""

# 查找 esptool（优先使用独立的 esptool.exe v4.5.1）
Write-Host "查找 esptool..." -ForegroundColor Cyan
Write-DebugInfo "开始查找 esptool..."
$esptool = $null
$usePio = $false
$useStandaloneExe = $false

$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$standaloneEspTool = Join-Path $scriptDir "esptool.exe"
Write-DebugInfo "检查独立 esptool.exe: $standaloneEspTool"
$standaloneEspToolExists = Test-Path $standaloneEspTool

# 方法1: 优先使用独立的 esptool.exe (v4.5.1)
if ($standaloneEspToolExists) {
    $esptool = $standaloneEspTool
    $useStandaloneExe = $true
    Write-Host "  找到: esptool.exe (独立版本 v4.5.1，优先使用)" -ForegroundColor Green
    Write-DebugInfo "使用独立 esptool.exe (优先): $esptool"
} else {
    Write-DebugInfo "独立 esptool.exe 不存在，继续查找其他版本"
}

# 方法2: 从 PlatformIO 包中查找
if (-not $esptool) {
    $pioPackages = "$env:USERPROFILE\.platformio\packages"
    Write-DebugInfo "检查 PlatformIO 包目录: $pioPackages"
    if (Test-Path $pioPackages) {
        Write-DebugInfo "PlatformIO 包目录存在，搜索 esptool..."
        $esptoolDirs = Get-ChildItem -Path $pioPackages -Filter "*esptool*" -Directory -ErrorAction SilentlyContinue
        Write-DebugInfo "找到 $($esptoolDirs.Count) 个 esptool 相关目录"
        foreach ($dir in $esptoolDirs) {
            $esptoolPath = Join-Path $dir.FullName "esptool.py"
            Write-DebugInfo "检查: $esptoolPath"
            if (Test-Path $esptoolPath) {
                $esptool = $esptoolPath
                Write-Host "  找到: $esptool" -ForegroundColor Green
                Write-DebugInfo "找到 PlatformIO esptool: $esptool"
                break
            }
        }
    } else {
        Write-DebugInfo "PlatformIO 包目录不存在: $pioPackages"
    }
}

# 方法3: 查找系统 Python esptool
if (-not $esptool) {
    Write-DebugInfo "查找系统 Python esptool..."
    $pythonEspTool = Get-Command esptool.py -ErrorAction SilentlyContinue
    if ($pythonEspTool) {
        $esptool = "esptool.py"
        Write-Host "  找到系统 esptool.py" -ForegroundColor Green
        Write-DebugInfo "找到系统 esptool.py: $($pythonEspTool.Source)"
    } else {
        Write-DebugInfo "系统 esptool.py 未找到"
    }
}

# 方法4: 使用 PlatformIO CLI
if (-not $esptool) {
    Write-DebugInfo "查找 PlatformIO CLI..."
    $pioCmd = Get-Command pio -ErrorAction SilentlyContinue
    if ($pioCmd) {
        Write-Host "  使用 PlatformIO CLI" -ForegroundColor Green
        Write-DebugInfo "找到 PlatformIO CLI: $($pioCmd.Source)"
        $usePio = $true
        
        # 查找 PlatformIO 的 esptool
        Write-DebugInfo "在 PlatformIO 包中查找 esptool.py..."
        $pioEspTool = Get-ChildItem -Path "$pioPackages\tool-esptoolpy*" -Recurse -Filter "esptool.py" -ErrorAction SilentlyContinue | Select-Object -First 1
        if ($pioEspTool) {
            $esptool = $pioEspTool.FullName
            Write-DebugInfo "找到 PlatformIO esptool: $esptool"
        }
    } else {
        Write-DebugInfo "PlatformIO CLI 未找到"
    }
}

# 如果所有方法都失败
if (-not $esptool) {
    Write-Host "✗ 未找到 esptool" -ForegroundColor Red
    Write-Host "请选择以下方案之一：" -ForegroundColor Yellow
    Write-Host "  1. 安装 PlatformIO 或 Python esptool" -ForegroundColor White
    Write-Host "  2. 运行 build_standalone.ps1 生成独立的 esptool.exe" -ForegroundColor White
    Write-DebugInfo "错误: 未找到任何可用的 esptool"
    exit 1
}

Write-DebugInfo "最终使用的工具: esptool=$esptool, usePio=$usePio, useStandaloneExe=$useStandaloneExe"
if ($useStandaloneExe) {
    Write-DebugInfo "使用独立 esptool.exe，无需 Python"
}
Write-Host ""

# 检测串口
if ([string]::IsNullOrWhiteSpace($Port)) {
    Write-Host "检测可用串口..." -ForegroundColor Cyan
    Write-DebugInfo "开始检测串口..."
    try {
        $ports = [System.IO.Ports.SerialPort]::GetPortNames()
        Write-DebugInfo "检测到 $($ports.Count) 个串口: $($ports -join ', ')"
        if ($ports.Count -eq 0) {
            Write-Host "✗ 未找到可用串口" -ForegroundColor Red
            Write-Host "请确保 ESP32 已连接到电脑" -ForegroundColor Yellow
            Write-DebugInfo "错误: 未找到可用串口"
            exit 1
        }
        
        Write-Host "可用串口:" -ForegroundColor Green
        for ($i = 0; $i -lt $ports.Count; $i++) {
            Write-Host "  [$i] $($ports[$i])" -ForegroundColor White
        }
        
        if (-not $NoConfirm) {
            $selection = Read-Host "`n请选择串口 (0-$($ports.Count-1))"
            $Port = $ports[[int]$selection]
            Write-DebugInfo "用户选择串口: [$selection] $Port"
        } else {
            $Port = $ports[0]
            Write-DebugInfo "自动选择第一个串口: $Port"
        }
    }
    catch {
        Write-Host "无法检测串口，请手动指定: -Port COMx" -ForegroundColor Yellow
        Write-DebugInfo "错误: 串口检测失败 - $_"
        Write-DebugInfo "错误堆栈: $($_.ScriptStackTrace)"
        exit 1
    }
}

Write-Host "使用串口: $Port" -ForegroundColor Green
Write-DebugInfo "最终使用的串口: $Port"
Write-Host ""

# 显示将要下载的文件
Write-Host "准备下载以下文件:" -ForegroundColor Cyan
foreach ($file in $filesToFlash) {
    $size = [math]::Round((Get-Item $file.Path).Length / 1KB, 2)
    Write-Host "  - $($file.Name): $($file.Address) ($size KB)" -ForegroundColor White
}
Write-Host ""


# 确认（如果不需要交互则跳过）
if (-not $NoConfirm) {
    Write-Host "提示: 工具将通过串口 RTS/DTR 信号自动复位 ESP32" -ForegroundColor Cyan
    Write-Host "      无需手动按 BOOT 键，自动进入下载模式" -ForegroundColor Cyan
    Write-Host ""
    $confirm = Read-Host "准备好后按 Enter 开始下载（或输入 q 退出）"
    if ($confirm -eq "q" -or $confirm -eq "Q") {
        Write-Host "已取消" -ForegroundColor Yellow
        exit 0
    }
} else {
    Write-Host "提示: 工具将通过串口 RTS/DTR 信号自动复位 ESP32" -ForegroundColor Cyan
    Write-Host "      等待 1 秒后自动开始下载..." -ForegroundColor Cyan
    Start-Sleep -Seconds 1
}

Write-Host ""
Write-Host "开始下载..." -ForegroundColor Cyan
Write-Host ""

# 构建 esptool 命令
$flashCommands = @()

foreach ($file in $filesToFlash) {
    $flashCommands += "--flash_mode", "qio"
    $flashCommands += "--flash_freq", "80m"
    $flashCommands += "--flash_size", "4MB"
    $flashCommands += "write_flash"
    $flashCommands += $file.Address
    $flashCommands += $file.Path
}

# 使用 PlatformIO CLI（推荐方式，模拟 VSCode）
if ($usePio) {
    Write-Host "使用 PlatformIO esptool（模拟 VSCode 下载过程）..." -ForegroundColor Cyan
    Write-Host ""
    
    # PlatformIO 会自动处理所有文件
    $pioCmd = "pio run -e ESP32_WROOM_32_SOLO --target upload --upload-port $Port"
    
    # 但我们需要手动指定文件，所以使用 esptool 直接调用
    # 查找 PlatformIO 的 esptool
    $pioEspTool = Get-ChildItem -Path "$pioPackages\tool-esptoolpy*" -Recurse -Filter "esptool.py" -ErrorAction SilentlyContinue | Select-Object -First 1
    
    if ($pioEspTool) {
        Write-DebugInfo "使用 PlatformIO esptool: $($pioEspTool.FullName)"
        
        # 查找可用的 Python 命令，优先使用 python（更可靠）
        $pythonCmd = $null
        $pythonPath = $null
        
        # 优先尝试 python
        $pythonCmdObj = Get-Command python -ErrorAction SilentlyContinue
        if ($pythonCmdObj) {
            $pythonPath = $pythonCmdObj.Source
            $pythonCmd = "python"
            Write-DebugInfo "找到 Python: $pythonPath"
            
            # 验证 Python 是否可用
            try {
                $testResult = & python --version 2>&1
                Write-DebugInfo "Python 验证成功: $testResult"
            } catch {
                Write-DebugInfo "Python 验证失败: $_"
                $pythonCmd = $null
                $pythonPath = $null
            }
        }
        
        # 如果 python 不可用，尝试 python3
        if (-not $pythonCmd) {
            $python3Cmd = Get-Command python3 -ErrorAction SilentlyContinue
            if ($python3Cmd) {
                $pythonPath = $python3Cmd.Source
                $pythonCmd = "python3"
                Write-DebugInfo "找到 Python3: $pythonPath"
                
                # 验证 Python3 是否可用
                try {
                    $testResult = & python3 --version 2>&1
                    Write-DebugInfo "Python3 验证成功: $testResult"
                } catch {
                    Write-DebugInfo "Python3 验证失败: $_"
                    $pythonCmd = $null
                    $pythonPath = $null
                }
            }
        }
        
        # 如果都不可用，报错
        if (-not $pythonCmd) {
            Write-Host "✗ 未找到可用的 Python 命令" -ForegroundColor Red
            Write-Host "请确保已安装 Python 并添加到系统 PATH" -ForegroundColor Yellow
            Write-DebugInfo "错误: 未找到可用的 Python 命令"
            exit 1
        }
        
        Write-DebugInfo "使用 Python 命令: $pythonCmd (路径: $pythonPath)"
        
        # 使用 RTS/DTR 自动复位（模拟 VSCode/PlatformIO 方式）
        # --before default_reset: 通过 RTS/DTR 自动复位进入下载模式
        # --after hard_reset: 下载完成后硬复位
        $esptoolCmd = "$pythonCmd `"$($pioEspTool.FullName)`" --chip esp32 --port $Port --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode qio --flash_freq 80m --flash_size 4MB"
        
        Write-DebugInfo "使用自动复位模式（RTS/DTR），无需手动按 BOOT 键"
        Write-DebugInfo "esptool 将通过串口 RTS/DTR 信号自动控制 ESP32 进入下载模式"
        
        foreach ($file in $filesToFlash) {
            $esptoolCmd += " $($file.Address) `"$($file.Path)`""
            Write-DebugInfo "添加文件到命令: $($file.Name) @ $($file.Address)"
        }
        
        Write-Host "执行命令:" -ForegroundColor Gray
        Write-Host $esptoolCmd -ForegroundColor DarkGray
        Write-DebugInfo "完整命令: $esptoolCmd"
        Write-Host ""
        
        try {
            Write-DebugInfo "开始执行 esptool 命令..."
            $startTime = Get-Date
            Invoke-Expression $esptoolCmd
            $endTime = Get-Date
            $duration = ($endTime - $startTime).TotalSeconds
            Write-DebugInfo "命令执行完成，耗时: $([math]::Round($duration, 2)) 秒，退出码: $LASTEXITCODE"
            
            if ($LASTEXITCODE -eq 0) {
                Write-Host ""
                Write-Host "✓ 下载成功！" -ForegroundColor Green
                Write-Host ""
                Write-Host "设备已自动重启..." -ForegroundColor Cyan
                Write-DebugInfo "下载成功完成，设备已通过 RTS/DTR 自动复位"
            } else {
                Write-Host ""
                Write-Host "✗ 下载失败 (退出码: $LASTEXITCODE)" -ForegroundColor Red
                Write-Host "请检查:" -ForegroundColor Yellow
                Write-Host "  1. 串口是否正确（当前: $Port）" -ForegroundColor White
                Write-Host "  2. 串口是否被其他程序占用" -ForegroundColor White
                Write-Host "  3. USB 线连接是否正常" -ForegroundColor White
                Write-Host "  4. 串口芯片是否支持 RTS/DTR 控制" -ForegroundColor White
                Write-DebugInfo "下载失败，退出码: $LASTEXITCODE"
                Write-DebugInfo "注意: 如果串口芯片不支持 RTS/DTR，可能需要手动进入下载模式"
                exit 1
            }
        }
        catch {
            Write-Host ""
            Write-Host "✗ 下载失败: $_" -ForegroundColor Red
            Write-DebugInfo "异常信息: $_"
            Write-DebugInfo "异常类型: $($_.Exception.GetType().FullName)"
            Write-DebugInfo "错误堆栈: $($_.ScriptStackTrace)"
            exit 1
        }
    } else {
        Write-Host "✗ 无法找到 PlatformIO esptool" -ForegroundColor Red
        exit 1
    }
}
# 使用直接 esptool
elseif ($esptool) {
    Write-DebugInfo "使用直接 esptool: $esptool"
    
    # 如果使用独立exe，不需要Python
    if ($useStandaloneExe) {
        Write-DebugInfo "使用独立 esptool.exe，无需 Python"
        # 构建命令字符串用于显示，实际执行时使用参数数组
        $esptoolCmd = "`"$esptool`" --chip esp32 --port $Port --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode qio --flash_freq 80m --flash_size 4MB"
    } else {
        # 查找可用的 Python 命令，优先使用 python（更可靠）
        $pythonCmd = $null
        $pythonPath = $null
        
        # 优先尝试 python
        $pythonCmdObj = Get-Command python -ErrorAction SilentlyContinue
        if ($pythonCmdObj) {
            $pythonPath = $pythonCmdObj.Source
            $pythonCmd = "python"
            Write-DebugInfo "找到 Python: $pythonPath"
            
            # 验证 Python 是否可用
            try {
                $testResult = & python --version 2>&1
                Write-DebugInfo "Python 验证成功: $testResult"
            } catch {
                Write-DebugInfo "Python 验证失败: $_"
                $pythonCmd = $null
                $pythonPath = $null
            }
        }
        
        # 如果 python 不可用，尝试 python3
        if (-not $pythonCmd) {
            $python3Cmd = Get-Command python3 -ErrorAction SilentlyContinue
            if ($python3Cmd) {
                $pythonPath = $python3Cmd.Source
                $pythonCmd = "python3"
                Write-DebugInfo "找到 Python3: $pythonPath"
                
                # 验证 Python3 是否可用
                try {
                    $testResult = & python3 --version 2>&1
                    Write-DebugInfo "Python3 验证成功: $testResult"
                } catch {
                    Write-DebugInfo "Python3 验证失败: $_"
                    $pythonCmd = $null
                    $pythonPath = $null
                }
            }
        }
        
        # 如果都不可用，报错
        if (-not $pythonCmd) {
            Write-Host "✗ 未找到可用的 Python 命令" -ForegroundColor Red
            Write-Host "请确保已安装 Python 并添加到系统 PATH" -ForegroundColor Yellow
            Write-Host "或者使用打包的 esptool.exe（无需Python）" -ForegroundColor Yellow
            Write-DebugInfo "错误: 未找到可用的 Python 命令"
            exit 1
        }
        
        Write-DebugInfo "使用 Python 命令: $pythonCmd (路径: $pythonPath)"
        $esptoolCmd = "$pythonCmd `"$esptool`" --chip esp32 --port $Port --baud 921600 --before default_reset --after hard_reset"
    }
    
    # 构建 write_flash 命令
    if (-not $useStandaloneExe) {
        $esptoolCmd += " write_flash -z --flash_mode qio --flash_freq 80m --flash_size 4MB"
    }
    
    # 使用 RTS/DTR 自动复位（模拟 VSCode/PlatformIO 方式）
    # --before default_reset: 通过 RTS/DTR 自动复位进入下载模式
    # --after hard_reset: 下载完成后硬复位
    
    Write-DebugInfo "使用自动复位模式（RTS/DTR），无需手动按 BOOT 键"
    Write-DebugInfo "esptool 将通过串口 RTS/DTR 信号自动控制 ESP32 进入下载模式"
    
    if (-not $useStandaloneExe) {
        foreach ($file in $filesToFlash) {
            $esptoolCmd += " $($file.Address) `"$($file.Path)`""
            Write-DebugInfo "添加文件到命令: $($file.Name) @ $($file.Address)"
        }
    }
    
    try {
        Write-DebugInfo "开始执行 esptool 命令..."
        $startTime = Get-Date
        
        # 如果使用独立 exe，使用参数数组方式执行（更可靠）
        if ($useStandaloneExe) {
            # 构建参数数组
            $esptoolArgs = @(
                "--chip", "esp32",
                "--port", $Port,
                "--baud", "921600",
                "--before", "default_reset",
                "--after", "hard_reset",
                "write_flash",
                "-z",
                "--flash_mode", "qio",
                "--flash_freq", "80m",
                "--flash_size", "4MB"
            )
            
            # 添加文件参数
            foreach ($file in $filesToFlash) {
                $esptoolArgs += $file.Address
                $esptoolArgs += $file.Path
                Write-DebugInfo "添加文件到命令: $($file.Name) @ $($file.Address)"
            }
            
            # 显示完整命令（用于调试）
            $cmdDisplay = "`"$esptool`" " + ($esptoolArgs -join " ")
            Write-Host "执行命令:" -ForegroundColor Gray
            Write-Host $cmdDisplay -ForegroundColor DarkGray
            Write-DebugInfo "完整命令: $cmdDisplay"
            Write-DebugInfo "使用独立 exe 执行，参数数量: $($esptoolArgs.Count)"
            Write-Host ""
            
            & $esptool $esptoolArgs
        } else {
            # 使用字符串命令执行（Python + esptool.py）
            Invoke-Expression $esptoolCmd
        }
        
        $endTime = Get-Date
        $duration = ($endTime - $startTime).TotalSeconds
        Write-DebugInfo "命令执行完成，耗时: $([math]::Round($duration, 2)) 秒，退出码: $LASTEXITCODE"
        
        if ($LASTEXITCODE -eq 0) {
            Write-Host ""
            Write-Host "✓ 下载成功！" -ForegroundColor Green
            Write-Host ""
            Write-Host "设备已自动重启..." -ForegroundColor Cyan
            Write-DebugInfo "下载成功完成，设备已通过 RTS/DTR 自动复位"
        } else {
            Write-Host ""
            Write-Host "✗ 下载失败 (退出码: $LASTEXITCODE)" -ForegroundColor Red
            Write-Host "请检查:" -ForegroundColor Yellow
            Write-Host "  1. 串口是否正确（当前: $Port）" -ForegroundColor White
            Write-Host "  2. 串口是否被其他程序占用" -ForegroundColor White
            Write-Host "  3. USB 线连接是否正常" -ForegroundColor White
            Write-Host "  4. 串口芯片是否支持 RTS/DTR 控制" -ForegroundColor White
            Write-DebugInfo "下载失败，退出码: $LASTEXITCODE"
            Write-DebugInfo "注意: 如果串口芯片不支持 RTS/DTR，可能需要手动进入下载模式"
            exit 1
        }
    }
    catch {
        Write-Host ""
        Write-Host "✗ 下载失败: $_" -ForegroundColor Red
        Write-DebugInfo "异常信息: $_"
        Write-DebugInfo "异常类型: $($_.Exception.GetType().FullName)"
        Write-DebugInfo "错误堆栈: $($_.ScriptStackTrace)"
        exit 1
    }
}

Write-Host ""
Write-Host "完成！" -ForegroundColor Green
