# edited by glg
import pytest

from pypos.modules.penjualan.services.transaksi_autocomplete_async_use_case_service import (
    TransaksiAutocompleteAsyncUseCaseService,
)

pytestmark = [pytest.mark.unit]


def test_build_fetch_payload_success():
    payload = TransaksiAutocompleteAsyncUseCaseService.build_fetch_payload(
        keyword="kopi",
        limit=5,
        lookup_started=1.0,
        fetch_callback=lambda keyword, limit: ([f"{keyword}-{limit}"], {f"{keyword}-{limit}": {"id": 1}}),
    )

    assert payload["ok"] is True
    assert payload["keyword"] == "kopi"
    assert payload["barang_list"] == ["kopi-5"]
    assert "kopi-5" in payload["mapping"]


def test_build_fetch_payload_error():
    payload = TransaksiAutocompleteAsyncUseCaseService.build_fetch_payload(
        keyword="kopi",
        limit=5,
        lookup_started=1.0,
        fetch_callback=lambda _keyword, _limit: (_ for _ in ()).throw(RuntimeError("db_fail")),
    )

    assert payload["ok"] is False
    assert payload["barang_list"] == []
    assert "db_fail" in str(payload["error"] or "")


def test_apply_ready_payload_stale_request_diabaikan():
    mapping_box = {"value": {"lama": {"id": 9}}}
    rows_box = {"value": ["lama"]}
    perf_calls = []
    warns = []

    applied = TransaksiAutocompleteAsyncUseCaseService.apply_ready_payload(
        request_id=1,
        payload={
            "keyword": "kopi",
            "barang_list": ["kopi-1"],
            "mapping": {"kopi-1": {"id": 1}},
            "lookup_started": 1.0,
            "ok": True,
        },
        is_latest_request_callback=lambda _rid: False,
        set_mapping_callback=lambda mapping: mapping_box.update(value=mapping),
        set_autocomplete_callback=lambda rows: rows_box.update(value=list(rows or [])),
        record_perf_callback=lambda *args, **kwargs: perf_calls.append((args, kwargs)),
        log_warning_callback=warns.append,
    )

    assert applied is False
    assert mapping_box["value"] == {"lama": {"id": 9}}
    assert rows_box["value"] == ["lama"]
    assert perf_calls == []
    assert warns == []


def test_apply_ready_payload_success_dan_warning_saat_error():
    mapping_box = {"value": {}}
    rows_box = {"value": []}
    perf_calls = []
    warns = []

    applied = TransaksiAutocompleteAsyncUseCaseService.apply_ready_payload(
        request_id=2,
        payload={
            "keyword": "teh",
            "barang_list": ["teh-1"],
            "mapping": {"teh-1": {"id": 2}},
            "lookup_started": 2.0,
            "ok": False,
            "error": "timeout",
        },
        is_latest_request_callback=lambda rid: int(rid) == 2,
        set_mapping_callback=lambda mapping: mapping_box.update(value=mapping),
        set_autocomplete_callback=lambda rows: rows_box.update(value=list(rows or [])),
        record_perf_callback=lambda *args, **kwargs: perf_calls.append((args, kwargs)),
        log_warning_callback=warns.append,
    )

    assert applied is True
    assert "teh-1" in mapping_box["value"]
    assert rows_box["value"] == ["teh-1"]
    assert len(perf_calls) == 2
    assert warns
    assert "Autocomplete barang gagal" in warns[0]


def test_submit_async_fetch_memakai_emit_callback_jika_tersedia():
    emitted = []

    def _submit(_key, worker):
        worker()
        return object()

    TransaksiAutocompleteAsyncUseCaseService.submit_async_fetch(
        owner_id=10,
        request_id=3,
        keyword="gula",
        limit=5,
        lookup_started=3.0,
        fetch_callback=lambda keyword, limit: ([f"{keyword}-{limit}"], {f"{keyword}-{limit}": {"id": 3}}),
        emit_callback=lambda req_id, payload: emitted.append((int(req_id), dict(payload))),
        on_ready_callback=lambda *_args, **_kwargs: emitted.append(("ready", {})),
        submit_task_callback=_submit,
    )

    assert emitted
    assert emitted[0][0] == 3
    assert emitted[0][1]["keyword"] == "gula"
