from __future__ import annotations

import json
from pathlib import Path

import openpyxl
from copy import copy


ROOT = Path(__file__).resolve().parents[1]
CASE_JSON = ROOT / "scripts" / "order_status_flow_cases.json"
CASE_WORKBOOK = ROOT / "测试用例" / "SaaS_E2E测试用例_单Sheet用例测试列表.xlsx"
FLOW_WORKBOOK = ROOT / "测试用例" / "订单状态流转_链路流程线整理.xlsx"


CASE_UPDATES = {
    "S-FLOW-042": {
        "用例层级": "订单状态流转用例",
        "来源/组合依据": "whiteboard_exported_image.png + 状态机对应关系梳理.html：【订单验收】",
        "所属模块": "订单验收",
        "用例标题": "【丸友集视角】打手待验收 / 丸友集子单待验收 / 丸掌柜主单服务中 / 子单代练中 - 拒绝验收子单",
        "登录平台/角色账号": "丸掌柜：企业主账号或客服账号；丸友集：工作室主账号或客服账号；打手：打手子账号。",
        "前置条件": "打手已提交验收，丸友集打手子单处于待验收，丸友集尚未同意或拒绝该子单验收。",
        "测试数据": "来源单号、订单标题、丸掌柜主单号、丸友集父单号、打手子单号、拒绝验收原因。",
        "执行步骤": "\n".join(
            [
                "1. 登录丸友集主账号或客服账号。",
                "2. 进入工作室履约应用-订单列表。",
                "3. 按来源单号查询目标订单。",
                "4. 打开目标订单操作或子单详情，确认目标打手子单为待验收。",
                "5. 点击拒绝验收或驳回验收。",
                "6. 填写拒绝原因并确认提交。",
                "7. 回到丸友集订单列表，按来源单号回查目标订单。",
                "8. 登录打手账号，进入打手应用-我的订单，按来源单号回查目标订单。",
                "9. 登录丸掌柜账号，进入订单管理详情，记录主单和子单状态。",
            ]
        ),
        "预期结果": "\n".join(
            [
                "1. 打手订单状态恢复为代练中。",
                "2. 丸友集目标打手子单恢复为代练中或页面对应继续履约状态。",
                "3. 丸掌柜主单仍为服务中。",
                "4. 丸掌柜子单仍为代练中或服务中。",
                "5. 打手侧可继续提交验收。",
            ]
        ),
        "跨端/状态断言": "\n".join(
            [
                "1. 拒绝子单验收不生成已完成收入。",
                "2. 拒绝子单验收不应让丸掌柜进入待验收。",
                "3. 拒绝后不能残留待验收作为目标子单当前状态。",
            ]
        ),
        "可组合/被引用关系": "FLOW-024 引用；拒绝后回到打手代练中分支，可再次进入 S-FLOW-040。",
        "自动化状态": "已自动化",
        "备注": "2026-07-01修正：该编号在 FLOW-024 链路中表示丸友集拒绝打手验收。",
    },
    "S-FLOW-043": {
        "用例层级": "订单状态流转用例",
        "来源/组合依据": "whiteboard_exported_image.png + 状态机对应关系梳理.html：【订单验收】",
        "所属模块": "订单验收",
        "用例标题": "【丸友集视角】打手待验收 / 丸友集子单待验收 / 丸掌柜主单服务中 / 子单代练中 - 同意验收子单",
        "登录平台/角色账号": "丸掌柜：企业主账号或客服账号；丸友集：工作室主账号或客服账号；打手：打手子账号。",
        "前置条件": "打手已提交验收，丸友集打手子单处于待验收。",
        "测试数据": "来源单号、订单标题、丸掌柜主单号、丸友集父单号、打手子单号、预期打手收入金额。",
        "执行步骤": "\n".join(
            [
                "1. 登录丸友集主账号或客服账号。",
                "2. 进入工作室履约应用-订单列表。",
                "3. 按来源单号查询目标订单。",
                "4. 打开目标订单操作或子单详情，确认目标打手子单为待验收。",
                "5. 点击同意验收子单。",
                "6. 在确认弹窗中确认同意验收。",
                "7. 回到丸友集订单列表，按来源单号回查目标订单。",
                "8. 登录打手账号，进入打手应用-我的收入，按来源单号校验收入记录。",
                "9. 登录丸掌柜账号，进入订单管理详情，记录主单和子单状态。",
            ]
        ),
        "预期结果": "\n".join(
            [
                "1. 打手订单状态为已完成或页面对应完成态。",
                "2. 丸友集目标打手子单状态为已完成。",
                "3. 丸友集父单不因验收单个子单自动变为上游待验收，除非页面另行执行申请上游验收。",
                "4. 丸掌柜主单仍为服务中。",
                "5. 丸掌柜子单仍为代练中或服务中。",
                "6. 打手收入记录可见且金额符合预期。",
            ]
        ),
        "跨端/状态断言": "\n".join(
            [
                "1. 验收子单是工作室向下管理打手，不等于申请上游验收。",
                "2. 打手收入或可结算记录可按结算用例继续校验。",
                "3. 完成单个打手子单不应直接完结丸掌柜主单。",
            ]
        ),
        "可组合/被引用关系": "FLOW-025、FLOW-026 等验收后续链路引用。",
        "自动化状态": "已自动化",
        "备注": "2026-07-01修正：该编号在 FLOW-025 链路中表示丸友集同意验收打手子单。",
    },
    "S-FLOW-044": {
        "用例层级": "订单状态流转用例",
        "来源/组合依据": "whiteboard_exported_image.png + 状态机对应关系梳理.html：【多子单履约】",
        "所属模块": "多子单履约",
        "用例标题": "【丸友集视角】前一子单已完成 / 丸掌柜主单服务中 / 子单代练中 - 续发下一子单",
        "登录平台/角色账号": "丸掌柜：企业主账号或客服账号；丸友集：工作室主账号或客服账号；打手：打手子账号。",
        "前置条件": "丸友集已同意验收前一打手子单，前一子单处于已完成，主单仍需继续履约且页面允许继续发单。",
        "测试数据": "来源单号、订单标题、丸掌柜主单号、丸友集父单号、已完成打手子单号、下一子单发单信息、价格模式、收单价百分比、打手账号。",
        "执行步骤": "\n".join(
            [
                "1. 登录丸友集主账号或客服账号。",
                "2. 进入工作室履约应用-订单列表。",
                "3. 按来源单号查询目标订单。",
                "4. 打开目标订单操作或子单列表，确认前一打手子单为已完成。",
                "5. 点击继续发单或再次发单。",
                "6. 填写下一子单分配方式、价格模式、收单价百分比、服务时限、联系电话等必填字段。",
                "7. 点击确认发单并处理确认提示。",
                "8. 回到丸友集订单列表，按来源单号回查目标订单和下一子单状态。",
                "9. 如分配方式为抢单大厅，登录打手账号进入抢单大厅，确认下一子单可见。",
                "10. 后续接 S-FLOW-026 由打手接单。",
            ]
        ),
        "预期结果": "\n".join(
            [
                "1. 前一子单保持已完成。",
                "2. 下一子单进入待接单、已发单或页面对应待打手处理状态。",
                "3. 丸友集父单仍为继续履约状态。",
                "4. 丸掌柜主单不因单个子单完成直接完结。",
                "5. 下一子单可继续接 S-FLOW-026。",
            ]
        ),
        "跨端/状态断言": "\n".join(
            [
                "1. 续发不能覆盖前一已完成子单。",
                "2. 下一子单的打手、价格、状态与前一子单相互独立。",
                "3. 主单状态按所有子单聚合展示。",
            ]
        ),
        "可组合/被引用关系": "FLOW-025 引用；后续接 S-FLOW-026。",
        "自动化状态": "已自动化",
        "备注": "2026-07-01修正：该编号在 FLOW-025 链路中表示子单完成后续发下一子单；丸掌柜同意上游验收另由后续上游验收链路覆盖。",
    },
}


