﻿from pypos.core.utils.db_helper import parse_float_safely


class DiskonService:
    MAX_QTY_FALLBACK = 100000

    def hitung_diskon_barang(self, barang_data, jenis_diskon, harga, jumlah):
        barang_data = barang_data or {}
        jenis_diskon = str(jenis_diskon or "").strip().lower()
        harga_base = parse_float_safely(harga)
        qty = max(0, int(jumlah or 0))
        diskon_persen = 0.0
        produk_jenis = "invoice"
        subtotal = harga_base * qty

        if jenis_diskon == "grosir":
            diskon_persen = parse_float_safely(barang_data.get("diskon_persen", 0))
            harga_grosir = parse_float_safely(barang_data.get("harga", harga_base))
            harga_base = harga_grosir
            subtotal = harga_base * qty * (1 - (diskon_persen / 100))
            produk_jenis = "diskon_grosir"
        elif jenis_diskon == "free":
            harga_base = parse_float_safely(barang_data.get("harga", harga_base))
            subtotal = harga_base * qty
            produk_jenis = "free_produk"

        return harga_base, subtotal, diskon_persen, produk_jenis

    # edited by glg
    def _resolve_harga_baseline(self, rows):
        candidates = []
        for row in rows:
            harga_jual = parse_float_safely(row.get("harga_jual", 0))
            if harga_jual > 0:
                candidates.append(harga_jual)
        if not candidates:
            return 0.0
        return min(candidates)

    # edited by glg
    def _normalize_harga_diskon(self, baris, harga_baseline):
        harga_diskon = parse_float_safely(baris.get("harga_diskon", 0))
        nilai_diskon = parse_float_safely(baris.get("nilai", 0))
        persen_diskon = parse_float_safely(baris.get("persen", 0))
        harga_jual = parse_float_safely(baris.get("harga_jual", 0))

        if harga_diskon > 0 and harga_baseline > 0 and harga_diskon <= (harga_baseline * 1.2):
            return harga_diskon
        if harga_baseline > 0 and nilai_diskon > 0 and nilai_diskon < harga_baseline:
            return max(0.0, harga_baseline - nilai_diskon)
        if harga_baseline > 0 and persen_diskon > 0:
            return max(0.0, harga_baseline * (1 - (persen_diskon / 100.0)))
        if harga_jual > 0 and nilai_diskon >= 0 and (harga_jual - nilai_diskon) > 0:
            return harga_jual - nilai_diskon
        return max(0.0, harga_diskon)

    def format_keterangan_grosir(self, data):
        if not data:
            return "Tidak ada diskon grosir."

        rows = sorted(
            list(data),
            key=lambda row: (
                int(row.get("minim", 0) or 0),
                -int(row.get("diskon_id", 0) or 0),
            ),
        )
        array_ket = []
        harga_baseline = self._resolve_harga_baseline(rows)
        minim_awal_diskon = None

        for baris in rows:
            minim = int(baris.get("minim", 0) or 0)
            maxim = int(baris.get("maxim", 0) or 0)
            if minim_awal_diskon is None and minim > 0:
                minim_awal_diskon = minim

            harga_diskon = self._normalize_harga_diskon(baris, harga_baseline)
            nilai_diskon = parse_float_safely(baris.get("nilai", 0))
            persen_diskon = parse_float_safely(baris.get("persen", 0))
            total_diskon = harga_diskon * max(1, minim)

            if maxim <= 0 or maxim == self.MAX_QTY_FALLBACK:
                ket = (
                    f"{minim} s/d ~ harga Rp {harga_diskon:,.0f} "
                    f"(disc Rp {nilai_diskon:,.0f} / {persen_diskon:.2f}%) "
                    f"(Rp {total_diskon:,.0f} / {minim})"
                )
            else:
                ket = (
                    f"{minim} s/d {maxim} harga Rp {harga_diskon:,.0f} "
                    f"(disc Rp {nilai_diskon:,.0f} / {persen_diskon:.2f}%) "
                    f"(Rp {total_diskon:,.0f} / {minim})"
                )

            array_ket.append(ket)

        if harga_baseline > 0 and minim_awal_diskon and minim_awal_diskon > 1:
            batas_jml = minim_awal_diskon - 1
            array_ket.insert(
                0,
                f"1 s/d {batas_jml} harga Rp {harga_baseline:,.0f} belum dapat diskon",
            )

        return "\n".join(array_ket)

    def format_keterangan_free(self, data):
        if not data:
            return "Tidak ada diskon free produk."

        baris = data[0]
        nama = baris.get("free_produk_nama", "-")
        minim = int(baris.get("minim", 0) or 0)
        kelipatan = int(baris.get("kelipatan", 0) or 0)

        if kelipatan == 1:
            return f"gratis produk {nama}\nberlaku kelipatan setiap pembelian {minim}"
        return f"gratis produk {nama}\ntidak berlaku kelipatan minimal pembelian {minim}"
