﻿# edited by glg
from datetime import datetime
from html import escape
from typing import Any, Dict, List


class HistoryDetailRenderService:
    """
    Builder HTML untuk preview history transaksi agar view tetap ringkas.
    """

    def __init__(self, log_debug=None, log_warning=None):
        self.log_debug = log_debug if callable(log_debug) else (lambda *_args, **_kwargs: None)
        self.log_warning = log_warning if callable(log_warning) else (lambda *_args, **_kwargs: None)

    # edited by glg
    @staticmethod
    def _safe_html_text(value, default="-"):
        text = str(value if value is not None else default).strip()
        if not text:
            text = str(default or "")
        return escape(text, quote=True)

    # edited by glg
    @classmethod
    def _mask_card_for_display(cls, value):
        raw = str(value or "").strip()
        if not raw:
            return ""
        digits = "".join(ch for ch in raw if ch.isdigit())
        if digits:
            return f"****{digits[-4:]}"
        compact = "".join(ch for ch in raw if ch.isalnum())
        if compact:
            return f"****{compact[-4:]}"
        return "****"

    @staticmethod
    def _fmt_rp(nilai):
        if nilai is None:
            return "Rp 0,00"
        try:
            raw = float(nilai)
        except (TypeError, ValueError):
            raw = 0.0
        return f"Rp {raw:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")

    @staticmethod
    def _fmt_qty(qty):
        try:
            q = float(qty)
        except (TypeError, ValueError):
            q = 0.0
        return str(int(q)) if q == int(q) else f"{q:.2f}"

    @staticmethod
    def _safe_float(value, default=0.0):
        try:
            return float(value)
        except (TypeError, ValueError):
            return float(default)

    @staticmethod
    def _safe_int(value, default=0):
        try:
            return int(float(value))
        except (TypeError, ValueError):
            return int(default)

    def _parse_datetime_parts(self, dtime_text: str):
        text = str(dtime_text or "").strip()
        if not text:
            return "", "", "-"
        try:
            dt = datetime.fromisoformat(text)
            return dt.strftime("%d/%m/%Y %H:%M:%S"), dt.strftime("%d %B %Y"), dt.strftime("%H:%M:%S")
        except (TypeError, ValueError) as exc:
            self.log_debug(f"Gagal parse dtime transaksi '{text}': {exc}")
            return text, text, "-"

    @staticmethod
    def _build_theme(settlement_id: int) -> Dict[str, str]:
        settled = int(settlement_id or 1) != 1
        if settled:
            return {
                "settlement_status": "✅ Settled",
                "settlement_color": "#28a745",
                "settlement_tooltip": "Transaksi sudah disetor/dilaporkan",
                "preview_border_color": "#28a745",
                "preview_bg_color": "#d4edda",
                "summary_bg_color": "#d4edda",
                "summary_border_color": "#28a745",
                "summary_rule_color": "#1e7e34",
                "item_box_bg_color": "#e7f6ec",
                "item_box_border_color": "#28a745",
            }
        return {
            "settlement_status": "⏳ Pending",
            "settlement_color": "#ffc107",
            "settlement_tooltip": "Belum disetor (Menunggu Settlement)",
            "preview_border_color": "#ffc107",
            "preview_bg_color": "#fff3cd",
            "summary_bg_color": "#fff3cd",
            "summary_border_color": "#ffc107",
            "summary_rule_color": "#856404",
            "item_box_bg_color": "#fff3cd",
            "item_box_border_color": "#ffc107",
        }

    @staticmethod
    def _build_preview_style(theme: Dict[str, str]) -> str:
        border = str(theme.get("preview_border_color") or "#17a2b8")
        bg = str(theme.get("preview_bg_color") or "#ffffff")
        return f"""
            QTextBrowser {{
                border: 2px solid {border};
                border-radius: 5px;
                padding: 8px;
                background-color: {bg};
            }}
            QTextBrowser QScrollBar:vertical {{
                border: none;
                background: #f8f9fa;
                width: 8px;
                margin: 0px;
            }}
            QTextBrowser QScrollBar::handle:vertical {{
                background: {border};
                min-height: 20px;
                border-radius: 4px;
            }}
            QTextBrowser QScrollBar::handle:vertical:hover {{
                background: {border};
            }}
            QTextBrowser QScrollBar::add-line:vertical,
            QTextBrowser QScrollBar::sub-line:vertical {{
                height: 0px;
            }}
            QTextBrowser QScrollBar::add-page:vertical,
            QTextBrowser QScrollBar::sub-page:vertical {{
                background: none;
            }}
        """

    def _build_voucher_section(self, voucher_info: List[Dict[str, Any]], summary_rule_color: str) -> str:
        if not voucher_info:
            return ""
        voucher_rows = ""
        for row in list(voucher_info or []):
            item = row if isinstance(row, dict) else {}
            kode = self._safe_html_text(item.get("kode_voucher"), "-")
            nilai = item.get("nilai_pakai") or 0
            voucher_rows += f"""
                <tr>
                    <td style='padding: 2px 0;'>Kode:</td>
                    <td style='padding: 2px 0;'>{kode}</td>
                    <td style='padding: 2px 0; text-align:right;'><b>{self._fmt_rp(nilai)}</b></td>
                </tr>
            """
        return f"""
            <tr>
                <td colspan='5' style='padding-top: 6px;'>
                    <div style='border: 1px dashed {summary_rule_color}; border-radius: 4px; padding: 6px; background: #f8f9fa;'>
                        <b style='color:#0d6efd;'>Voucher Digunakan</b>
                        <table width='100%' cellspacing='2' style='font-size: 9pt;'>
                            {voucher_rows}
                        </table>
                    </div>
                </td>
            </tr>
        """

    def _build_return_section(self, return_items: List[Dict[str, Any]], summary_rule_color: str) -> str:
        if not return_items:
            return ""
        return_rows = ""
        for row in list(return_items or []):
            item = row if isinstance(row, dict) else {}
            nama = self._safe_html_text(item.get("produk_nama"), "-")
            qty = self._safe_html_text(item.get("jumlah"), "0")
            subtotal = item.get("subtotal") or 0
            return_rows += f"""
                <tr>
                    <td style='padding: 2px 0;'>{nama}</td>
                    <td style='padding: 2px 0; text-align:center;'>{qty}</td>
                    <td style='padding: 2px 0; text-align:right;'><b>{self._fmt_rp(subtotal)}</b></td>
                </tr>
            """
        return f"""
            <tr>
                <td colspan='5' style='padding-top: 6px;'>
                    <div style='border: 1px dashed {summary_rule_color}; border-radius: 4px; padding: 6px; background: #f8f9fa;'>
                        <b style='color:#dc3545;'>Barang Direturn</b>
                        <table width='100%' cellspacing='2' style='font-size: 9pt;'>
                            <tr>
                                <td><b>Produk</b></td>
                                <td align='center'><b>Qty</b></td>
                                <td align='right'><b>Subtotal</b></td>
                            </tr>
                            {return_rows}
                        </table>
                    </div>
                </td>
            </tr>
        """

    def build_transaksi_detail_payload(
        self,
        *,
        header_data,
        detail_rows,
        voucher_info=None,
        return_items=None,
    ) -> Dict[str, str]:
        header = list(header_data or [])
        if not header:
            return {
                "style_sheet": self._build_preview_style(self._build_theme(1)),
                "html": "<p style='text-align:center; color:red;'>❌ Data transaksi tidak ditemukan</p>",
            }

        customer_nama = self._safe_html_text(header[1] if len(header) > 1 else "", "tunai")
        diskon_persen = self._safe_float(header[2] if len(header) > 2 else 0)
        ppn_persen = self._safe_float(header[3] if len(header) > 3 else 0)
        transaksi_nilai = self._safe_float(header[4] if len(header) > 4 else 0)
        dtime = header[5] if len(header) > 5 else ""
        kasir_nama = self._safe_html_text(header[7] if len(header) > 7 else "", "System")
        metode_pembayaran = str(header[8] if len(header) > 8 else "")
        bank_nama = self._safe_html_text(header[10] if len(header) > 10 else "", "Tunai")
        settlement_id = self._safe_int(header[11] if len(header) > 11 else 1, 1)
        jumlah_bayar = self._safe_float(header[12] if len(header) > 12 else 0)
        kembalian = self._safe_float(header[13] if len(header) > 13 else 0)
        no_kartu = str(header[15] if len(header) > 15 else "")
        ppn_mode = str(header[16] if len(header) > 16 else "exclude").strip().lower()
        if ppn_mode not in {"include", "exclude"}:
            ppn_mode = "exclude"

        _waktu_str, tanggal_str, jam_str = self._parse_datetime_parts(str(dtime or ""))

        theme = self._build_theme(settlement_id)
        ppn_display = self._fmt_rp(ppn_persen if ppn_persen > 0 else 0)
        diskon_display = f"{diskon_persen:.0f}%" if diskon_persen > 0 else "0%"
        ppn_label = "Termasuk PPN" if ppn_mode == "include" else "PPN"
        ppn_prefix = "" if ppn_mode == "include" else "+ "
        subtotal_nilai = max(0.0, transaksi_nilai - ppn_persen)

        metode_icon = {
            "tunai": "💵",
            "kredit": "💳",
            "debit": "🏧",
        }.get((metode_pembayaran or "tunai").strip().lower(), "💰")

        kartu_info = ""
        if no_kartu and no_kartu.strip():
            kartu_masked = self._mask_card_for_display(no_kartu)
            kartu_info = f" | {kartu_masked}"
        metode_display = self._safe_html_text((metode_pembayaran or "tunai").upper(), "TUNAI")
        tanggal_display = self._safe_html_text(f"{tanggal_str} {jam_str}", "-")

        voucher_section = self._build_voucher_section(voucher_info or [], theme["summary_rule_color"])
        return_section = self._build_return_section(return_items or [], theme["summary_rule_color"])

        info_html = f"""
        <div style='font-family: Segoe UI, Arial; font-size: 9.5pt;'>
            <table width='100%' cellspacing='4' cellpadding='3'>
                <tr>
                    <td width='20%' valign='top'>
                        <b style='color: #28a745; font-size: 10pt;'>👤 PEMBELI</b><br>
                        <span style='font-size: 9pt;'>{customer_nama}</span>
                    </td>
                    <td width='20%' valign='top'>
                        <b style='color: #007bff; font-size: 10pt;'>👨‍💼 KASIR</b><br>
                        <span style='font-size: 9pt;'>{kasir_nama}</span>
                    </td>
                    <td width='20%' valign='top'>
                        <b style='color: #6f42c1; font-size: 10pt;'>🕐 WAKTU</b><br>
                        <span style='font-size: 8.5pt;'>{tanggal_display}</span>
                    </td>
                    <td width='20%' valign='top'>
                        <b style='color: #fd7e14; font-size: 10pt;'>{metode_icon} BAYAR</b><br>
                        <span style='font-size: 8.5pt;'>{metode_display} - {bank_nama}{kartu_info}</span>
                    </td>
                    <td width='20%' valign='top'>
                        <b style='font-size: 10pt;'>SETTLEMENT</b><br>
                        <span style='color: {theme['settlement_color']}; font-weight: bold; font-size: 8.5pt;' title='{self._safe_html_text(theme['settlement_tooltip'])}'>{theme['settlement_status']}</span>
                    </td>
                </tr>
                <tr>
                    <td colspan='5' style='padding-top: 6px;'>
                        <table width='100%' style='background-color: {theme['summary_bg_color']}; border: 1px solid {theme['summary_border_color']}; border-radius: 4px; padding: 6px;'>
                            <tr>
                                <td width='60%' valign='top'>
                                    <table width='100%' cellspacing='2' style='font-size: 9pt;'>
                                        <tr>
                                            <td width='50%'>Subtotal:</td>
                                            <td width='50%' align='right'><b>{self._fmt_rp(subtotal_nilai)}</b></td>
                                        </tr>
                                        <tr>
                                            <td>Diskon ({diskon_display}):</td>
                                            <td align='right'><b style='color: #28a745;'>- Rp 0,00</b></td>
                                        </tr>
                                        <tr>
                                            <td>{ppn_label}:</td>
                                            <td align='right'><b style='color: #dc3545;'>{ppn_prefix}{ppn_display}</b></td>
                                        </tr>
                                        <tr style='border-top: 1px solid {theme['summary_rule_color']};'>
                                            <td style='padding-top: 3px;'><b>TOTAL:</b></td>
                                            <td align='right' style='padding-top: 3px;'><b style='font-size: 10pt; color: #dc3545;'>{self._fmt_rp(transaksi_nilai)}</b></td>
                                        </tr>
                                    </table>
                                </td>
                                <td width='40%' style='border-left: 1px solid {theme['summary_border_color']}; padding-left: 8px;' valign='top'>
                                    <table width='100%' cellspacing='2' style='font-size: 9pt;'>
                                        <tr>
                                            <td width='50%'>Dibayar:</td>
                                            <td width='50%' align='right'><b style='color: #007bff;'>{self._fmt_rp(jumlah_bayar)}</b></td>
                                        </tr>
                                        <tr>
                                            <td>Kembalian:</td>
                                            <td align='right'><b style='color: #28a745;'>{self._fmt_rp(kembalian)}</b></td>
                                        </tr>
                                    </table>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr>
                {voucher_section}
                {return_section}
                <tr>
                    <td colspan='5' style='padding-top: 8px; text-align: center;'>
                        <div style='background-color: {theme['item_box_bg_color']}; border: 2px solid {theme['item_box_border_color']}; border-radius: 5px; padding: 8px;'>
                            <b style='font-size: 11pt; color: {theme['item_box_border_color']};'>📦 {len(list(detail_rows or []))} ITEM</b> dalam transaksi ini
                            <span style='font-size: 9pt; color: #666;'> | Klik "Detail Barang" untuk melihat daftar lengkap</span>
                        </div>
                    </td>
                </tr>
            </table>
        </div>
        """

        return {
            "style_sheet": self._build_preview_style(theme),
            "html": info_html,
        }

    def build_barang_detail_html(self, detail_rows) -> str:
        rows = list(detail_rows or [])
        if not rows:
            return "<p style='text-align:center; color:red;'>❌ Tidak ada detail barang</p>"

        items_html = ""
        total_qty = 0.0
        total_nilai = 0.0

        for idx, item in enumerate(rows, 1):
            try:
                kode = self._safe_html_text(item[0], "-")
                nama = self._safe_html_text(item[1], "-")
                harga = self._safe_float(item[2], 0.0)
                jumlah = self._safe_float(item[3], 0.0)
                diskon_item = self._safe_float(item[4] if len(item) > 4 else 0, 0.0)
                subtotal = (harga * jumlah) - diskon_item
                satuan = self._safe_html_text(item[5] if len(item) > 5 else "", "")
            except (TypeError, ValueError, IndexError) as exc:
                self.log_warning(f"Gagal parsing detail item ke-{idx} pada history transaksi: {exc}")
                continue

            total_qty += jumlah
            total_nilai += subtotal

            items_html += f"""
                <tr style='border-bottom: 1px solid #e9ecef;'>
                    <td style='padding: 6px 4px;'>{idx}</td>
                    <td style='padding: 6px 4px;'><b style='color: #004085;'>{kode}</b></td>
                    <td style='padding: 6px 4px;'>{nama}</td>
                    <td style='padding: 6px 4px;' align='right'>{self._fmt_rp(harga)}</td>
                    <td style='padding: 6px 4px;' align='center'><b>{self._fmt_qty(jumlah)}</b> {satuan}</td>
                    <td style='padding: 6px 4px;' align='right'>{self._fmt_rp(diskon_item) if diskon_item > 0 else '-'}</td>
                    <td style='padding: 6px 4px; background-color: #fff8dc;' align='right'><b style='color: #dc3545;'>{self._fmt_rp(subtotal)}</b></td>
                </tr>
            """

        return f"""
        <div style='font-family: Segoe UI, Arial; font-size: 9pt;'>
            <div style='background-color: #e7f3ff; border: 2px solid #17a2b8; border-radius: 5px; padding: 10px; margin-bottom: 8px;'>
                <b style='color: #17a2b8; font-size: 10.5pt;'>📦 DAFTAR BARANG ({len(rows)} item)</b>
                <span style='float: right; font-size: 9.5pt;'>
                    Total Qty: <b>{self._fmt_qty(total_qty)}</b> |
                    Total Nilai: <b style='color: #dc3545;'>{self._fmt_rp(total_nilai)}</b>
                </span>
            </div>
            <table width='100%' cellspacing='0' style='font-size: 9pt; table-layout: fixed; border-collapse: collapse; border: 2px solid #17a2b8;'>
                <thead>
                    <tr style='background-color: #17a2b8; color: white;'>
                        <th style='padding: 8px 4px; text-align: left; width: 5%;'>No</th>
                        <th style='padding: 8px 4px; text-align: left; width: 12%;'>Kode</th>
                        <th style='padding: 8px 4px; text-align: left; width: 33%;'>Nama Barang</th>
                        <th style='padding: 8px 4px; text-align: right; width: 13%;'>Harga</th>
                        <th style='padding: 8px 4px; text-align: center; width: 10%;'>Qty</th>
                        <th style='padding: 8px 4px; text-align: right; width: 12%;'>Diskon</th>
                        <th style='padding: 8px 4px; text-align: right; width: 15%;'>Subtotal</th>
                    </tr>
                </thead>
                <tbody style='background-color: white;'>
                    {items_html}
                </tbody>
            </table>
            <div style='background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 5px; padding: 8px; margin-top: 8px;'>
                <table width='100%' style='font-size: 9pt;'>
                    <tr>
                        <td width='50%'><b>📊 Total Item:</b></td>
                        <td width='50%' align='right'><b>{len(rows)}</b></td>
                    </tr>
                    <tr>
                        <td><b>📦 Total Qty:</b></td>
                        <td align='right'><b>{self._fmt_qty(total_qty)}</b></td>
                    </tr>
                    <tr style='border-top: 2px solid #17a2b8;'>
                        <td style='padding-top: 4px;'><b style='font-size: 10pt;'>💰 TOTAL NILAI:</b></td>
                        <td align='right' style='padding-top: 4px;'><b style='font-size: 10pt; color: #dc3545;'>{self._fmt_rp(total_nilai)}</b></td>
                    </tr>
                </table>
            </div>
        </div>
        """
