# edited by glg
import os
from datetime import date

os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")

from PySide6.QtWidgets import QApplication, QMessageBox

from pypos.modules.penjualan.views.pembatalan_transaksi_view import (
    PembatalanTransaksiView,
)


def _qapp():
    app = QApplication.instance()
    if app is None:
        app = QApplication([])
    return app


class _ControllerStub:
    def __init__(self, rows=None, cancel_result=(False, "Transaksi sudah disettle dan tidak dapat dibatalkan.")):
        self._rows = list(rows or [])
        self._cancel_result = tuple(cancel_result)
        self.cancel_calls = []
        self.verify_calls = 0

    def load_transaksi(self, keyword=""):
        _ = keyword
        return list(self._rows)

    def get_allowed_date_range(self):
        today = date.today()
        return today, today

    def verifikasi_admin_pembatalan(self, _parent=None):
        self.verify_calls += 1
        return "admin-qa"

    def batalkan_transaksi(self, transaksi_id, admin_name=""):
        self.cancel_calls.append((str(transaksi_id), str(admin_name)))
        return self._cancel_result


def _sample_row(trx_id=101):
    return {
        "id": trx_id,
        "nomer": f"INV-{trx_id}",
        "dtime": "2026-03-08 10:10:10",
        "customers_nama": "Cust",
        "kasir_nama": "Kasir",
        "jumlah_item": 2,
        "transaksi_nilai": 120000,
    }


def test_gui_pembatalan_warning_jika_belum_pilih_transaksi(monkeypatch):
    _qapp()
    warnings = []
    monkeypatch.setattr(QMessageBox, "warning", lambda *args, **kwargs: warnings.append((args, kwargs)))

    view = PembatalanTransaksiView(_ControllerStub(rows=[]))
    view.btn_batalkan.click()

    assert warnings, "Harus muncul warning jika transaksi belum dipilih."
    assert "Pilih transaksi yang akan dibatalkan." in str(warnings[-1][0][2])
    view.close()


def test_gui_pembatalan_tampil_warning_saat_controller_menolak_settled(monkeypatch):
    _qapp()
    warnings = []
    infos = []
    monkeypatch.setattr(QMessageBox, "exec", lambda self: QMessageBox.Yes)
    monkeypatch.setattr(QMessageBox, "warning", lambda *args, **kwargs: warnings.append((args, kwargs)))
    monkeypatch.setattr(QMessageBox, "information", lambda *args, **kwargs: infos.append((args, kwargs)))

    controller = _ControllerStub(
        rows=[_sample_row(201)],
        cancel_result=(False, "Transaksi sudah disettle dan tidak dapat dibatalkan."),
    )
    view = PembatalanTransaksiView(controller)

    view._on_row_clicked(0, 0)
    view.btn_batalkan.click()

    assert controller.verify_calls == 1
    assert controller.cancel_calls == [("201", "admin-qa")]
    assert warnings, "Harus menampilkan warning ketika controller menolak pembatalan."
    assert "Transaksi sudah disettle dan tidak dapat dibatalkan." in str(warnings[-1][0][2])
    assert not infos
    view.close()


def test_gui_pembatalan_sukses_refresh_dan_info(monkeypatch):
    _qapp()
    warnings = []
    infos = []
    monkeypatch.setattr(QMessageBox, "exec", lambda self: QMessageBox.Yes)
    monkeypatch.setattr(QMessageBox, "warning", lambda *args, **kwargs: warnings.append((args, kwargs)))
    monkeypatch.setattr(QMessageBox, "information", lambda *args, **kwargs: infos.append((args, kwargs)))

    controller = _ControllerStub(
        rows=[_sample_row(301)],
        cancel_result=(True, "Transaksi berhasil dibatalkan."),
    )
    view = PembatalanTransaksiView(controller)

    # Spy refresh_data agar bisa memastikan dipanggil setelah sukses.
    refresh_counter = {"count": 0}
    original_refresh = view.refresh_data

    def _refresh_spy():
        refresh_counter["count"] += 1
        return original_refresh()

    view.refresh_data = _refresh_spy
    view._on_row_clicked(0, 0)
    view.btn_batalkan.click()

    assert controller.verify_calls == 1
    assert controller.cancel_calls == [("301", "admin-qa")]
    assert infos, "Harus menampilkan info saat pembatalan sukses."
    assert "Transaksi berhasil dibatalkan." in str(infos[-1][0][2])
    assert refresh_counter["count"] >= 1
    assert not warnings
    view.close()
