from __future__ import annotations

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

from openpyxl import load_workbook


ROOT = Path(__file__).resolve().parents[1]
FLOW_WORKBOOK = ROOT / "测试用例" / "订单状态流转_链路流程线整理.xlsx"
BACKUP_DIR = ROOT / "runtime" / "excel_backups"


def backup(path: Path) -> Path:
    BACKUP_DIR.mkdir(parents=True, exist_ok=True)
    target = BACKUP_DIR / f"{path.stem}.before_move_flow_013_014_after_017_{datetime.now():%Y%m%d-%H%M%S}{path.suffix}"
    shutil.copy2(path, target)
    return target


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


def copy_row_style(ws, source: int, target: int) -> None:
    for column in range(1, ws.max_column + 1):
        src = ws.cell(source, column)
        dst = ws.cell(target, column)
        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)
    ws.row_dimensions[target].height = ws.row_dimensions[source].height


def row_snapshot(ws, row: int) -> tuple[list[object], int | None]:
    return [ws.cell(row, column).value for column in range(1, ws.max_column + 1)], ws.row_dimensions[row].height


def write_row_snapshot(ws, row: int, values: list[object], height: int | None) -> None:
    for column, value in enumerate(values, start=1):
        ws.cell(row, column).value = value
    ws.row_dimensions[row].height = height


def move_row_after(ws, key: str, anchor: str) -> None:
    source = find_row(ws, key)
    anchor_row = find_row(ws, anchor)
    if source is None or anchor_row is None:
        raise AssertionError(f"missing row: key={key} source={source}; anchor={anchor} anchor_row={anchor_row}")
    if source == anchor_row + 1:
        return

    values, height = row_snapshot(ws, source)
    style_source = source
    ws.delete_rows(source)
    if source < anchor_row:
        anchor_row -= 1
    target = anchor_row + 1
    ws.insert_rows(target)
    copy_row_style(ws, min(style_source, ws.max_row), target)
    write_row_snapshot(ws, target, values, height)


def capture_block(ws, key: str) -> list[tuple[list[object], int | None, int]]:
    rows: list[tuple[list[object], int | None, int]] = []
    for row in range(2, ws.max_row + 1):
        if str(ws.cell(row, 1).value or "").strip() == key:
            values, height = row_snapshot(ws, row)
            rows.append((values, height, row))
    if not rows:
        raise AssertionError(f"missing detail block: {key}")
    return rows


def delete_block(ws, key: str) -> None:
    for row in range(ws.max_row, 1, -1):
        if str(ws.cell(row, 1).value or "").strip() == key:
            ws.delete_rows(row)


def insert_block_after(ws, key: str, anchor: str) -> None:
    block = capture_block(ws, key)
    delete_block(ws, key)
    anchor_rows = [row for row in range(2, ws.max_row + 1) if str(ws.cell(row, 1).value or "").strip() == anchor]
    if not anchor_rows:
        raise AssertionError(f"missing detail anchor: {anchor}")

    target = max(anchor_rows) + 1
    ws.insert_rows(target, amount=len(block))
    style_row = max(2, target - 1)
    for offset, (values, height, _source_row) in enumerate(block):
        row = target + offset
        copy_row_style(ws, style_row, row)
        write_row_snapshot(ws, row, values, height)


def print_order(ws) -> None:
    for row in range(2, ws.max_row + 1):
        flow_id = str(ws.cell(row, 1).value or "").strip()
        if flow_id.startswith("FLOW-"):
            print(row, flow_id, ws.cell(row, 2).value)


def main() -> None:
    backup_path = backup(FLOW_WORKBOOK)
    workbook = load_workbook(FLOW_WORKBOOK)

    summary = workbook["链路流程线"]
    details = workbook["链路步骤明细"]

    move_row_after(summary, "FLOW-013", "FLOW-017")
    move_row_after(summary, "FLOW-014", "FLOW-013")

    insert_block_after(details, "FLOW-013", "FLOW-017")
    insert_block_after(details, "FLOW-014", "FLOW-013")

    notes = workbook["说明"]
    notes.append([
        "更新记录",
        f"{datetime.now():%Y-%m-%d %H:%M:%S} 调整 FLOW-013/FLOW-014 位置：移动到 FLOW-017 后，归入打手代练中撤销主单后的处罚追缴分支区；链路内容未改。",
    ])

    workbook.save(FLOW_WORKBOOK)
    print(f"backup {backup_path}")
    print(f"updated {FLOW_WORKBOOK}")
    print_order(summary)


if __name__ == "__main__":
    main()