def headers_for(sheet) -> dict[str, int]:
    return {
        str(sheet.cell(1, column).value or "").strip(): column
        for column in range(1, sheet.max_column + 1)
        if str(sheet.cell(1, column).value or "").strip()
    }


def update_case_json() -> None:
    cases = json.loads(CASE_JSON.read_text(encoding="utf-8"))
    for item in cases:
        case_id = str(item.get("用例编号", "")).strip()
        if case_id in CASE_UPDATES:
            item.update(CASE_UPDATES[case_id])
    CASE_JSON.write_text(json.dumps(cases, ensure_ascii=False, indent=2), encoding="utf-8")


def update_rows_by_case_id(workbook_path: Path) -> None:
    workbook = openpyxl.load_workbook(workbook_path)
    try:
        for sheet in workbook.worksheets:
            headers = headers_for(sheet)
            case_col = headers.get("用例编号")
            if not case_col:
                continue
            for row in range(2, sheet.max_row + 1):
                case_id = str(sheet.cell(row, case_col).value or "").strip()
                updates = CASE_UPDATES.get(case_id)
                if not updates:
                    continue
                for header, value in updates.items():
                    column = headers.get(header)
                    if column:
                        cell = sheet.cell(row, column)
                        cell.value = value
                        alignment = copy(cell.alignment)
                        alignment.wrap_text = True
                        alignment.vertical = "top"
                        cell.alignment = alignment
        workbook.save(workbook_path)
    finally:
        workbook.close()


