class PembayaranFormService:
    def show_credit_form(
        self,
        view,
        total_awal,
        ppn_value,
        connect_signal_once,
        recalculate_callback,
        reset_verifikasi_callback,
        on_percent_changed_callback=None,
        on_nominal_changed_callback=None,
    ):
        total_text = view.format_rupiah(total_awal)
        view.input_total_credit.setText(total_text)
        view.ppn_credit.setText(str(ppn_value))
        view.input_no_kartu_credit.setText("")
        view.input_approval_credit.setText("")
        connect_signal_once(
            view.diskon_tambahan_credit.textChanged,
            on_percent_changed_callback or recalculate_callback,
        )
        connect_signal_once(view.diskon_tambahan_credit.valueChanged, reset_verifikasi_callback)
        connect_signal_once(
            view.diskon_tambahan_rp_credit.textChanged,
            on_nominal_changed_callback or recalculate_callback,
        )
        connect_signal_once(view.ppn_credit.textChanged, recalculate_callback)
        recalculate_callback()
        view.diskon_tambahan_credit.setFocus()

    def show_debit_form(
        self,
        view,
        total_awal,
        ppn_value,
        connect_signal_once,
        recalculate_callback,
        reset_verifikasi_callback,
        on_percent_changed_callback=None,
        on_nominal_changed_callback=None,
    ):
        total_text = view.format_rupiah(total_awal)
        view.input_total_debit.setText(total_text)
        view.ppn_debit.setText(str(ppn_value))
        view.input_no_kartu_debit.setText("")
        view.input_approval_debit.setText("")
        connect_signal_once(
            view.diskon_tambahan_debit.textChanged,
            on_percent_changed_callback or recalculate_callback,
        )
        connect_signal_once(view.diskon_tambahan_debit.valueChanged, reset_verifikasi_callback)
        connect_signal_once(
            view.diskon_tambahan_rp_debit.textChanged,
            on_nominal_changed_callback or recalculate_callback,
        )
        connect_signal_once(view.ppn_debit.textChanged, recalculate_callback)
        recalculate_callback()
        view.diskon_tambahan_debit.setFocus()

    def show_tunai_form(
        self,
        view,
        total_awal,
        ppn_value,
        connect_signal_once,
        recalculate_callback,
        reset_verifikasi_callback,
        hitung_kembalian_callback,
        on_percent_changed_callback=None,
        on_nominal_changed_callback=None,
    ):
        total_text = view.format_rupiah(total_awal)
        view.input_total_tunai.setText(total_text)
        view.ppn_tunai.setText(str(ppn_value))
        view.input_kembalian_tunai.setText("")
        view.input_total_harus_dibayar_tunai.setText("")
        connect_signal_once(
            view.diskon_tambahan_tunai.valueChanged,
            on_percent_changed_callback or recalculate_callback,
        )
        connect_signal_once(view.diskon_tambahan_tunai.valueChanged, reset_verifikasi_callback)
        connect_signal_once(
            view.diskon_tambahan_rp_tunai.textChanged,
            on_nominal_changed_callback or recalculate_callback,
        )
        connect_signal_once(view.input_bayar_tunai.textChanged, hitung_kembalian_callback)
        recalculate_callback()
        view.input_bayar_tunai.setFocus()

    def calculate_total_harus_dibayar_by_mode(
        self,
        mode,
        view,
        mode_service,
        parse_rupiah_callback,
        calculation_service,
        ppn_percent,
        ppn_mode,
        apply_voucher_callback,
        set_breakdown_callback,
        get_diskon_source_callback=None,
        log_debug_callback=None,
        log_error_callback=None,
    ):
        try:
            total_widget = mode_service.get_total_widget(view, mode)
            diskon_widget = mode_service.get_diskon_widget(view, mode)
            diskon_nilai_widget = mode_service.get_diskon_nilai_widget(view, mode)
            ppn_widget = mode_service.get_ppn_widget(view, mode)
            harus_bayar_widget = mode_service.get_harus_dibayar_widget(view, mode)
            if (
                total_widget is None
                or diskon_widget is None
                or diskon_nilai_widget is None
                or ppn_widget is None
                or harus_bayar_widget is None
            ):
                return

            total = parse_rupiah_callback(total_widget.text())
            diskon_persen = int(diskon_widget.value())
            diskon_nilai_manual = float(parse_rupiah_callback(diskon_nilai_widget.text()))
            diskon_source = (
                get_diskon_source_callback(mode)
                if callable(get_diskon_source_callback)
                else "percent"
            )
            prefer_diskon_nilai = str(diskon_source or "percent").strip().lower() == "nominal"
            calc = calculation_service.calculate(
                total_awal=total,
                diskon_persen=diskon_persen,
                ppn_persen=ppn_percent,
                diskon_nilai=diskon_nilai_manual,
                prefer_diskon_nilai=prefer_diskon_nilai,
                voucher_amount=0.0,
                ppn_mode=ppn_mode,
            )
            total_sebelum_voucher = float(calc["total_sebelum_voucher"])
            total_nilai = apply_voucher_callback(total_sebelum_voucher)
            voucher_nilai = max(0.0, total_sebelum_voucher - total_nilai)
            ppn_widget.setText(view.format_rupiah(calc["ppn_nilai"]))
            set_breakdown_callback(
                mode=mode,
                diskon_nilai=calc["diskon_nilai"],
                voucher_nilai=voucher_nilai,
                sync_nominal=not prefer_diskon_nilai,
            )
            if callable(log_debug_callback):
                log_debug_callback(
                    f"[{mode.upper()}] diskon%={calc.get('diskon_persen_efektif', diskon_persen):.2f}, "
                    f"ppn={calc['ppn_nilai']}, total_harus_dibayar={total_nilai}"
                )
            harus_bayar_widget.setText(view.format_rupiah(total_nilai))
            if mode == "tunai":
                view.input_bayar_tunai.setText(view.format_rupiah(total_nilai))
        except (TypeError, ValueError, AttributeError, KeyError, RuntimeError) as e:
            if callable(log_error_callback):
                log_error_callback(f"Error hitung_total_harus_dibayar_{mode}: {e}")
            set_breakdown_callback(mode=mode, diskon_nilai=0, voucher_nilai=0, sync_nominal=True)
            harus_bayar_widget = mode_service.get_harus_dibayar_widget(view, mode)
            if harus_bayar_widget is not None:
                harus_bayar_widget.setText("0")
            if mode == "tunai":
                view.input_bayar_tunai.setText("0")
