# edited by glg
from pypos.modules.penjualan.services.transaksi_payment_persist_use_case_service import (
    TransaksiPaymentPersistUseCaseService,
)
from pypos.modules.penjualan.services.transaksi_persist_ui_use_case_service import (
    TransaksiPersistUiUseCaseService,
)

import pytest

pytestmark = [pytest.mark.unit]


class _PersistServiceStub:
    def __init__(self, result):
        self.result = result

    def persist(self, **_kwargs):
        return self.result


def test_run_persist_failure_mengembalikan_false_dan_show_error():
    service = TransaksiPaymentPersistUseCaseService()
    persist_ui_service = TransaksiPersistUiUseCaseService()
    persist_service = _PersistServiceStub(
        {
            "ok": False,
            "error": {
                "error_code": "TRX_SAVE_DB_ERROR",
                "message": "Gagal menyimpan transaksi ke database.",
                "reason": "db_error",
                "trace_id": "trx-trace-1",
                "error": "sqlite_fail",
            },
        }
    )

    logs = []
    shown_errors = []
    reset_calls = []
    clear_calls = []

    ok = service.run_persist(
        persist_service=persist_service,
        persist_ui_use_case_service=persist_ui_service,
        transaksi_data=[],
        detail_data=[],
        transaksi_data_dict={},
        metode_text="TUNAI",
        audit_message="unit_test",
        log_error_callback=logs.append,
        show_error_callback=lambda title, message: shown_errors.append((title, message)),
        reset_form_callback=lambda: reset_calls.append(True),
        clear_preorder_callback=lambda: clear_calls.append(True),
    )

    assert ok is False
    assert logs
    assert "TRX_SAVE_DB_ERROR" in logs[0]
    assert "trace_id=trx-trace-1" in logs[0]
    assert shown_errors
    assert "Kode: TRX_SAVE_DB_ERROR" in shown_errors[0][1]
    assert reset_calls == []
    assert clear_calls == []


def test_run_persist_success_mengupdate_quota_schedule_print_dan_reset():
    service = TransaksiPaymentPersistUseCaseService()
    persist_ui_service = TransaksiPersistUiUseCaseService()
    persist_service = _PersistServiceStub(
        {
            "ok": True,
            "transaksi_id": 77,
            "arr_free_produk": [{"free_produk_nama": "Bonus A", "free_qty": 1}],
            "free_items_summary": [{"nama": "Bonus A", "qty": 1}],
            "trace_id": "trx-trace-2",
            "idempotent_replay": False,
        }
    )

    transaksi_data_dict = {"oleh_nama": "Kasir"}
    quota_calls = []
    print_calls = []
    info_logs = []
    infos = []
    reset_calls = []
    clear_calls = []

    ok = service.run_persist(
        persist_service=persist_service,
        persist_ui_use_case_service=persist_ui_service,
        transaksi_data=["trx"],
        detail_data=["detail"],
        transaksi_data_dict=transaksi_data_dict,
        metode_text="QRIS",
        audit_message="unit_test",
        update_quota_callback=lambda arr: quota_calls.append(list(arr or [])),
        schedule_print_callback=lambda trx, detail, data: print_calls.append((trx, detail, dict(data or {}))),
        log_info_callback=info_logs.append,
        show_info_callback=lambda title, message: infos.append((title, message)),
        reset_form_callback=lambda: reset_calls.append(True),
        clear_preorder_callback=lambda: clear_calls.append(True),
    )

    assert ok is True
    assert transaksi_data_dict.get("free_items_summary") == [{"nama": "Bonus A", "qty": 1}]
    assert quota_calls == [[{"free_produk_nama": "Bonus A", "free_qty": 1}]]
    assert len(print_calls) == 1
    assert print_calls[0][0] == ["trx"]
    assert print_calls[0][1] == ["detail"]
    assert "free_items_summary" in print_calls[0][2]
    assert info_logs and "transaksi_id=77" in info_logs[0]
    assert infos and "Metode: QRIS" in infos[0][1]
    assert reset_calls == [True]
    assert clear_calls == [True]


def test_run_persist_success_idempotent_replay_tidak_show_info():
    service = TransaksiPaymentPersistUseCaseService()
    persist_ui_service = TransaksiPersistUiUseCaseService()
    persist_service = _PersistServiceStub(
        {
            "ok": True,
            "transaksi_id": 88,
            "arr_free_produk": [],
            "free_items_summary": [],
            "trace_id": "trx-trace-3",
            "idempotent_replay": True,
        }
    )

    infos = []
    ok = service.run_persist(
        persist_service=persist_service,
        persist_ui_use_case_service=persist_ui_service,
        transaksi_data=[],
        detail_data=[],
        transaksi_data_dict={},
        metode_text="TUNAI",
        audit_message="unit_test",
        show_success_dialog=True,
        show_info_callback=lambda title, message: infos.append((title, message)),
        reset_form_callback=lambda: None,
        clear_preorder_callback=lambda: None,
    )

    assert ok is True
    assert infos == []


def test_run_persist_success_callback_menggantikan_dialog_sukses():
    service = TransaksiPaymentPersistUseCaseService()
    persist_ui_service = TransaksiPersistUiUseCaseService()
    persist_service = _PersistServiceStub(
        {
            "ok": True,
            "transaksi_id": 99,
            "arr_free_produk": [],
            "free_items_summary": [],
            "trace_id": "",
            "idempotent_replay": False,
        }
    )

    callback_ids = []
    infos = []

    ok = service.run_persist(
        persist_service=persist_service,
        persist_ui_use_case_service=persist_ui_service,
        transaksi_data=[],
        detail_data=[],
        transaksi_data_dict={},
        metode_text="TUNAI",
        audit_message="unit_test",
        success_callback=lambda tid: callback_ids.append(int(tid or 0)),
        show_info_callback=lambda title, message: infos.append((title, message)),
        reset_form_callback=lambda: None,
        clear_preorder_callback=lambda: None,
    )

    assert ok is True
    assert callback_ids == [99]
    assert infos == []
