$ErrorActionPreference = "Stop"

function Add-CaseTitleAnnotations {
    param(
        [string]$Text,
        [hashtable]$TitleMap,
        [string]$OwnId
    )
    if ([string]::IsNullOrEmpty($Text)) {
        return $Text
    }
    $pattern = '(?<![A-Z0-9-])(?:A|B|F|S)-[A-Z0-9]+(?:-[A-Z0-9]+)*-\d{3}(?![A-Z0-9-])'
    return [regex]::Replace($Text, $pattern, {
        param($m)
        $code = $m.Value
        if ($code -eq $OwnId) {
            return $code
        }
        $nextIndex = $m.Index + $m.Length
        if ($nextIndex -lt $Text.Length -and $Text[$nextIndex] -eq [char]0xFF08) {
            return $code
        }
        if ($TitleMap.ContainsKey($code)) {
            return "$code（$($TitleMap[$code])）"
        }
        return $code
    })
}

function Set-SheetData {
    param(
        $Worksheet,
        [array]$Rows,
        [array]$Headers
    )
    $Worksheet.Cells.Clear() | Out-Null
    for ($c = 0; $c -lt $Headers.Count; $c++) {
        $Worksheet.Cells.Item(1, $c + 1).Value2 = [string]$Headers[$c]
    }
    for ($r = 0; $r -lt $Rows.Count; $r++) {
        $values = $Rows[$r]
        for ($c = 0; $c -lt $Headers.Count; $c++) {
            $value = ""
            if ($c -lt $values.Count -and $null -ne $values[$c]) {
                $value = [string]$values[$c]
            }
            $Worksheet.Cells.Item($r + 2, $c + 1).Value2 = $value
        }
    }

    $used = $Worksheet.UsedRange
    $used.WrapText = $true
    $used.VerticalAlignment = -4160
    $used.Borders.LineStyle = 1

    $header = $Worksheet.Range("A1:N1")
    $header.Font.Bold = $true
    $header.Interior.Color = 14277081
    $header.HorizontalAlignment = -4108

    $Worksheet.Columns.Item(1).ColumnWidth = 18
    $Worksheet.Columns.Item(2).ColumnWidth = 16
    $Worksheet.Columns.Item(3).ColumnWidth = 42
    $Worksheet.Columns.Item(4).ColumnWidth = 18
    $Worksheet.Columns.Item(5).ColumnWidth = 36
    $Worksheet.Columns.Item(6).ColumnWidth = 42
    $Worksheet.Columns.Item(7).ColumnWidth = 48
    $Worksheet.Columns.Item(8).ColumnWidth = 42
    $Worksheet.Columns.Item(9).ColumnWidth = 72
    $Worksheet.Columns.Item(10).ColumnWidth = 46
    $Worksheet.Columns.Item(11).ColumnWidth = 50
    $Worksheet.Columns.Item(12).ColumnWidth = 48
    $Worksheet.Columns.Item(13).ColumnWidth = 16
    $Worksheet.Columns.Item(14).ColumnWidth = 36
    $used.Rows.AutoFit() | Out-Null
}

$root = (Resolve-Path ".").Path
$target = Join-Path $root "SaaS_E2E测试用例_单Sheet用例测试列表.xlsx"
$backup = Join-Path $root ("SaaS_E2E测试用例_单Sheet用例测试列表.broken-" + (Get-Date -Format "yyyyMMdd-HHmmss") + ".xlsx")
if (Test-Path $target) {
    Copy-Item -LiteralPath $target -Destination $backup -Force
}

$rowsJsonPath = Join-Path $root "runtime\testcase_excel_rows.json"
$payload = Get-Content -LiteralPath $rowsJsonPath -Encoding UTF8 -Raw | ConvertFrom-Json

$headers = @(
    "用例编号", "用例层级", "来源/组合依据", "所属模块", "用例标题", "涉及角色/账号", "前置条件",
    "测试数据", "测试步骤", "预期结果", "校验点/断言", "依赖/组合关系", "自动化状态", "备注"
)

$atomicRows = New-Object System.Collections.ArrayList
foreach ($item in $payload.rows) {
    [void]$atomicRows.Add(@($item.values))
}

