from __future__ import annotations

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

from openpyxl import load_workbook


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


CASE_UPDATES = {
    "S-FLOW-050": {
        "source": "实测平台：丸掌柜客服发起主单申诉，丸掌柜主账号在商家管理-主单申诉单审核",
        "module": "订单已完结 主单申诉-丸掌柜发起",
        "title": "【丸掌柜】已完成状态发起主单申诉",
        "role": "丸掌柜：客服账号或企业主账号发起；丸掌柜：企业主账号审核；不涉及丸友集。",
        "pre": "丸掌柜订单状态为已完成，订单详情存在【主单发起申诉】入口。",
        "data": "来源单号、订单标题、丸掌柜主单号、申诉类型、申诉金额、申诉原因、操作凭证。",
        "steps": "1. 登录丸掌柜客服账号或企业主账号。\n2. 进入【丸掌柜】商家管理-订单管理。\n3. 查询已完成状态的目标订单。\n4. 点击订单编号第一列主单号进入订单详情。\n5. 点击右下角【主单发起申诉】。\n6. 选择申诉类型，填写申诉金额、申诉原因并上传凭证。\n7. 提交主单申诉。\n8. 进入【丸掌柜】商家管理-主单申诉单。\n9. 按主单号、来源单号或订单标题查询目标申诉单。\n10. 记录申诉单状态、申诉金额和申诉原因。",
        "expected": "1. 丸掌柜主单订单状态保持已完成。\n2. 主单申诉单页面生成待审核/待处理申诉记录。\n3. 申诉金额、申诉原因、凭证与提交内容一致。\n4. 全流程不需要登录丸友集，丸友集侧不参与审批。",
        "assertion": "1. 主单号、来源单号、申诉单号、申诉金额、申诉原因在订单详情和主单申诉单中一致。\n2. 发起申诉不应改变已完成主状态。\n3. 该流程只在丸掌柜内流转，不校验丸友集审批。",
        "relation": "订单状态流转分支库；后续承接 S-FLOW-052 或 S-FLOW-053，由丸掌柜主账号在主单申诉单审核。",
        "status": "待自动化",
        "note": "按实测平台修正：主单申诉全程不经过丸友集审批。",
    },
    "S-FLOW-051": {
        "source": "实测平台：丸掌柜客服发起主单申诉，丸掌柜主账号在商家管理-主单申诉单审核",
        "module": "订单已完结 主单申诉-丸掌柜发起",
        "title": "【丸掌柜】已售后状态发起主单申诉",
        "role": "丸掌柜：客服账号或企业主账号发起；丸掌柜：企业主账号审核；不涉及丸友集。",
        "pre": "丸掌柜订单状态为已售后，订单详情存在【主单发起申诉】入口。",
        "data": "来源单号、订单标题、丸掌柜主单号、申诉类型、申诉金额、申诉原因、操作凭证。",
        "steps": "1. 登录丸掌柜客服账号或企业主账号。\n2. 进入【丸掌柜】商家管理-订单管理。\n3. 查询已售后状态的目标订单。\n4. 点击订单编号第一列主单号进入订单详情。\n5. 点击右下角【主单发起申诉】。\n6. 选择申诉类型，填写申诉金额、申诉原因并上传凭证。\n7. 提交主单申诉。\n8. 进入【丸掌柜】商家管理-主单申诉单。\n9. 按主单号、来源单号或订单标题查询目标申诉单。\n10. 记录申诉单状态、申诉金额和申诉原因。",
        "expected": "1. 丸掌柜主单订单状态保持已售后。\n2. 主单申诉单页面生成待审核/待处理申诉记录。\n3. 申诉金额、申诉原因、凭证与提交内容一致。\n4. 全流程不需要登录丸友集，丸友集侧不参与审批。",
        "assertion": "1. 主单号、来源单号、申诉单号、申诉金额、申诉原因在订单详情和主单申诉单中一致。\n2. 发起申诉不应回退到售后中或普通履约状态。\n3. 该流程只在丸掌柜内流转，不校验丸友集审批。",
        "relation": "订单状态流转分支库；后续承接 S-FLOW-052 或 S-FLOW-053，由丸掌柜主账号在主单申诉单审核。",
        "status": "待自动化",
        "note": "按实测平台修正：主单申诉全程不经过丸友集审批。",
    },
    "S-FLOW-052": {
        "source": "实测平台：丸掌柜主账号在商家管理-主单申诉单审核通过/确认赔偿",
        "module": "订单已完结 主单申诉-丸掌柜审核",
        "title": "【丸掌柜】主单申诉单审核通过/确认赔偿",
        "role": "丸掌柜：企业主账号或主单申诉审核权限账号；不涉及丸友集。",
        "pre": "已执行 S-FLOW-050 或 S-FLOW-051，丸掌柜主单申诉单中存在待审核/待处理申诉记录。",
        "data": "主单申诉单号、来源单号、订单标题、丸掌柜主单号、赔偿金额、审核备注。",
        "steps": "1. 登录丸掌柜企业主账号或主单申诉审核权限账号。\n2. 进入【丸掌柜】商家管理-主单申诉单。\n3. 按主单号、来源单号、订单标题或申诉单号查询目标申诉单。\n4. 打开申诉单详情。\n5. 点击审核通过、同意赔偿或页面对应通过入口。\n6. 填写赔偿金额和审核备注。\n7. 提交审核结果。\n8. 返回主单申诉单列表重新查询目标申诉单。\n9. 回到订单管理查询目标订单，打开主单详情记录订单状态。",
        "expected": "1. 主单申诉单处理结果为审核通过、确认赔偿或页面对应完成状态。\n2. 丸掌柜订单主状态保持已完成或已售后终态。\n3. 赔偿金额、审核备注保存成功。\n4. 全流程不涉及丸友集审批。",
        "assertion": "1. 申诉单号、主单号、来源单号、赔偿金额、审核结果在主单申诉单和订单详情记录中一致。\n2. 审核通过不应错误回退订单主状态。\n3. 不登录丸友集校验审批。",
        "relation": "承接 S-FLOW-050/S-FLOW-051；丸掌柜内部主单申诉正向审核结果。",
        "status": "待自动化",
        "note": "按实测平台修正：主单申诉由丸掌柜主账号在主单申诉单审核通过/确认赔偿。",
    },
    "S-FLOW-053": {
        "source": "实测平台：丸掌柜主账号在商家管理-主单申诉单驳回",
        "module": "订单已完结 主单申诉-丸掌柜审核",
        "title": "【丸掌柜】主单申诉单审核驳回",
        "role": "丸掌柜：企业主账号或主单申诉审核权限账号；不涉及丸友集。",
        "pre": "已执行 S-FLOW-050 或 S-FLOW-051，丸掌柜主单申诉单中存在待审核/待处理申诉记录。",
        "data": "主单申诉单号、来源单号、订单标题、丸掌柜主单号、驳回原因、审核备注。",
        "steps": "1. 登录丸掌柜企业主账号或主单申诉审核权限账号。\n2. 进入【丸掌柜】商家管理-主单申诉单。\n3. 按主单号、来源单号、订单标题或申诉单号查询目标申诉单。\n4. 打开申诉单详情。\n5. 点击驳回申诉或页面对应驳回入口。\n6. 填写驳回原因和审核备注。\n7. 提交审核结果。\n8. 返回主单申诉单列表重新查询目标申诉单。\n9. 回到订单管理查询目标订单，打开主单详情记录订单状态。",
        "expected": "1. 主单申诉单处理结果为已驳回或页面对应驳回状态。\n2. 丸掌柜订单主状态保持已完成或已售后终态。\n3. 驳回原因和审核备注保存成功。\n4. 不生成确认赔偿金额记录。\n5. 全流程不涉及丸友集审批。",
        "assertion": "1. 申诉单号、主单号、来源单号、驳回原因、审核结果在主单申诉单和订单详情记录中一致。\n2. 驳回不应错误回退订单主状态。\n3. 不登录丸友集校验审批。",
        "relation": "承接 S-FLOW-050/S-FLOW-051；丸掌柜内部主单申诉逆向审核结果。",
        "status": "待自动化",
        "note": "按实测平台修正：主单申诉由丸掌柜主账号在主单申诉单驳回。",
    },
}


