"""Local product stock compensation helpers.

Stock is decremented when checkout succeeds. When a reserved instance is
confirmed failed/released, this module adds one unit back once per instance.
"""
from datetime import datetime, timezone
from typing import Any

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.instance import Instance
from app.models.product import Product, StockPolicy

RESTOCK_MARKER_KEY = "local_stock_restock"
CHECKOUT_STOCK_KEY = "local_stock_checkout"


def _enum_value(value: Any) -> str:
    return value.value if hasattr(value, "value") else str(value)


def _payload_dict(instance: Instance) -> dict[str, Any]:
    return dict(instance.upstream_payload) if isinstance(instance.upstream_payload, dict) else {}


def _stock_was_decremented(instance: Instance, product: Product) -> bool:
    payload = _payload_dict(instance)
    checkout_stock = payload.get(CHECKOUT_STOCK_KEY)
    if isinstance(checkout_stock, dict) and "decremented" in checkout_stock:
        return bool(checkout_stock.get("decremented"))
    return _enum_value(product.stock_policy) == StockPolicy.TRACKED.value


def mark_checkout_stock_state(instance: Instance, *, decremented: bool, product_id: int) -> None:
    payload = _payload_dict(instance)
    payload[CHECKOUT_STOCK_KEY] = {
        "decremented": bool(decremented),
        "product_id": int(product_id),
    }
    instance.upstream_payload = payload


async def restock_released_instances(
    db: AsyncSession,
    instances: list[Instance],
    *,
    source: str,
    reason: str | None = None,
    refund_no: str | None = None,
) -> dict[str, Any]:
    pending: list[Instance] = []
    summary: dict[str, Any] = {
        "checked": 0,
        "restocked": 0,
        "deduped": 0,
        "skipped": 0,
        "products": {},
    }

    for instance in instances:
        summary["checked"] += 1
        payload = _payload_dict(instance)
        if payload.get(RESTOCK_MARKER_KEY):
            summary["deduped"] += 1
            continue
        pending.append(instance)

    product_ids = sorted({int(instance.product_id) for instance in pending if instance.product_id})
    if not product_ids:
        return summary

    product_result = await db.execute(
        select(Product)
        .where(Product.id.in_(product_ids))
        .order_by(Product.id.asc())
        .with_for_update()
        .execution_options(populate_existing=True)
    )
    products = {int(product.id): product for product in product_result.scalars().all()}
    now = datetime.now(timezone.utc).isoformat()

    for instance in pending:
        product = products.get(int(instance.product_id))
        if not product:
            summary["skipped"] += 1
            continue
        if _enum_value(product.stock_policy) != StockPolicy.TRACKED.value:
            summary["skipped"] += 1
            continue
        if not _stock_was_decremented(instance, product):
            summary["skipped"] += 1
            continue

        product.stock = max(0, int(product.stock or 0)) + 1
        payload = _payload_dict(instance)
        payload[RESTOCK_MARKER_KEY] = {
            "at": now,
            "source": source,
            "reason": reason,
            "refund_no": refund_no,
            "product_id": int(product.id),
            "quantity": 1,
        }
        instance.upstream_payload = payload

        product_key = str(product.id)
        products_summary = summary["products"]
        products_summary[product_key] = int(products_summary.get(product_key, 0)) + 1
        summary["restocked"] += 1

    if summary["restocked"]:
        await db.flush()
    return summary
