"""Location hierarchy and putaway rule selection."""
from fastapi import HTTPException
from sqlalchemy import text


def validate_parent_location(child_tenant: int, child_warehouse: int,
                             parent_tenant: int, parent_warehouse: int) -> None:
    if int(child_tenant) != int(parent_tenant) or int(child_warehouse) != int(parent_warehouse):
        raise HTTPException(status_code=400, detail="上级库位必须属于同一租户和仓库")


def choose_putaway_location(rules: list[dict], *, product_id: int,
                            category_id: int | None) -> int | None:
    candidates = []
    for rule in rules:
        rule_product = int(rule.get("product_id") or 0)
        rule_category = int(rule.get("category_id") or 0)
        if rule_product and rule_product != int(product_id):
            continue
        if rule_category and rule_category != int(category_id or 0):
            continue
        specificity = 0 if rule_product else (1 if rule_category else 2)
        candidates.append((specificity, int(rule.get("priority") or 100), int(rule["destination_location_id"])))
    return min(candidates)[2] if candidates else None


async def validate_parent(db, tenant_id: int, warehouse_id: int, parent_id: int | None,
                          child_id: int | None = None) -> None:
    if not parent_id:
        return
    current = int(parent_id)
    visited = set()
    while current:
        if current == child_id or current in visited:
            raise HTTPException(status_code=400, detail="库位层级不能形成循环")
        visited.add(current)
        row = (await db.execute(
            text("SELECT tenant_id,warehouse_id,parent_id FROM inventory_locations "
                 "WHERE id=:id AND tenant_id=:tid AND is_active=1 FOR UPDATE"),
            {"id": current, "tid": tenant_id},
        )).fetchone()
        if row is None:
            raise HTTPException(status_code=400, detail="上级库位不存在或已停用")
        validate_parent_location(tenant_id, warehouse_id, int(row[0]), int(row[1]))
        current = int(row[2] or 0)


async def resolve_putaway_location(db, tenant_id: int, warehouse_id: int,
                                   product_id: int) -> int:
    product = (await db.execute(
        text("SELECT category_id FROM products WHERE id=:id AND tenant_id=:tid"),
        {"id": product_id, "tid": tenant_id},
    )).fetchone()
    if product is None:
        raise HTTPException(status_code=400, detail="商品不存在或不属于当前租户")
    rows = (await db.execute(
        text("SELECT r.destination_location_id,r.product_id,r.category_id,r.priority "
             "FROM inventory_putaway_rules r JOIN inventory_locations l "
             "ON l.id=r.destination_location_id AND l.tenant_id=r.tenant_id "
             "WHERE r.tenant_id=:tid AND r.warehouse_id=:wh AND r.is_active=1 AND l.is_active=1"),
        {"tid": tenant_id, "wh": warehouse_id},
    )).fetchall()
    rules = [{"destination_location_id": row[0], "product_id": row[1],
              "category_id": row[2], "priority": row[3]} for row in rows]
    destination = choose_putaway_location(rules, product_id=product_id, category_id=product[0])
    if destination:
        return destination
    default_id = (await db.execute(
        text("SELECT id FROM inventory_locations WHERE tenant_id=:tid AND warehouse_id=:wh "
             "AND is_default=1 AND is_active=1 ORDER BY id LIMIT 1"),
        {"tid": tenant_id, "wh": warehouse_id},
    )).scalar()
    if not default_id:
        raise HTTPException(status_code=400, detail="仓库没有可用的默认库位或上架规则")
    return int(default_id)