REPLACEMENTS = {
    "订单已完结 申诉-上游发起": "订单已完结 主单申诉",
    "【丸掌柜】已完成状态发起申诉": "【丸掌柜】已完成状态发起主单申诉",
    "【丸掌柜】已售后状态发起申诉": "【丸掌柜】已售后状态发起主单申诉",
    "已完成状态发起申诉": "已完成状态发起主单申诉",
    "已售后状态发起申诉": "已售后状态发起主单申诉",
    "丸友集确认赔偿后申诉完成": "丸掌柜主单申诉审核通过/确认赔偿",
    "丸友集驳回申诉": "丸掌柜主单申诉审核驳回",
    "丸友集确认赔偿": "丸掌柜主单申诉审核通过/确认赔偿",
    "丸友集驳回": "丸掌柜主单申诉审核驳回",
    "由丸友集确认赔偿": "由丸掌柜主账号审核通过/确认赔偿",
    "丸友集侧驳回申诉": "丸掌柜主账号在主单申诉单驳回",
    "丸友集侧申诉待处理": "丸掌柜主单申诉单待审核/待处理",
    "丸友集出现待处理申诉": "丸掌柜主单申诉单出现待审核/待处理申诉",
    "登录丸友集账号": "登录丸掌柜主账号",
    "登录丸友集主账号或客服账号": "登录丸掌柜主账号或主单申诉审核权限账号",
    "进入申诉处理入口": "进入商家管理-主单申诉单",
    "丸友集申诉处理结果": "丸掌柜主单申诉单处理结果",
    "赔偿金额、处理备注、申诉结果两端一致": "赔偿金额、审核备注、申诉结果在丸掌柜订单详情和主单申诉单中一致",
    "驳回原因两端一致": "驳回原因在丸掌柜订单详情和主单申诉单中一致",
    "两端一致": "丸掌柜订单详情和主单申诉单一致",
    "不登录丸友集/打手查询": "不登录丸友集/打手查询",
}