def load_case_map() -> dict[str, dict[str, str]]:
    workbook = openpyxl.load_workbook(CASE_WORKBOOK, data_only=True)
    try:
        sheet = workbook["订单状态流转"]
        headers = headers_for(sheet)
        case_col = headers["用例编号"]
        result: dict[str, dict[str, str]] = {}
        for row in range(2, sheet.max_row + 1):
            case_id = str(sheet.cell(row, case_col).value or "").strip()
            if not case_id:
                continue
            result[case_id] = {
                header: str(sheet.cell(row, column).value or "")
                for header, column in headers.items()
            }
        return result
    finally:
        workbook.close()


def update_flow_summary() -> None:
    case_map = load_case_map()
    workbook = openpyxl.load_workbook(FLOW_WORKBOOK)
    try:
        sheet = workbook["链路流程线"]
        headers = headers_for(sheet)
        sequence_col = headers.get("用例编号序列")
        ref_col = headers.get("用例链路（编号+标题）")
        module_col = headers.get("涉及模块")
        if not sequence_col:
            return
        for row in range(2, sheet.max_row + 1):
            sequence = str(sheet.cell(row, sequence_col).value or "")
            case_ids = [part.strip() for part in sequence.split("->") if part.strip()]
            if not any(case_id in CASE_UPDATES for case_id in case_ids):
                continue
            if ref_col:
                sheet.cell(row, ref_col).value = " -> ".join(
                    f"{case_id}({case_map.get(case_id, {}).get('用例标题', '')})"
                    for case_id in case_ids
                )
            if module_col:
                modules: list[str] = []
                for case_id in case_ids:
                    module = case_map.get(case_id, {}).get("所属模块", "")
                    if module and module not in modules:
                        modules.append(module)
                sheet.cell(row, module_col).value = " -> ".join(modules)
        workbook.save(FLOW_WORKBOOK)
    finally:
        workbook.close()


def main() -> None:
    update_case_json()
    update_rows_by_case_id(CASE_WORKBOOK)
    update_rows_by_case_id(FLOW_WORKBOOK)
    update_flow_summary()
    print("Synced FLOW-024/FLOW-025 acceptance cases: S-FLOW-042, S-FLOW-043, S-FLOW-044")


if __name__ == "__main__":
    main()
