from pypos.core.base_view import BaseView
from PySide6.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QPushButton,
    QTableWidget, QTableWidgetItem, QLabel, QMessageBox, QDateEdit, QComboBox, QTextBrowser
)
from PySide6.QtCore import QDate, Qt, QTimer, Signal
from PySide6.QtGui import QGuiApplication
import logging
from pypos.modules.penjualan.common.history_detail_render import (
    HistoryDetailRenderService,
)

LOGGER = logging.getLogger(__name__)

class HistoryTransaksiView(BaseView, QDialog):
    # edited by glg
    # Signal lintas-thread untuk mengirim payload detail transaksi dari worker ke UI thread.
    detail_payload_ready = Signal(int, object)
    # edited by glg
    # Signal lintas-thread untuk refresh daftar history transaksi.
    history_payload_ready = Signal(int, object)

    def __init__(self, controller, parent=None, as_page=False, on_close_requested=None):
        super().__init__(parent)
        self.controller = controller
        self.is_page = bool(as_page)
        self._on_close_requested = on_close_requested
        self._detail_ready_handler = None
        self._history_ready_handler = None
        # edited by glg
        # Debounce navigasi keyboard agar currentCellChanged tidak menembak query detail berkali-kali.
        self._selection_preview_timer = QTimer(self)
        self._selection_preview_timer.setSingleShot(True)
        self._selection_preview_timer.setInterval(140)
        self._selection_preview_timer.timeout.connect(self._emit_current_cell_selection)
        self._pending_selection_row = -1
        self._pending_selection_col = -1
        # edited by glg
        # Debounce filter pencarian agar loop hide/show row tidak dipanggil setiap ketikan.
        self._search_filter_timer = QTimer(self)
        self._search_filter_timer.setSingleShot(True)
        self._search_filter_timer.setInterval(260)
        self._search_filter_timer.timeout.connect(self._apply_scheduled_search_filter)
        self._pending_search_text = ""
        # edited by glg
        self.detail_render_service = HistoryDetailRenderService(
            log_debug=LOGGER.debug,
            log_warning=LOGGER.warning,
        )
        self.detail_payload_ready.connect(self._on_detail_payload_ready, Qt.QueuedConnection)
        self.history_payload_ready.connect(self._on_history_payload_ready, Qt.QueuedConnection)
        if self.is_page:
            self.setWindowFlags(Qt.Widget)
        else:
            self.setWindowTitle("History Transaksi")
            from pypos.core.utils.window_size_helper import set_window_size_by_screen
            set_window_size_by_screen(self, percent=0.7, min_size=(800, 520))
            screen = QGuiApplication.primaryScreen()
            if screen:
                available_geo = screen.availableGeometry()
                self.setMaximumSize(available_geo.width(), available_geo.height())

        self.layout = QVBoxLayout()

        self.filter_layout = QHBoxLayout()

        from PySide6.QtWidgets import QLineEdit
        self.search_box = QLineEdit()
        self.search_box.setPlaceholderText("\U0001F50D Cari nomor invoice / kasir / customer...")
        self.search_box.setMaximumWidth(300)
        self.search_box.textChanged.connect(self._schedule_search_filter)
        self.filter_layout.addWidget(self.search_box)
        self.filter_layout.addWidget(QLabel("Dari:"))
        self.start_date_edit = QDateEdit()
        self.start_date_edit.setCalendarPopup(True)
        self.start_date_edit.setDate(QDate.currentDate())
        self.filter_layout.addWidget(self.start_date_edit)
        self.filter_layout.addWidget(QLabel("Sampai:"))
        self.end_date_edit = QDateEdit()
        self.end_date_edit.setCalendarPopup(True)
        self.end_date_edit.setDate(QDate.currentDate())
        self.filter_layout.addWidget(self.end_date_edit)

        # Preset filter
        self.preset_combo = QComboBox()
        self.preset_combo.addItem("Hari Ini", "today")
        self.preset_combo.addItem("Kemarin", "yesterday")
        self.preset_combo.addItem("7 Hari Terakhir", "last7")
        self.preset_combo.addItem("30 Hari Terakhir", "last30")
        self.preset_combo.addItem("Custom", "custom")
        self.preset_combo.currentIndexChanged.connect(self.on_preset_changed)
        self.filter_layout.addWidget(self.preset_combo)
        self.btn_filter = QPushButton("\U0001F50D Filter")
        self.btn_filter.setProperty("class", "primary")
        self.btn_filter.clicked.connect(self.kirim_filter_tanggal)
        self.filter_layout.addWidget(self.btn_filter)
        self.filter_layout.addStretch()
        self.layout.addLayout(self.filter_layout)

        self.table = QTableWidget(0, 8)
        self.table.setHorizontalHeaderLabels(["ID", "Nomer", "Tanggal", "Kasir", "Customer", "Jml Barang", "Total Harga", "Settlement"])
        self.table.setColumnHidden(0, True)  # PATCH: Sembunyikan kolom ID
        self.table.setColumnHidden(7, True)  # PATCH: Sembunyikan kolom Settlement (gunakan warna row)
        self.table.cellClicked.connect(self.on_cell_clicked)
        self.table.currentCellChanged.connect(self.on_current_cell_changed)
        from PySide6.QtWidgets import QHeaderView
        header = self.table.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.Stretch)
        self.table.setColumnWidth(1, 180)  # Nomer invoice (shortened)
        self.table.setColumnWidth(3, 100)  # Kasir
        self.table.setColumnWidth(5, 80)   # Jumlah Barang
        self.table.setProperty("class", "history-transaksi")
        self.layout.addWidget(self.table)
        self.legend_layout = QHBoxLayout()
        self.legend_layout.addStretch()
        legend_label = QLabel("Keterangan: ")
        legend_label.setStyleSheet("font-weight: bold;")
        self.legend_layout.addWidget(legend_label)
        pending_legend = QLabel("\U0001F7E8 Pending (Belum Settlement)")
        pending_legend.setStyleSheet("padding: 4px 8px; background-color: #fff3cd; border: 1px solid #ffc107; border-radius: 3px;")
        self.legend_layout.addWidget(pending_legend)
        settled_legend = QLabel("\U0001F7E9 Settled (Sudah Settlement)")
        settled_legend.setStyleSheet("padding: 4px 8px; background-color: #d4edda; border: 1px solid #28a745; border-radius: 3px; margin-left: 8px;")
        self.legend_layout.addWidget(settled_legend)

        canceled_legend = QLabel("Dibatalkan")
        canceled_legend.setStyleSheet("padding: 4px 8px; background-color: #f8d7da; border: 1px solid #dc3545; border-radius: 3px; margin-left: 8px;")
        self.legend_layout.addWidget(canceled_legend)
        self.legend_layout.addStretch()
        self.layout.addLayout(self.legend_layout)

        self.btn_toggle_preview = QPushButton("\U0001F441\ufe0f Tampilkan Preview")
        self.btn_toggle_preview.setProperty("class", "history-toggle primary")
        self.btn_toggle_preview.clicked.connect(self.toggle_preview_section)
        self.layout.addWidget(self.btn_toggle_preview)
        self.preview_label = QLabel("\U0001F4DD Preview Detail Transaksi:")
        self.layout.addWidget(self.preview_label)
        self.info_transaksi_label = QTextBrowser()
        self.info_transaksi_label.setHtml("<p style='text-align:center; color:#999;'>Pilih transaksi untuk melihat detail</p>")
        self.info_transaksi_label.setReadOnly(True)
        self.info_transaksi_label.setOpenExternalLinks(False)
        self.info_transaksi_label.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.info_transaksi_label.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.info_transaksi_label.setLineWrapMode(QTextBrowser.WidgetWidth)
        self.info_transaksi_label.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard)
        self.info_transaksi_label.document().setDocumentMargin(0)
        self.info_transaksi_label.setMinimumHeight(200)
        self.info_transaksi_label.setMaximumHeight(300)
        self.info_transaksi_label.setStyleSheet("""
            QTextBrowser {
                border: 2px solid #17a2b8;
                border-radius: 5px;
                padding: 8px;
                background-color: white;
            }
            QTextBrowser QScrollBar:vertical {
                border: none;
                background: #f8f9fa;
                width: 8px;
                margin: 0px;
            }
            QTextBrowser QScrollBar::handle:vertical {
                background: #17a2b8;
                min-height: 20px;
                border-radius: 4px;
            }
            QTextBrowser QScrollBar::handle:vertical:hover {
                background: #138496;
            }
            QTextBrowser QScrollBar::add-line:vertical,
            QTextBrowser QScrollBar::sub-line:vertical {
                height: 0px;
            }
            QTextBrowser QScrollBar::add-page:vertical,
            QTextBrowser QScrollBar::sub-page:vertical {
                background: none;
            }
        """)
        self.layout.addWidget(self.info_transaksi_label)
        self.preview_label.setVisible(False)
        self.info_transaksi_label.setVisible(False)
        self.is_preview_visible = False
        self.btn_toggle_detail = QPushButton("\U0001F4E6 Detail Barang")
        self.btn_toggle_detail.setProperty("class", "history-toggle primary")
        self.btn_toggle_detail.clicked.connect(self.toggle_detail_view)
        self.btn_toggle_detail.setVisible(False)
        self.btn_copy_invoice = QPushButton("\U0001F4CB Copy Invoice")
        self.btn_copy_invoice.setProperty("class", "history-action primary")
        self.btn_copy_invoice.clicked.connect(self.copy_invoice_number)
        self.btn_copy_invoice.setVisible(False)
        self.btn_copy_invoice.setToolTip("Copy nomor invoice ke clipboard")
        self.btn_reprint = QPushButton("\U0001F5A8\ufe0f Print Ulang")
        self.btn_reprint.setProperty("class", "history-action primary")
        self.btn_reprint.clicked.connect(self.reprint_transaksi)
        self.btn_reprint.setVisible(False)
        self.btn_reprint.setToolTip("Print ulang struk transaksi ini")
        # Button layout
        self.button_layout = QHBoxLayout()
        self.button_layout.addWidget(self.btn_toggle_detail)
        self.button_layout.addWidget(self.btn_copy_invoice)
        self.button_layout.addWidget(self.btn_reprint)
        self.button_layout.addStretch()
        self.btn_close = QPushButton("\u274C Tutup")
        self.btn_close.setProperty("class", "history-close danger")
        self.btn_close.clicked.connect(self._handle_close_request)
        self.button_layout.addWidget(self.btn_close)
        self.layout.addLayout(self.button_layout)
        self.setLayout(self.layout)
        # State untuk toggle
        self.current_header_data = None
        self.current_detail_rows = None
        self.is_showing_items = False
        self.current_invoice_number = None  # PATCH: Simpan invoice number untuk copy

    def _handle_close_request(self):
        if callable(self._on_close_requested):
            self._on_close_requested()
            return
        if self.is_page:
            self.close()
        else:
            self.reject()

    def copy_invoice_number(self):
        """PATCH[FrontEndAgent|CopyFeature]: Copy nomor invoice ke clipboard"""
        if self.current_invoice_number:
            from PySide6.QtWidgets import QApplication
            clipboard = QApplication.clipboard()
            clipboard.setText(self.current_invoice_number)
            QMessageBox.information(self, "Berhasil", f"Nomor invoice berhasil dicopy:\n{self.current_invoice_number}")

    def reprint_transaksi(self):
        """PATCH[FrontEndAgent|ReprintFeature]: Print ulang struk transaksi yang dipilih"""
        if not self.current_header_data or not self.current_detail_rows:
            QMessageBox.warning(self, "Peringatan", "Tidak ada transaksi yang dipilih untuk di-print.")
            return

        # Panggil controller untuk print ulang
        reply = QMessageBox.question(
            self,
            "Konfirmasi Print",
            f"Print ulang struk untuk invoice:\n{self.current_invoice_number}?",
            QMessageBox.Yes | QMessageBox.No
        )
        if reply == QMessageBox.Yes:
            self.controller.print_ulang_transaksi(self.current_header_data, self.current_detail_rows)

    def render_transaksi_list(self, rows):
        """PATCH[FrontEndAgent|UXImprovement]: Render dengan format readable + highlighting"""
        from PySide6.QtGui import QColor
        from PySide6.QtCore import Qt

        # edited by glg
        # Render batch: hindari insertRow berulang agar refresh history tetap ringan.
        safe_rows = list(rows or [])
        self.table.setUpdatesEnabled(False)
        self.table.blockSignals(True)
        self.table.setRowCount(len(safe_rows))
        try:
            for row, row_data in enumerate(safe_rows):

                # row_data: [id, nomer, tanggal, customer, total, kasir_nama, settlement_id, jumlah_item, is_trash]
                transaksi_id = str(row_data[0])
                nomer_full = str(row_data[1])
                tanggal = str(row_data[2])
                customer = str(row_data[3])
                total = float(row_data[4]) if row_data[4] else 0
                kasir = str(row_data[5]) if len(row_data) > 5 else "-"
                settlement_id = int(row_data[6]) if len(row_data) > 6 else 1
                jumlah_item = int(row_data[7]) if len(row_data) > 7 else 0
                is_trash = int(row_data[8]) if len(row_data) > 8 else 0


                total_fmt = f"Rp {total:,.0f}".replace(",", ".")

                if is_trash == 1:
                    settlement_status = "Dibatalkan"
                    row_color = QColor(248, 215, 218)  # Light red
                elif settlement_id == 1:
                    settlement_status = "\u23F3 Pending"
                    row_color = QColor(255, 243, 205)  # Light orange
                else:
                    settlement_status = "\u2705 Settled"
                    row_color = QColor(212, 237, 218)  # Light green

                # Masukkan data ke tabel
                items = [
                    (0, transaksi_id),
                    (1, nomer_full),  # PATCH: Full invoice number
                    (2, tanggal),
                    (3, kasir),
                    (4, customer),
                    (5, f"{jumlah_item} item"),
                    (6, total_fmt),
                    (7, settlement_status)
                ]

                for col, val in items:
                    item = QTableWidgetItem(str(val))
                    item.setBackground(row_color)  # PATCH: Row highlighting
                    if col == 5:  # Jumlah barang center
                        item.setTextAlignment(Qt.AlignCenter)
                    if col == 6:  # Total harga align right
                        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                    if col == 7:  # Settlement center
                        item.setTextAlignment(Qt.AlignCenter)
                    self.table.setItem(row, col, item)
        finally:
            self.table.blockSignals(False)
            self.table.setUpdatesEnabled(True)
        # edited by glg
        # Pertahankan filter aktif setelah refresh data history.
        if hasattr(self, "search_box") and self.search_box is not None:
            self.on_search_changed(self.search_box.text())

    def tampilkan_history_rows(self, rows):
        """Alias untuk kompatibilitas dengan controller"""
        self.render_transaksi_list(rows)

    def set_date_inputs(self, start_iso, end_iso):
        """Sinkronisasi input tanggal dengan controller"""
        try:
            start_qdate = QDate.fromString(start_iso, "yyyy-MM-dd")
            end_qdate = QDate.fromString(end_iso, "yyyy-MM-dd")
            if start_qdate.isValid():
                self.start_date_edit.setDate(start_qdate)
            if end_qdate.isValid():
                self.end_date_edit.setDate(end_qdate)
        except (TypeError, ValueError, AttributeError) as exc:
            LOGGER.warning("Gagal sinkronisasi input tanggal history: %s", exc)

    def kirim_filter_tanggal(self):
        """Submit filter tanggal ke controller"""
        start = self.start_date_edit.date()
        end = self.end_date_edit.date()
        if start > end:
            QMessageBox.warning(self, "Validasi Tanggal", "Tanggal mulai tidak boleh melebihi tanggal akhir.")
            return
        start_str = start.toString("yyyy-MM-dd")
        end_str = end.toString("yyyy-MM-dd")

        # Set ke custom mode
        custom_idx = self.preset_combo.findData("custom")
        if custom_idx != -1 and self.preset_combo.currentIndex() != custom_idx:
            self.preset_combo.blockSignals(True)
            self.preset_combo.setCurrentIndex(custom_idx)
            self.preset_combo.blockSignals(False)

        self.controller.filter_by_date_range(start_str, end_str)

    def on_preset_changed(self, index):
        """Handler perubahan preset filter"""
        mode = self.preset_combo.itemData(index)
        self.start_date_edit.setEnabled(True)
        self.end_date_edit.setEnabled(True)
        self.btn_filter.setEnabled(True)

        if mode != "custom":
            if hasattr(self.controller, "filter_by_preset"):
                self.controller.filter_by_preset(mode)

    def on_current_cell_changed(self, currentRow, currentColumn, previousRow, previousColumn):
        """Handler navigasi keyboard (arrow keys)"""
        _ = previousRow
        _ = previousColumn
        if currentRow < 0:
            return
        self._pending_selection_row = int(currentRow)
        self._pending_selection_col = int(currentColumn)
        self._selection_preview_timer.start()

    # edited by glg
    def on_cell_clicked(self, row, column):
        if self._selection_preview_timer.isActive():
            self._selection_preview_timer.stop()
        self.controller.transaksi_diklik(row, column)

    # edited by glg
    def _emit_current_cell_selection(self):
        row = int(self._pending_selection_row)
        col = int(self._pending_selection_col)
        if row < 0:
            return
        if self.table.currentRow() != row:
            return
        self.controller.transaksi_diklik(row, col)

    # edited by glg
    def set_detail_payload_handler(self, handler):
        self._detail_ready_handler = handler

    # edited by glg
    def emit_detail_payload(self, request_id, payload):
        try:
            self.detail_payload_ready.emit(int(request_id), payload)
        except (TypeError, ValueError, RuntimeError, AttributeError) as exc:
            LOGGER.warning("Gagal emit detail payload history: %s", exc)
            return

    # edited by glg
    def _on_detail_payload_ready(self, request_id, payload):
        if callable(self._detail_ready_handler):
            self._detail_ready_handler(int(request_id), payload)

    # edited by glg
    def set_history_payload_handler(self, handler):
        self._history_ready_handler = handler

    # edited by glg
    def emit_history_payload(self, request_id, payload):
        try:
            self.history_payload_ready.emit(int(request_id), payload)
        except (TypeError, ValueError, RuntimeError, AttributeError) as exc:
            LOGGER.warning("Gagal emit list payload history: %s", exc)
            return

    # edited by glg
    def _on_history_payload_ready(self, request_id, payload):
        if callable(self._history_ready_handler):
            self._history_ready_handler(int(request_id), payload)

    # edited by glg
    def _schedule_search_filter(self, text):
        self._pending_search_text = str(text or "")
        if hasattr(self, "_search_filter_timer") and self._search_filter_timer is not None:
            self._search_filter_timer.start()

    # edited by glg
    def _apply_scheduled_search_filter(self):
        self.on_search_changed(self._pending_search_text)

    def on_search_changed(self, text):
        """PATCH[FrontEndAgent|SearchFeature]: Filter tabel berdasarkan search text"""
        search_text = text.lower().strip()

        for row in range(self.table.rowCount()):
            show_row = False

            if not search_text:
                show_row = True
            else:
                # Search di kolom: Nomer (1), Kasir (3), Customer (4)
                for col in [1, 3, 4]:
                    item = self.table.item(row, col)
                    if item and search_text in item.text().lower():
                        show_row = True
                        break

            self.table.setRowHidden(row, not show_row)

    def tampilkan_detail_transaksi(self, header_data, detail_rows, voucher_info=None, return_items=None):
        """PATCH[FrontEndAgent|DetailInfo]: Tampilkan info transaksi lengkap dengan format informatif"""
        # PATCH[FrontEndAgent|AutoShowPreview]: Auto-show preview saat transaksi diklik
        if not self.is_preview_visible:
            self.is_preview_visible = True
            self.preview_label.setVisible(True)
            self.info_transaksi_label.setVisible(True)
            self.btn_toggle_preview.setText("\U0001F441\ufe0f Sembunyikan Preview")

        if not header_data:
            self.info_transaksi_label.setHtml("<p style='text-align:center; color:red;'>\u274C Data transaksi tidak ditemukan</p>")
            self.btn_toggle_detail.setVisible(False)
            self.btn_copy_invoice.setVisible(False)
            self.btn_reprint.setVisible(False)
            return

        # Store data for toggle
        self.current_header_data = header_data
        self.current_detail_rows = detail_rows
        self.current_voucher_info = voucher_info or []
        self.current_return_items = return_items or []
        self.is_showing_items = False
        self.btn_toggle_detail.setVisible(True)
        self.btn_copy_invoice.setVisible(True)  # PATCH: Show copy button
        self.btn_reprint.setVisible(True)  # PATCH: Show reprint button
        self.btn_toggle_detail.setText("\U0001F4E6 Detail Barang")
        self.preview_label.setText("\U0001F4DD Preview Detail Transaksi:")

        # edited by glg
        # Refactor: render HTML preview dipusatkan ke service agar fungsi view tetap ringkas.
        render_payload = self.detail_render_service.build_transaksi_detail_payload(
            header_data=header_data,
            detail_rows=detail_rows or [],
            voucher_info=self.current_voucher_info,
            return_items=self.current_return_items,
        )
        style_sheet = str(render_payload.get("style_sheet") or "").strip()
        html = str(render_payload.get("html") or "").strip()
        if style_sheet:
            self.info_transaksi_label.setStyleSheet(style_sheet)
        self.info_transaksi_label.setHtml(html or "<p style='text-align:center; color:red;'>\u274C Data transaksi tidak valid</p>")

    def toggle_detail_view(self):
        """PATCH[FrontEndAgent|ToggleDetail]: Toggle antara info transaksi dan detail barang"""
        if not self.current_header_data or not self.current_detail_rows:
            return

        self.is_showing_items = not self.is_showing_items

        if self.is_showing_items:
            # Tampilkan detail barang saja
            self.btn_toggle_detail.setText("\U0001F4CB Info Transaksi")
            self.preview_label.setText("\U0001F4E6 Detail Barang:")
            self.tampilkan_detail_barang_saja(self.current_detail_rows)
        else:
            # Tampilkan info transaksi lengkap
            self.btn_toggle_detail.setText("\U0001F4E6 Detail Barang")
            self.preview_label.setText("\U0001F4DD Preview Detail Transaksi:")
            self.tampilkan_detail_transaksi(
                self.current_header_data,
                self.current_detail_rows,
                self.current_voucher_info,
                self.current_return_items
            )

    def tampilkan_detail_barang_saja(self, detail_rows):
        """PATCH[FrontEndAgent|PremiumUX]: Detail barang dengan refinement UX profesional + native scroll"""
        # edited by glg
        # Refactor: render detail item dipindah ke service agar kode UI lebih modular.
        detail_html = self.detail_render_service.build_barang_detail_html(detail_rows)
        self.info_transaksi_label.setHtml(detail_html)

    def toggle_preview_section(self):
        """PATCH[FrontEndAgent|TogglePreview]: Toggle tampilkan/sembunyikan preview section"""
        self.is_preview_visible = not self.is_preview_visible

        self.preview_label.setVisible(self.is_preview_visible)
        self.info_transaksi_label.setVisible(self.is_preview_visible)
        self.btn_toggle_detail.setVisible(self.is_preview_visible and self.current_header_data is not None)
        self.btn_copy_invoice.setVisible(self.is_preview_visible and self.current_invoice_number is not None)
        self.btn_reprint.setVisible(self.is_preview_visible and self.current_header_data is not None)

        if self.is_preview_visible:
            self.btn_toggle_preview.setText("\U0001F441\ufe0f Sembunyikan Preview")
            # Jika ada data yang sudah dipilih, tampilkan kembali
            if self.current_header_data and self.current_detail_rows:
                if self.is_showing_items:
                    self.tampilkan_detail_barang_saja(self.current_detail_rows)
                else:
                    self.tampilkan_detail_transaksi(self.current_header_data, self.current_detail_rows)
        else:
            self.btn_toggle_preview.setText("\U0001F441\ufe0f Tampilkan Preview")