def copy_row_style(ws, src_row: int, dst_row: int) -> None:
    if src_row < 1 or src_row == dst_row:
        return
    for col in range(1, ws.max_column + 1):
        src = ws.cell(src_row, col)
        dst = ws.cell(dst_row, col)
        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


def find_row(ws, key: str) -> int | None:
    for row in range(2, ws.max_row + 1):
        if str(ws.cell(row, 1).value or "") == key:
            return row
    return None


def case_row(case_id: str, data: dict[str, str]) -> list[str]:
    return [
        case_id,
        "订单状态流转用例",
        data["source"],
        data["module"],
        data["title"],
        data["role"],
        data["pre"],
        data["data"],
        data["steps"],
        data["expected"],
        data["assertion"],
        data["relation"],
        data["status"],
        data["note"],
    ]


def upsert_case(ws, case_id: str, data: dict[str, str]) -> None:
    row = find_row(ws, case_id)
    values = case_row(case_id, data)
    if row is None:
        ws.append(values)
        copy_row_style(ws, ws.max_row - 1, ws.max_row)
        return
    for column, value in enumerate(values, start=1):
        ws.cell(row, column).value = value


def replace_text(value):
    if not isinstance(value, str):
        return value
    for old, new in REPLACEMENTS.items():
        value = value.replace(old, new)
    value = value.replace("申诉赔偿", "主单申诉审核通过")
    value = value.replace("申诉驳回", "主单申诉审核驳回")
    value = value.replace("申诉完成/确认赔偿", "主单申诉审核通过/确认赔偿")
    return value


def replace_sheet_text(ws) -> None:
    for row in ws.iter_rows():
        for cell in row:
            cell.value = replace_text(cell.value)


def update_main() -> None:
    workbook = load_workbook(MAIN)
    sheet = workbook["订单状态流转"]
    for case_id, data in CASE_UPDATES.items():
        upsert_case(sheet, case_id, data)
    workbook.save(MAIN)


def update_flow() -> None:
    workbook = load_workbook(FLOW)
    for sheet_name in ["链路流程线", "链路步骤明细", "用例覆盖索引", "原始用例索引"]:
        replace_sheet_text(workbook[sheet_name])

    raw = workbook["原始用例索引"]
    coverage = workbook["用例覆盖索引"]
    for case_id, data in CASE_UPDATES.items():
        row = find_row(raw, case_id)
        values = [case_id, data["module"], data["title"], data["pre"], data["expected"], data["steps"]]
        if row:
            for column, value in enumerate(values, start=1):
                raw.cell(row, column).value = value
        else:
            raw.append(values)
            copy_row_style(raw, raw.max_row - 1, raw.max_row)

        row = find_row(coverage, case_id)
        if row:
            coverage.cell(row, 2).value = data["module"]
            coverage.cell(row, 3).value = data["title"]
            coverage.cell(row, 7).value = "按实测平台修正：主单申诉由丸掌柜主账号在主单申诉单审核，不涉及丸友集"

    steps = workbook["链路步骤明细"]
    for row in range(2, steps.max_row + 1):
        case_id = str(steps.cell(row, 3).value or "")
        if case_id in CASE_UPDATES:
            data = CASE_UPDATES[case_id]
            steps.cell(row, 4).value = data["module"]
            steps.cell(row, 5).value = data["title"]
            steps.cell(row, 6).value = data["pre"]
            steps.cell(row, 7).value = data["expected"]

    notes = workbook["说明"]
    notes.append(["更新记录", f"{datetime.now():%Y-%m-%d %H:%M:%S} 修正 S-FLOW-050~053：主单申诉全程由丸掌柜发起并在主单申诉单审核，不涉及丸友集"])
    copy_row_style(notes, notes.max_row - 1, notes.max_row)
    workbook.save(FLOW)


if __name__ == "__main__":
    update_main()
    update_flow()
    print(f"corrected {MAIN}")
    print(f"corrected {FLOW}")
