"""分箱服务 + 快递单号生成

generate_tracking_no: 纯函数，从订单号派生快递单号
build_parcel_data:    同步函数，对单个订单执行分箱，返回箱子列表（不写库）
"""
from __future__ import annotations
from app.core.services.packing_engine import ShipmentItem, auto_pack


def generate_tracking_no(order_no: str, carrier_prefix: str, box_index: int) -> str:
    """
    生成快递单号。
    格式：{carrier_prefix}{订单UUID6位}{箱序号2位}
    例：ORD-20260520-A3F8C1, FTD0123, 1 → FTD0123A3F8C101
    """
    uuid_part = order_no.split("-")[-1]  # 取末段 6 位
    return f"{carrier_prefix}{uuid_part}{box_index:02d}"


def build_parcel_data(
    order_id: int,
    order_no: str,
    order_items: list[dict],
    carrier_prefix: str,
    rules: list[dict],
) -> list[dict]:
    """
    对单个订单执行分箱，返回箱子数据列表（不写数据库）。

    每个箱子格式：
    {
        "order_id": int,
        "tracking_no": str,
        "box_index": int,
        "weight": 0,
        "items": [
            {"order_item_id": int, "product_name": str, "sku_name": str|None, "qty": int}
        ]
    }

    order_items 每项需要字段：
        id, product_snapshot(dict with "name"), quantity, variant_id(可None), product_id
    """
    # 构建 ShipmentItem 列表（quantity=实际数量，auto_pack 内部展开）
    shipment_items = [
        ShipmentItem(
            id=str(oi["id"]),
            sku_id=str(oi.get("variant_id") or oi.get("product_id", 0)),
            name=oi["product_snapshot"].get("name", ""),
            weight=float(oi["product_snapshot"].get("weight", 0)),
            value=float(oi.get("unit_price", 0)),
            attributes=oi["product_snapshot"],
            quantity=oi["quantity"],
        )
        for oi in order_items
    ]

    pack_result = auto_pack(shipment_items, rules)

    # 构建返回结构：从 pack_result.boxes 聚合回 order_item 数量
    # 每个 Box.items 是展开后的单件列表，需要按 id 重新聚合 qty
    parcels: list[dict] = []

    # 构建 order_item_id → order_item 映射
    oi_map = {str(oi["id"]): oi for oi in order_items}

    for box_index, box in enumerate(pack_result.boxes, start=1):
        # 聚合：同一 order_item_id 的展开件合并回 qty
        qty_map: dict[str, int] = {}
        for unit in box.items:
            qty_map[unit.id] = qty_map.get(unit.id, 0) + 1

        parcel_items = []
        for oi_id_str, qty in qty_map.items():
            oi = oi_map[oi_id_str]
            snapshot = oi["product_snapshot"]
            parcel_items.append({
                "order_item_id": int(oi_id_str),
                "product_name": snapshot.get("name", ""),
                "sku_name": snapshot.get("sku_name") or snapshot.get("variant_name"),
                "qty": qty,
            })

        parcels.append({
            "order_id": order_id,
            "tracking_no": generate_tracking_no(order_no, carrier_prefix, box_index),
            "box_index": box_index,
            "weight": 0,
            "items": parcel_items,
        })

    # 如果所有商品都被禁运（不应发生，但保底）
    if not parcels:
        parcels.append({
            "order_id": order_id,
            "tracking_no": generate_tracking_no(order_no, carrier_prefix, 1),
            "box_index": 1,
            "weight": 0,
            "items": [
                {
                    "order_item_id": oi["id"],
                    "product_name": oi["product_snapshot"].get("name", ""),
                    "sku_name": None,
                    "qty": oi["quantity"],
                }
                for oi in order_items
            ],
        })

    return parcels
