from __future__ import annotations

from copy import copy
from datetime import datetime
from pathlib import Path
import shutil

from openpyxl import load_workbook


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

CASE_083 = {
    "用例编号": "S-FLOW-083",
    "来源/组合依据": "FLOW-030 实测：S-FLOW-034 后丸掌柜子单列表售后中目标行展示【取消售后】入口。",
    "所属模块": "丸掌柜发起售后",
    "用例标题": "【丸掌柜】异常中子单售后中状态-取消子单售后",
    "前置条件": "已执行 S-FLOW-034，丸掌柜已对异常中子单发起子单售后；丸掌柜订单详情子单列表目标子单状态为售后中，操作列存在【取消售后】入口。",
    "执行步骤": "1. 登录丸掌柜主账号。\n2. 进入商家管理-订单管理。\n3. 按主单号或来源单号查询目标订单。\n4. 打开订单详情并定位子单列表中售后中的目标子单。\n5. 点击目标子单行内【取消售后】。\n6. 在取消售后弹窗中填写取消原因。\n7. 点击【确认取消】。\n8. 回到订单详情，回读主单状态、子单汇总状态、目标子单列表状态和售后信息。\n9. 登录丸友集账号，进入订单列表，按来源单号回查目标订单状态。",
    "预期结果": "1. 丸掌柜侧异常中子单售后取消提交成功。\n2. 目标子单不再显示售后中，恢复为异常中或页面对应可继续处理状态。\n3. 售后取消原因可在订单详情/日志中追溯。\n4. 丸友集侧目标订单不再停留在售后中。\n5. 后续可按页面规则重新对异常中子单发起售后或选择其他异常中后续处理。",
    "跨端/状态断言": "1. 本用例处理的是丸掌柜侧子单行内【取消售后】，不是丸友集侧处理/拒绝子单售后。\n2. 与 S-FLOW-036 区分：S-FLOW-036 为丸友集侧拒绝/取消子单售后，S-FLOW-083 为丸掌柜侧主动取消已发起的子单售后。\n3. 查询字段使用来源单号或主单号，不混用来源单号到订单号字段。",
    "可组合/被引用关系": "承接 S-FLOW-034；被 FLOW-030 引用；取消后可重新接 S-FLOW-034 或按异常中子单后续链路处理。",
    "自动化状态": "已自动化",
    "备注": "2026-07-02 新增：覆盖丸掌柜侧异常中子单售后中行内【取消售后】入口。",
}

FLOW_030_SEQ = "S-FLOW-007 -> S-FLOW-014 -> S-FLOW-021 -> S-FLOW-026 -> S-FLOW-040 -> S-FLOW-043 -> S-FLOW-045 -> S-FLOW-046 -> S-FLOW-048 -> S-FLOW-034 -> S-FLOW-083"
FLOW_030_UPDATE = {
    "链路编号": "FLOW-030",
    "链路名称": "待验收阶段-发起售后-取消售后-异常中子单发起售后-取消子单售后",
    "链路类型": "待验收售后取消后接异常中子单售后取消",
    "终点状态": "异常中子单售后已取消；目标子单恢复异常中或页面对应可继续处理状态",
    "用例编号序列": FLOW_030_SEQ,
    "适用场景": "验证待验收阶段售后取消后，丸掌柜子单列表回到异常中；对异常中子单发起售后后，再由丸掌柜侧取消该子单售后。",
    "数据复用建议": "同一订单在 S-FLOW-034 后继续接 S-FLOW-083；该分支与丸友集侧 S-FLOW-035/S-FLOW-036 处理分支互斥。",
    "注意事项/缺口": "S-FLOW-083 是丸掌柜侧行内取消售后，不是丸友集侧处理售后；取消后可按页面实际状态决定是否重新接 S-FLOW-034。",
}


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


def copy_cell_style(src, dst) -> None:
    if src.has_style:
        dst._style = copy(src._style)
    dst.font = copy(src.font)
    dst.fill = copy(src.fill)
    dst.border = copy(src.border)
    dst.alignment = copy(src.alignment)
    dst.number_format = src.number_format
    dst.protection = copy(src.protection)


def copy_row_style(ws, src_row: int, dst_row: int) -> None:
    ws.row_dimensions[dst_row].height = ws.row_dimensions[src_row].height
    for col in range(1, ws.max_column + 1):
        copy_cell_style(ws.cell(src_row, col), ws.cell(dst_row, col))


def row_by_value(ws, col: int) -> dict[str, int]:
    rows: dict[str, int] = {}
    for row in range(2, ws.max_row + 1):
        value = str(ws.cell(row, col).value or "").strip()
        if value and value not in rows:
            rows[value] = row
    return rows


def set_row_values(ws, row: int, values: dict[str, str]) -> None:
    h = header_map(ws)
    for key, value in values.items():
        if key in h:
            ws.cell(row, h[key]).value = value


