from __future__ import annotations

from pathlib import Path
from copy import copy

import openpyxl


WORKBOOK = Path("SaaS_E2E测试用例_单Sheet用例测试列表.xlsx")
SHEET = "用例测试列表"


CASES = [
    {
        "用例编号": "DATA-CONFIG-001",
        "用例标题": "商家管理-数据字典配置工单-问题类型选项",
        "来源/组合依据": "S-FLOW-002 及客服工单/售后申请流程依赖商家管理-数据字典【工单-问题类型】。",
        "测试数据": "字典分类：工单-问题类型；选项名称：E2E售后问题；排序权重值：1；状态：启用。",
        "执行步骤": "1. 登录丸掌柜账号。\n2. 进入商家管理-数据字典。\n3. 切换【工单-问题类型】分类。\n4. 按字典值查询【E2E售后问题】。\n5. 如不存在则点击添加选项，填写名称和排序权重值，状态保持启用并保存。",
        "预期结果": "1. 【工单-问题类型】下存在启用状态的【E2E售后问题】。\n2. 重复执行脚本不会重复新增同名字典项。\n3. 后续客服工单/售后申请可选择问题类型。",
        "备注": "脚本路径：e2e/tests/数据配置/test_data_config_001_006_data_dictionary_options.py；pytest marker：data_config_001。",
    },
    {
        "用例编号": "DATA-CONFIG-002",
        "用例标题": "商家管理-数据字典配置工单-紧急程度选项",
        "来源/组合依据": "S-FLOW-002 及客服工单/售后申请流程依赖商家管理-数据字典【工单-紧急程度】。",
        "测试数据": "字典分类：工单-紧急程度；选项名称：E2E普通紧急；展示色：#000000；解决时限：240分钟；排序权重值：1；状态：启用。",
        "执行步骤": "1. 登录丸掌柜账号。\n2. 进入商家管理-数据字典。\n3. 切换【工单-紧急程度】分类。\n4. 按字典值查询【E2E普通紧急】。\n5. 如不存在则点击添加选项，填写名称、展示色、解决时限和排序权重值，状态保持启用并保存。",
        "预期结果": "1. 【工单-紧急程度】下存在启用状态的【E2E普通紧急】。\n2. 解决时限保存成功，后续工单列表可计算时限。\n3. 重复执行脚本不会重复新增同名字典项。",
        "备注": "脚本路径：e2e/tests/数据配置/test_data_config_001_006_data_dictionary_options.py；pytest marker：data_config_002。",
    },
    {
        "用例编号": "DATA-CONFIG-003",
        "用例标题": "商家管理-数据字典配置工单-跟进类型选项",
        "来源/组合依据": "客服工单跟进流程依赖商家管理-数据字典【工单-跟进类型】。",
        "测试数据": "字典分类：工单-跟进类型；选项名称：E2E售后跟进；排序权重值：1；状态：启用。",
        "执行步骤": "1. 登录丸掌柜账号。\n2. 进入商家管理-数据字典。\n3. 切换【工单-跟进类型】分类。\n4. 按字典值查询【E2E售后跟进】。\n5. 如不存在则点击添加选项，填写名称和排序权重值，状态保持启用并保存。",
        "预期结果": "1. 【工单-跟进类型】下存在启用状态的【E2E售后跟进】。\n2. 后续客服工单跟进记录可选择跟进类型。\n3. 重复执行脚本不会重复新增同名字典项。",
        "备注": "脚本路径：e2e/tests/数据配置/test_data_config_001_006_data_dictionary_options.py；pytest marker：data_config_003。",
    },
    {
        "用例编号": "DATA-CONFIG-004",
        "用例标题": "商家管理-数据字典配置售后-申请类型选项",
        "来源/组合依据": "S-FLOW-002 发起售后弹窗依赖商家管理-数据字典【售后-申请类型】。",
        "测试数据": "字典分类：售后-申请类型；选项名称：E2E售后申请；排序权重值：1；状态：启用。",
        "执行步骤": "1. 登录丸掌柜账号。\n2. 进入商家管理-数据字典。\n3. 切换【售后-申请类型】分类。\n4. 按字典值查询【E2E售后申请】。\n5. 如不存在则点击添加选项，填写名称和排序权重值，状态保持启用并保存。",
        "预期结果": "1. 【售后-申请类型】下存在启用状态的【E2E售后申请】。\n2. S-FLOW-002 发起售后时申请类型下拉可选择。\n3. 重复执行脚本不会重复新增同名字典项。",
        "备注": "脚本路径：e2e/tests/数据配置/test_data_config_001_006_data_dictionary_options.py；pytest marker：data_config_004。",
    },
    {
        "用例编号": "DATA-CONFIG-005",
        "用例标题": "商家管理-数据字典配置申诉类型选项",
        "来源/组合依据": "申诉流程依赖商家管理-数据字典【申诉类型】。",
        "测试数据": "字典分类：申诉类型；选项名称：E2E售后申诉；排序权重值：1；状态：启用。",
        "执行步骤": "1. 登录丸掌柜账号。\n2. 进入商家管理-数据字典。\n3. 切换【申诉类型】分类。\n4. 按字典值查询【E2E售后申诉】。\n5. 如不存在则点击添加选项，填写名称和排序权重值，状态保持启用并保存。",
        "预期结果": "1. 【申诉类型】下存在启用状态的【E2E售后申诉】。\n2. 后续申诉流程可选择申诉类型。\n3. 重复执行脚本不会重复新增同名字典项。",
        "备注": "脚本路径：e2e/tests/数据配置/test_data_config_001_006_data_dictionary_options.py；pytest marker：data_config_005。",
    },
    {
        "用例编号": "DATA-CONFIG-006",
        "用例标题": "商家管理-数据字典配置处罚类型选项",
        "来源/组合依据": "子单处罚流程依赖商家管理-数据字典【处罚类型】。",
        "测试数据": "字典分类：处罚类型；选项名称：E2E售后处罚；排序权重值：1；状态：启用。",
        "执行步骤": "1. 登录丸掌柜账号。\n2. 进入商家管理-数据字典。\n3. 切换【处罚类型】分类。\n4. 按字典值查询【E2E售后处罚】。\n5. 如不存在则点击添加选项，填写名称和排序权重值，状态保持启用并保存。",
        "预期结果": "1. 【处罚类型】下存在启用状态的【E2E售后处罚】。\n2. 后续子单处罚流程可选择处罚类型。\n3. 重复执行脚本不会重复新增同名字典项。",
        "备注": "脚本路径：e2e/tests/数据配置/test_data_config_001_006_data_dictionary_options.py；pytest marker：data_config_006。",
    },
]

