"""流水写入唯一入口。所有库存变化必须经此产生，余额由流水派生。"""
import hashlib
from dataclasses import dataclass
from decimal import Decimal

from app.plugins.inventory.models import InventoryTransaction


@dataclass
class TxnRequest:
    tenant_id: int
    product_id: int
    variant_id: int | None
    warehouse_id: int
    qty_delta: Decimal
    doc_type: str
    doc_id: int | None
    location_id: int | None = None
    batch_id: int | None = None
    serial_id: int | None = None
    stock_state: str = "sellable"
    unit_cost: Decimal | None = None
    operator_id: int | None = None
    reason: str | None = None
    unallocated: bool = False


def idempotency_key(doc_type: str, doc_id: int | None, product_id: int,
                    variant_id: int | None, stock_state: str) -> str:
    raw = f"{doc_type}:{doc_id}:{product_id}:{variant_id or 0}:{stock_state}"
    return f"{doc_type}:{hashlib.sha1(raw.encode()).hexdigest()}"[:120]


def build_txn(req: TxnRequest, qty_before: Decimal) -> InventoryTransaction:
    if req.qty_delta == 0:
        raise ValueError("库存变动数量不能为 0")
    qty_after = qty_before + req.qty_delta
    return InventoryTransaction(
        tenant_id=req.tenant_id,
        product_id=req.product_id,
        variant_id=req.variant_id,
        warehouse_id=req.warehouse_id,
        location_id=req.location_id,
        batch_id=req.batch_id,
        serial_id=req.serial_id,
        stock_state=req.stock_state,
        qty_delta=req.qty_delta,
        qty_before=qty_before,
        qty_after=qty_after,
        unit_cost=req.unit_cost,
        amount=(req.unit_cost * req.qty_delta) if req.unit_cost is not None else None,
        doc_type=req.doc_type,
        doc_id=req.doc_id,
        idempotency_key=idempotency_key(req.doc_type, req.doc_id, req.product_id,
                                        req.variant_id, req.stock_state),
        operator_id=req.operator_id,
        reason=req.reason,
        unallocated=1 if req.unallocated else 0,
    )