$comboRows = @(
    @(
        "F-REG-001", "组合流程用例", "A-SAAS-001 -> A-SAAS-003 -> A-SAAS-004", "注册开通",
        "企业注册认证并开通双应用流程",
        "租户平台：企业主账号；SaaS主站：主站管理员账号。",
        "测试手机号可用；主站管理员账号可登录；丸友集和丸掌柜应用入口可审批。",
        "企业注册信息；应用=丸友集、丸掌柜。",
        "1. 先执行用例A-SAAS-001。`n2. 先执行用例A-SAAS-003。`n3. 先执行用例A-SAAS-004。`n4. 回到租户平台应用中心，确认丸友集和丸掌柜均已开通并可进入。",
        "企业完成认证，丸友集和丸掌柜双应用开通成功。",
        "企业认证状态、应用开通状态、租户端入口和主站审批状态一致。",
        "组合举证：A-SAAS-001产出已认证企业；A-SAAS-003产出丸友集已开通；A-SAAS-004产出丸掌柜已开通",
        "已自动化组合", "注册开通大流程"
    ),
    @(
        "F-CONFIG-001", "组合流程用例", "A-AUTH-001 -> A-PUSH-001 -> A-PUSH-003", "授权配置",
        "授权绑定、工作室授权、推单策略配置流程",
        "丸友集：工作室主账号；丸掌柜：企业主账号。",
        "丸友集和丸掌柜均已开通；两个主账号可登录。",
        "授权密钥；工作室名称；策略类型；策略名称。",
        "1. 先执行用例A-AUTH-001。`n2. 先执行用例A-PUSH-001。`n3. 先执行用例A-PUSH-003。`n4. 回到丸掌柜推单配置列表，确认策略可用。",
        "丸掌柜完成丸友集授权绑定、工作室授权和推单策略配置。",
        "授权关系、权限项、工作室授权状态、策略类型和策略名称跨端一致。",
        "组合举证：A-AUTH-001产出已授权关系；A-PUSH-001产出工作室授权；A-PUSH-003产出推单策略",
        "已自动化组合", "配置大流程"
    ),
    @(
        "F-MAIN-001", "组合流程用例", "A-SAAS-001 -> A-SAAS-003 -> A-AUTH-001 -> A-PUSH-001 -> A-PUSH-003 -> A-ORDER-001", "主流程",
        "注册开通授权配置发单主流程闭环",
        "租户平台：新注册企业账号；SaaS主站：主站管理员账号；丸友集：工作室主账号；丸掌柜：企业主账号。",
        "测试手机号可注册；SaaS主站管理员账号可登录；丸友集和丸掌柜应用可开通；两个企业主账号可登录；授权和推单配置入口可用。",
        "企业注册信息；丸友集/丸掌柜账号；授权密钥；策略类型=单平台指定/多工作室同时分发/多平台分发；来源单号；订单标题。",
        "1. 先执行用例A-SAAS-001，租户注册企业并由SaaS主站完成商户认证。`n2. 先执行用例A-SAAS-003，已认证企业申请开通丸友集并由SaaS主站审批通过。`n3. 确认丸掌柜企业主账号可用，并复用固定丸掌柜账号进入后续授权和发单链路。`n4. 先执行用例A-AUTH-001，丸友集生成授权密钥，丸掌柜激活密钥，丸友集完成权限配置和回查。`n5. 先执行用例A-PUSH-001，丸掌柜新增丸友集工作室授权。`n6. 先执行用例A-PUSH-003，丸掌柜按策略类型新增推单配置策略。`n7. 先执行用例A-ORDER-001，丸掌柜手工录单创建外来订单并发布到丸友集。`n8. 登录丸友集相关主账号，进入工作室履约应用-抢单大厅。`n9. 按来源单号或订单标题搜索订单，确认外来订单已到达丸友集。",
        "从租户注册、商户认证、丸友集开通、授权绑定、工作室授权、推单策略到丸掌柜手工录单发单形成可执行主链路。",
        "企业认证状态、应用开通状态、授权密钥状态、权限项、工作室授权、推单策略、来源单号和订单标题在台账及两端页面一致。",
        "组合举证：A-SAAS-001产出已认证企业；A-SAAS-003产出丸友集已开通；A-AUTH-001产出已授权关系；A-PUSH-001产出工作室授权；A-PUSH-003产出推单策略；A-ORDER-001产出已派单外来订单",
        "已自动化组合", "核心大流程；对应test_e2e_main_001_full_closed_loop.py"
    ),
    @(
        "F-MAIN-002", "组合流程用例", "A-ORDER-001 -> A-TASK-001 -> A-DELIVERY-001 -> A-DELIVERY-002 -> B-SETTLE-PLAYER-ACCOUNT-001 -> B-SETTLE-PLAYER-APPLY-001", "主流程",
        "丸掌柜发单到打手提交结算账单主流程",
        "丸掌柜：企业主账号；丸友集：工作室主账号；打手应用：打手子账号。",
        "已完成F-MAIN-001；丸掌柜已具备推单策略；丸友集工作室和打手子账号可用；打手打款账户可完善。",
        "来源单号；订单标题；策略名称；分配方式；打手账号；预期打手收入金额；打款账户信息。",
        "1. 先执行用例A-ORDER-001，丸掌柜手工录单并发布外来订单到丸友集。`n2. 进入丸友集-工作室履约应用-抢单大厅，确认订单可见。`n3. 先执行用例A-TASK-001，丸友集接入外部订单并发给打手，打手完成抢单。`n4. 进入丸友集-工作室履约应用-订单列表，确认订单已发给打手。`n5. 进入打手应用-我的订单，确认订单已进入打手处理列表。`n6. 先执行用例A-DELIVERY-001，打手确认上号、上传首图并提交验收。`n7. 进入丸友集-工作室履约应用-订单列表，确认订单处于待验收状态。`n8. 先执行用例A-DELIVERY-002，丸友集验收打手子单并校验打手收入。`n9. 先执行用例B-SETTLE-PLAYER-ACCOUNT-001，确认或完善打手打款账户信息。`n10. 先执行用例B-SETTLE-PLAYER-APPLY-001，打手在我的收入中提交一键结算账单。`n11. 登录丸友集主账号，进入工作室基础应用-财务结算列表。`n12. 打开员工结算汇总详情，按来源单号或订单标题核对打手结算金额。",
        "外来订单从丸掌柜发布到丸友集，再由丸友集发给打手；打手完成履约、丸友集验收并产生收入后，可完善账户并提交结算账单。",
        "来源单号/订单标题贯穿所有小用例；台账状态按已派单 -> 打手已抢单 -> 已提交验收 -> 收入已验证 -> 打手打款账户已就绪 -> 打手结算账单已提交推进。",
        "组合举证：A-ORDER-001产出已派单；A-TASK-001产出打手已抢单；A-DELIVERY-001产出已提交验收；A-DELIVERY-002产出收入已验证；B-SETTLE-PLAYER-ACCOUNT-001产出打手账户已就绪；B-SETTLE-PLAYER-APPLY-001产出打手结算账单已提交",
        "已自动化组合", "核心大流程；对应test_e2e_main_002_order_to_player_settlement.py"
    )
)