COMMON = {
    "用例层级": "前置数据配置用例",
    "所属模块": "数据配置",
    "登录平台/角色账号": "丸掌柜：企业主账号或具备商家管理-数据字典权限账号。",
    "前置条件": "丸掌柜账号已开通；账号具备进入商家管理-数据字典并新增字典项的权限。",
    "跨端/状态断言": "数据配置只影响丸掌柜基础字典，不创建订单、不改变订单状态；后续由售后/工单/申诉/处罚相关流程引用。",
    "可组合/被引用关系": "被 S-FLOW-002、上游发起售后、客服工单、申诉、处罚相关用例引用。",
    "自动化状态": "已自动化",
}


def copy_row_style(sheet, source_row: int, target_row: int) -> None:
    sheet.row_dimensions[target_row].height = sheet.row_dimensions[source_row].height
    for column in range(1, sheet.max_column + 1):
        source = sheet.cell(source_row, column)
        target = sheet.cell(target_row, column)
        if source.has_style:
            target._style = copy(source._style)
        target.font = copy(source.font)
        target.fill = copy(source.fill)
        target.border = copy(source.border)
        target.alignment = copy(source.alignment)
        target.number_format = source.number_format
        target.protection = copy(source.protection)


def find_style_template_row(sheet, case_id_column: int, first_data_config_row: int | None) -> int:
    upper_bound = first_data_config_row or sheet.max_row + 1
    for row in range(upper_bound - 1, 1, -1):
        case_id = sheet.cell(row, case_id_column).value
        if case_id and not str(case_id).startswith("DATA-CONFIG"):
            return row
    return 2


def main() -> None:
    workbook = openpyxl.load_workbook(WORKBOOK)
    sheet = workbook[SHEET]
    headers = [cell.value for cell in sheet[1]]
    index = {header: column + 1 for column, header in enumerate(headers)}

    rows_by_id = {}
    first_data_config_row = None
    for row in range(2, sheet.max_row + 1):
        case_id = sheet.cell(row, index["用例编号"]).value
        if case_id:
            rows_by_id[str(case_id)] = row
            if str(case_id).startswith("DATA-CONFIG") and first_data_config_row is None:
                first_data_config_row = row

    template_row = find_style_template_row(sheet, index["用例编号"], first_data_config_row)

    for case in CASES:
        case_id = case["用例编号"]
        row = rows_by_id.get(case_id)
        if row is None:
            row = sheet.max_row + 1
            rows_by_id[case_id] = row
        copy_row_style(sheet, template_row, row)
        values = {**COMMON, **case}
        for header, value in values.items():
            sheet.cell(row, index[header]).value = value

    workbook.save(WORKBOOK)
    print(f"updated {len(CASES)} data config cases in {WORKBOOK}")


if __name__ == "__main__":
    main()
