param(
    [string]$Version = (Get-Date -Format "yyyyMMdd-HHmmss"),
    [string]$TargetInstance = "auto"
)

$ErrorActionPreference = "Stop"

$configPath = "D:\EPproject\LabelReplaceServer\deployment\config\deployment-config.json"
$stateFile = "D:\EPproject\LabelReplaceServer\deployment\instance_state.json"
$logFile = "D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log"

function Log {
    param([string]$Message, [string]$Level = "INFO")
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Level] [BluGreen] $Message"
    Write-Host $logEntry -ForegroundColor $(switch($Level) {
        "ERROR" { "Red" }
        "WARN" { "Yellow" }
        "INFO" { "Green" }
        "DEBUG" { "Gray" }
        default { "White" }
    })
    
    $logDirPath = Split-Path -Parent $logFile
    if (!(Test-Path $logDirPath)) {
        New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null
    }
    Add-Content -Path $logFile -Value $logEntry
}

function GetCurrentActiveInstance {
    if (Test-Path $stateFile) {
        try {
            $state = Get-Content $stateFile | ConvertFrom-Json
            return $state.activeInstance
        }
        catch {
            Log "读取状态文件失败，假设Blue为活跃实例" "WARN"
            return "blue"
        }
    }
    return "blue"
}

function SetActiveInstance {
    param([string]$Instance)
    
    $state = @{
        activeInstance = $Instance
        lastUpdate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        version = $Version
    }
    
    $logDirPath = Split-Path -Parent $stateFile
    if (!(Test-Path $logDirPath)) {
        New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null
    }
    
    $state | ConvertTo-Json | Set-Content -Path $stateFile -Force
    Log "已更新活跃实例为: $Instance (版本: $Version)" "INFO"
}

function StopInstance {
    param([string]$Instance, [int]$Port)
    
    Log "尝试停止 $Instance 实例 (端口: $Port)..." "INFO"
    
    try {
        $processes = Get-Process | Where-Object { 
            $_.ProcessName -eq "CONTROLLER" -and $_.Handles -gt 0 
        }
        
        foreach ($proc in $processes) {
            try {
                $proc | Stop-Process -Force -ErrorAction Stop
                Log "已停止进程 $($proc.Id)" "INFO"
            }
            catch {
                Log "停止进程失败: $_" "WARN"
            }
        }
        
        Start-Sleep -Seconds 2
        
        $stillRunning = Get-Process | Where-Object { 
            $_.ProcessName -eq "CONTROLLER" 
        }
        
        if ($stillRunning) {
            Log "警告: 仍有 CONTROLLER 进程运行" "WARN"
            return $false
        }
        
        Log "$Instance 实例已成功停止" "INFO"
        return $true
    }
    catch {
        Log "停止 $Instance 实例失败: $_" "ERROR"
        return $false
    }
}

function StartInstance {
    param([string]$Instance, [string]$Directory, [string]$Port, [string]$Environment)
    
    Log "启动 $Instance 实例 (端口: $Port, 目录: $Directory)..." "INFO"
    
    try {
        if (!(Test-Path $Directory)) {
            throw "目录不存在: $Directory"
        }
        
        $exePath = Join-Path $Directory "CONTROLLER.exe"
        if (!(Test-Path $exePath)) {
            throw "可执行文件不存在: $exePath"
        }
        
        $env:DEPLOYMENT_INSTANCE = if ($Instance -eq "green") { "green" } else { "blue" }
        $env:SHUTDOWN_TIMEOUT = "30"
        
        $process = Start-Process -FilePath $exePath -WorkingDirectory $Directory -PassThru -ErrorAction Stop
        
        Log "$Instance 实例已启动 (PID: $($process.Id))" "INFO"
        Start-Sleep -Seconds 2
        
        return $process.Id
    }
    catch {
        Log "启动 $Instance 实例失败: $_" "ERROR"
        throw
    }
}

try {
    Log "========================================" "INFO"
    Log "蓝绿部署流程开始" "INFO"
    Log "版本: $Version" "INFO"
    Log "========================================" "INFO"
    
    if (!(Test-Path $configPath)) {
        throw "配置文件不存在: $configPath"
    }
    
    $config = Get-Content $configPath | ConvertFrom-Json
    Log "已加载部署配置" "INFO"
    
    $currentActive = GetCurrentActiveInstance
    Log "当前活跃实例: $currentActive" "INFO"
    
    $nextInstance = if ($currentActive -eq "blue") { "green" } else { "blue" }
    
    if ($TargetInstance -ne "auto") {
        $nextInstance = $TargetInstance
        Log "使用指定的目标实例: $nextInstance" "INFO"
    }
    
    Log "下一个部署实例: $nextInstance" "INFO"
    
    $targetConfig = if ($nextInstance -eq "green") { 
        $config.GreenInstance 
    } else { 
        $config.BlueInstance 
    }
    
    Log "========== 第一步：编译和发布 ==========" "INFO"
    $publishScript = "D:\EPproject\LabelReplaceServer\deployment\scripts\build-and-publish.ps1"
    $buildResult = & $publishScript -OutputDirectory $targetConfig.Directory -Version $Version -Configuration Release
    
    if (!$buildResult) {
        throw "编译和发布失败"
    }
    
    Log "========== 第二步：启动新实例 ==========" "INFO"
    $newPid = StartInstance -Instance $nextInstance -Directory $targetConfig.Directory `
        -Port $targetConfig.Port -Environment $targetConfig.Environment
    
    Log "========== 第三步：健康检查 ==========" "INFO"
    $healthScript = "D:\EPproject\LabelReplaceServer\deployment\scripts\health-check.ps1"
    $healthResult = & $healthScript -Instance $nextInstance -Port $targetConfig.Port
    
    if (!$healthResult) {
        throw "新实例健康检查失败，中止部署"
    }
    
    Log "========== 第四步：切换流量 ==========" "INFO"
    SetActiveInstance -Instance $nextInstance
    
    Log "========== 第五步：停止旧实例 ==========" "INFO"
    $oldConfig = if ($currentActive -eq "green") { 
        $config.GreenInstance 
    } else { 
        $config.BlueInstance 
    }
    
    Log "等待旧实例优雅关闭 (超时: $($config.Deployment.GracefulShutdownTimeout) 秒)..." "INFO"
    Start-Sleep -Seconds 5
    
    StopInstance -Instance $currentActive -Port $oldConfig.Port
    
    Log "========================================" "INFO"
    Log "蓝绿部署完成！" "INFO"
    Log "新活跃实例: $nextInstance (端口: $($targetConfig.Port))" "INFO"
    Log "========================================" "INFO"
}
catch {
    Log "蓝绿部署失败: $_" "ERROR"
    Log "错误详情: $($_.Exception.StackTrace)" "ERROR"
    exit 1
}