$titleMap = @{}
foreach ($row in $atomicRows) {
    if ($row.Count -ge 5) {
        $titleMap[[string]$row[0]] = [string]$row[4]
    }
}
foreach ($row in $comboRows) {
    $titleMap[[string]$row[0]] = [string]$row[4]
}

$annotatedAtomic = New-Object System.Collections.ArrayList
foreach ($row in $atomicRows) {
    $ownId = [string]$row[0]
    $newRow = New-Object System.Collections.ArrayList
    for ($i = 0; $i -lt $row.Count; $i++) {
        $value = [string]$row[$i]
        if ($i -ne 0) {
            $value = Add-CaseTitleAnnotations -Text $value -TitleMap $titleMap -OwnId $ownId
        }
        [void]$newRow.Add($value)
    }
    [void]$annotatedAtomic.Add(@($newRow))
}

$annotatedCombo = New-Object System.Collections.ArrayList
foreach ($row in $comboRows) {
    $ownId = [string]$row[0]
    $newRow = New-Object System.Collections.ArrayList
    for ($i = 0; $i -lt $row.Count; $i++) {
        $value = [string]$row[$i]
        if ($i -ne 0) {
            $value = Add-CaseTitleAnnotations -Text $value -TitleMap $titleMap -OwnId $ownId
        }
        [void]$newRow.Add($value)
    }
    [void]$annotatedCombo.Add(@($newRow))
}

$excel = New-Object -ComObject Excel.Application
$excel.DisplayAlerts = $false
$excel.Visible = $false
try {
    $workbook = $excel.Workbooks.Add()
    while ($workbook.Worksheets.Count -lt 2) {
        [void]$workbook.Worksheets.Add()
    }
    while ($workbook.Worksheets.Count -gt 2) {
        $workbook.Worksheets.Item($workbook.Worksheets.Count).Delete()
    }
    $sheet1 = $workbook.Worksheets.Item(1)
    $sheet1.Name = "用例测试列表"
    $sheet2 = $workbook.Worksheets.Item(2)
    $sheet2.Name = "组合流程用例"

    Set-SheetData -Worksheet $sheet1 -Rows $annotatedAtomic -Headers $headers
    Set-SheetData -Worksheet $sheet2 -Rows $annotatedCombo -Headers $headers

    if (Test-Path $target) {
        Remove-Item -LiteralPath $target -Force
    }
    $workbook.SaveAs($target, 51)
    $workbook.Close($false)

    $verify = $excel.Workbooks.Open($target)
    $verify.Worksheets.Item(2).Activate()
    $verify.Save()
    $excel.Visible = $true
    Write-Output "OPENED:$target"
}
catch {
    if ($workbook) {
        try { $workbook.Close($false) } catch {}
    }
    throw
}
finally {
    if (-not $excel.Visible) {
        $excel.Quit()
        [System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel) | Out-Null
    }
}
