# edited by glg
import sqlite3


class TransaksiPaymentPersistUseCaseService:
    """
    Use-case service untuk orkestrasi persist transaksi berbasis UI flow.
    Controller cukup memasok callback side-effect agar coupling menurun.
    """

    @staticmethod
    def _call(callback, *args, **kwargs):
        if callable(callback):
            return callback(*args, **kwargs)
        return None

    def run_persist(
        self,
        *,
        persist_service,
        persist_ui_use_case_service,
        transaksi_data,
        detail_data,
        transaksi_data_dict,
        metode_text,
        audit_message,
        voucher_callback=None,
        success_callback=None,
        show_success_dialog=True,
        update_quota_callback=None,
        schedule_print_callback=None,
        log_error_callback=None,
        log_info_callback=None,
        show_error_callback=None,
        show_info_callback=None,
        reset_form_callback=None,
        clear_preorder_callback=None,
    ) -> bool:
        # edited by glg
        # Fail-safe boundary: exception dari flow persist tidak boleh membocorkan traceback ke UI slot.
        try:
            result = persist_ui_use_case_service.execute(
                persist_service=persist_service,
                transaksi_data=transaksi_data,
                detail_data=detail_data,
                transaksi_data_dict=transaksi_data_dict,
                metode_text=metode_text,
                audit_message=audit_message,
                voucher_callback=voucher_callback,
            )
        except (sqlite3.Error, RuntimeError, TypeError, ValueError, KeyError, AttributeError) as exc:
            error_code = "TRX_SAVE_FLOW_UNHANDLED"
            self._call(
                log_error_callback,
                f"Gagal simpan transaksi pembayaran [{error_code}]: {exc}",
            )
            self._call(
                show_error_callback,
                "Simpan Transaksi",
                f"{exc}\nKode: {error_code}",
            )
            return False
        if not bool((result or {}).get("ok")):
            error_payload = persist_ui_use_case_service.normalize_error_payload(result)
            error_code = error_payload["error_code"]
            error_message = error_payload["error_message"]
            trace_id = error_payload["trace_id"]
            reason = error_payload["reason"]
            raw_error = error_payload["raw_error"]
            if trace_id:
                self._call(
                    log_error_callback,
                    f"Gagal simpan transaksi pembayaran [{error_code}] trace_id={trace_id}: "
                    f"{raw_error or error_message} reason={reason}",
                )
            else:
                self._call(
                    log_error_callback,
                    f"Gagal simpan transaksi pembayaran [{error_code}]: "
                    f"{raw_error or error_message} reason={reason}",
                )
            self._call(
                show_error_callback,
                "Simpan Transaksi",
                f"{error_message}\nKode: {error_code}",
            )
            return False

        success_payload = persist_ui_use_case_service.normalize_success_payload(result)
        transaksi_id = success_payload["transaksi_id"]
        arr_free_produk = success_payload["arr_free_produk"]
        if isinstance(transaksi_data_dict, dict):
            transaksi_data_dict["free_items_summary"] = success_payload["free_items_summary"]
        trace_id = success_payload["trace_id"]

        self._call(update_quota_callback, arr_free_produk)
        self._call(schedule_print_callback, transaksi_data, detail_data, transaksi_data_dict)
        if trace_id:
            self._call(log_info_callback, f"Simpan transaksi sukses transaksi_id={transaksi_id} trace_id={trace_id}")
        if callable(success_callback):
            success_callback(transaksi_id)
        elif show_success_dialog and not bool(success_payload["idempotent_replay"]):
            self._call(
                show_info_callback,
                "Sukses",
                f"Transaksi #{transaksi_id} berhasil disimpan!\nMetode: {metode_text}",
            )
        self._call(reset_form_callback)
        self._call(clear_preorder_callback)
        return True