def update_case_book() -> None:
    backup = CASE_BOOK.with_name(f"{CASE_BOOK.stem}.s_flow_083前备份_{datetime.now():%Y%m%d%H%M%S}{CASE_BOOK.suffix}")
    shutil.copyfile(CASE_BOOK, backup)
    wb = load_workbook(CASE_BOOK)
    ws = wb["订单状态流转"]
    h = header_map(ws)
    rows = row_by_value(ws, h["用例编号"])
    if "S-FLOW-083" in rows:
        row = rows["S-FLOW-083"]
    else:
        anchor = rows.get("S-FLOW-082") or max(rows.values())
        ws.insert_rows(anchor + 1)
        copy_row_style(ws, anchor, anchor + 1)
        row = anchor + 1
    set_row_values(ws, row, CASE_083)
    wb.save(CASE_BOOK)


def load_case_rows() -> dict[str, dict[str, str]]:
    wb = load_workbook(CASE_BOOK, data_only=True)
    ws = wb["订单状态流转"]
    h = header_map(ws)
    rows: dict[str, dict[str, str]] = {}
    for row in range(2, ws.max_row + 1):
        case_id = str(ws.cell(row, h["用例编号"]).value or "").strip()
        if case_id:
            rows[case_id] = {key: str(ws.cell(row, col).value or "") for key, col in h.items()}
    return rows


def enrich_flow(values: dict[str, str], case_rows: dict[str, dict[str, str]]) -> dict[str, str]:
    case_ids = [item.strip() for item in values["用例编号序列"].split("->") if item.strip()]
    refs = []
    modules = []
    for case_id in case_ids:
        case = case_rows.get(case_id, {})
        refs.append(f"{case_id}({case.get('用例标题', '')})")
        module = case.get("所属模块", "")
        if module and module not in modules:
            modules.append(module)
    enriched = dict(values)
    enriched["用例链路（编号+标题）"] = " -> ".join(refs)
    enriched["涉及模块"] = " -> ".join(modules)
    return enriched


def delete_detail_rows(ws, flow_id: str) -> int:
    insert_at = ws.max_row + 1
    for row in range(ws.max_row, 1, -1):
        if str(ws.cell(row, 1).value or "").strip() == flow_id:
            insert_at = min(insert_at, row)
            ws.delete_rows(row)
    return insert_at if insert_at <= ws.max_row + 1 else ws.max_row + 1


def update_flow_book() -> None:
    backup = FLOW_BOOK.with_name(f"{FLOW_BOOK.stem}.s_flow_083前备份_{datetime.now():%Y%m%d%H%M%S}{FLOW_BOOK.suffix}")
    shutil.copyfile(FLOW_BOOK, backup)
    case_rows = load_case_rows()
    wb = load_workbook(FLOW_BOOK)
    summary = wb["链路流程线"]
    hs = header_map(summary)
    flow_rows = row_by_value(summary, hs["链路编号"])
    set_row_values(summary, flow_rows["FLOW-030"], enrich_flow(FLOW_030_UPDATE, case_rows))

    details = wb["链路步骤明细"]
    insert_at = delete_detail_rows(details, "FLOW-030")
    style_row = max(2, min(insert_at - 1, details.max_row))
    for offset, case_id in enumerate([item.strip() for item in FLOW_030_SEQ.split("->") if item.strip()]):
        row = insert_at + offset
        details.insert_rows(row)
        copy_row_style(details, style_row, row)
        case = case_rows.get(case_id, {})
        values = [
            "FLOW-030",
            str(offset + 1),
            case_id,
            case.get("所属模块", ""),
            case.get("用例标题", ""),
            case.get("前置条件", ""),
            case.get("预期结果", ""),
        ]
        for col, value in enumerate(values, start=1):
            details.cell(row, col).value = value

    coverage = wb["用例覆盖索引"]
    hc = header_map(coverage)
    coverage_rows = row_by_value(coverage, hc["用例编号"])
    if "S-FLOW-083" not in coverage_rows:
        template = coverage_rows.get("S-FLOW-082") or max(coverage_rows.values())
        row = coverage.max_row + 1
        coverage.insert_rows(row)
        copy_row_style(coverage, template, row)
    else:
        row = coverage_rows["S-FLOW-083"]
    set_row_values(
        coverage,
        row,
        {
            "用例编号": "S-FLOW-083",
            "所属模块": CASE_083["所属模块"],
            "用例标题": CASE_083["用例标题"],
            "覆盖次数": "1",
            "出现链路": "FLOW-030",
            "是否已覆盖": "是",
            "备注": "新增丸掌柜侧取消异常中子单售后分支",
        },
    )

    if "说明" in wb.sheetnames:
        wb["说明"].append(["更新记录", f"{datetime.now():%Y-%m-%d %H:%M:%S} 新增 S-FLOW-083，并将 FLOW-030 接到 S-FLOW-034 -> S-FLOW-083。"])
    wb.save(FLOW_BOOK)


def main() -> None:
    update_case_book()
    update_flow_book()
    print("Synced S-FLOW-083 and FLOW-030.")


if __name__ == "__main__":
    main()
