# edited by glg
from typing import Any, Callable, Dict


class TransaksiBarangMutationUseCaseService:
    """
    Use-case service untuk keputusan mutasi barang di keranjang transaksi.
    Fokus service ini pada keputusan domain (plan), bukan side-effect UI.
    """

    @staticmethod
    def _to_int(value, default=0) -> int:
        try:
            return int(value)
        except (TypeError, ValueError):
            return int(default)

    def build_apply_plan(
        self,
        *,
        id_barang,
        tambahan_qty,
        find_barang_row_callback: Callable[[str], Any],
        compute_total_qty_callback: Callable[[Any, Any], int],
        ensure_admin_authorized_callback: Callable[[str, int], bool],
        find_barang_detail_callback: Callable[[str, int], Dict[str, Any]],
        is_valid_harga_callback: Callable[[Dict[str, Any]], bool],
    ) -> Dict[str, Any]:
        pid = str(id_barang or "").strip()
        existing_row, jumlah_lama = find_barang_row_callback(pid)
        jumlah_total = int(compute_total_qty_callback(tambahan_qty, jumlah_lama))

        if not bool(ensure_admin_authorized_callback(pid, jumlah_total)):
            return {
                "ok": False,
                "reason": "admin_rejected",
                "id_barang": pid,
                "existing_row": existing_row,
                "jumlah_total": jumlah_total,
                "barang_detail": {},
            }

        barang_detail = find_barang_detail_callback(pid, jumlah_total)
        if not bool(is_valid_harga_callback(barang_detail)):
            return {
                "ok": False,
                "reason": "invalid_harga",
                "id_barang": pid,
                "existing_row": existing_row,
                "jumlah_total": jumlah_total,
                "barang_detail": barang_detail if isinstance(barang_detail, dict) else {},
            }

        return {
            "ok": True,
            "reason": "ok",
            "id_barang": pid,
            "existing_row": existing_row,
            "jumlah_total": jumlah_total,
            "barang_detail": barang_detail if isinstance(barang_detail, dict) else {},
        }

    def build_manual_qty_plan(
        self,
        *,
        id_barang,
        prev_qty,
        qty_text,
        normalize_manual_qty_callback: Callable[[Any], Any],
        ensure_admin_authorized_callback: Callable[[str, int], bool],
        find_barang_detail_callback: Callable[[str, int], Dict[str, Any]],
        is_valid_harga_callback: Callable[[Dict[str, Any]], bool],
    ) -> Dict[str, Any]:
        pid = str(id_barang or "").strip()
        prev_qty_int = self._to_int(prev_qty, 1)
        is_valid_qty, jumlah = normalize_manual_qty_callback(qty_text)
        jumlah_int = self._to_int(jumlah, 0)
        if not bool(is_valid_qty):
            return {
                "ok": False,
                "reason": "invalid_qty",
                "id_barang": pid,
                "revert_qty": 1,
                "jumlah": 0,
                "barang_detail": {},
            }

        if int(jumlah_int) == int(prev_qty_int):
            return {
                "ok": False,
                "reason": "no_change",
                "id_barang": pid,
                "revert_qty": prev_qty_int,
                "jumlah": jumlah_int,
                "barang_detail": {},
            }

        if not bool(ensure_admin_authorized_callback(pid, jumlah_int)):
            return {
                "ok": False,
                "reason": "admin_rejected",
                "id_barang": pid,
                "revert_qty": prev_qty_int,
                "jumlah": jumlah_int,
                "barang_detail": {},
            }

        barang_detail = find_barang_detail_callback(pid, jumlah_int)
        if not bool(is_valid_harga_callback(barang_detail)):
            return {
                "ok": False,
                "reason": "invalid_harga",
                "id_barang": pid,
                "revert_qty": prev_qty_int,
                "jumlah": jumlah_int,
                "barang_detail": barang_detail if isinstance(barang_detail, dict) else {},
            }

        return {
            "ok": True,
            "reason": "ok",
            "id_barang": pid,
            "revert_qty": prev_qty_int,
            "jumlah": jumlah_int,
            "barang_detail": barang_detail if isinstance(barang_detail, dict) else {},
        }
