<?= $this->extend('layouts/main') ?>
<?= $this->section('css') ?>
<style>
/* ═══════════════════════════════════════
   POS — menggunakan CSS variables acuan
═══════════════════════════════════════ */
.main-content { padding: 0 !important; height: 100vh; overflow: hidden; }

.pos-shell {
    display: grid;
    grid-template-columns: 1fr 380px;
    height: 100vh;
    overflow: hidden;
}

/* ── LEFT ── */
.pos-left {
    display: flex;
    flex-direction: column;
    background: var(--bg-card2);
    overflow: hidden;
    border-right: 1px solid var(--border);
}

/* topbar */
.pos-topbar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 13px 18px;
    background: var(--bg-side);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.pos-logo {
    width: 34px; height: 34px;
    background: var(--text-main);
    border-radius: 9px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.pos-logo svg { width: 17px; height: 17px; fill: #fff; }
.pos-title {
    font-size: .82rem;
    font-weight: 700;
    color: var(--text-main);
    letter-spacing: .02em;
    line-height: 1.2;
    white-space: nowrap;
}
.pos-title small {
    display: block;
    font-size: .67rem;
    font-weight: 400;
    color: var(--text-muted);
}

.pos-search-wrap { flex: 1; position: relative; }
.pos-search-wrap input {
    width: 100%;
    background: var(--bg-card2);
    border: 1.5px solid var(--border);
    border-radius: 10px;
    padding: 9px 14px 9px 36px;
    font-size: .84rem;
    color: var(--text-main);
    outline: none;
    transition: border-color .15s, background .15s;
}
.pos-search-wrap input::placeholder { color: var(--text-muted); }
.pos-search-wrap input:focus { border-color: var(--accent); background: #fff; }
.pos-search-wrap .ico {
    position: absolute; left: 11px; top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted); font-size: .88rem; pointer-events: none;
}

/* channel tabs */
.chan-tabs {
    display: flex;
    background: var(--bg-side);
    border-bottom: 1px solid var(--border);
    padding: 0 18px;
    flex-shrink: 0;
    overflow-x: auto;
}
.chan-tabs::-webkit-scrollbar { height: 0; }
.chan-tab {
    background: none;
    border: none;
    border-bottom: 2.5px solid transparent;
    padding: 12px 16px;
    font-size: .79rem;
    font-weight: 600;
    color: var(--text-muted);
    cursor: pointer;
    white-space: nowrap;
    transition: color .15s, border-color .15s;
    display: flex; align-items: center; gap: 6px;
}
.chan-tab:hover { color: var(--text-main); }
.chan-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.chan-tab .dot {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: currentColor;
    opacity: .5;
}
.chan-tab.active .dot { opacity: 1; }

/* mitra bar */
.mitra-bar {
    display: none;
    align-items: center;
    gap: 10px;
    padding: 9px 18px;
    background: var(--accent-soft);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.mitra-bar.visible { display: flex; }
.mitra-bar label { font-size: .74rem; font-weight: 700; color: var(--accent); white-space: nowrap; }
.mitra-bar select {
    flex: 1;
    background: #fff;
    border: 1.5px solid var(--border);
    border-radius: 8px;
    padding: 7px 10px;
    font-size: .81rem;
    color: var(--text-main);
    outline: none;
    transition: border-color .15s;
}
.mitra-bar select:focus { border-color: var(--accent); }

/* harga-khusus badge di grid */
.pc-harga-tag {
    font-size: .63rem;
    font-weight: 700;
    color: #fff;
    background: var(--accent);
    border-radius: 5px;
    padding: 1px 5px;
    display: inline-block;
    margin-top: 2px;
}

/* product grid */
.prod-area {
    flex: 1;
    overflow-y: auto;
    padding: 14px 18px 20px;
}
.prod-area::-webkit-scrollbar { width: 4px; }
.prod-area::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }

.prod-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(144px, 1fr));
    gap: 10px;
}

.prod-card {
    background: var(--bg-side);
    border: 1.5px solid var(--border);
    border-radius: 12px;
    padding: 13px 11px;
    cursor: pointer;
    transition: border-color .15s, transform .12s, box-shadow .15s;
    position: relative;
    user-select: none;
}
.prod-card:hover {
    border-color: var(--accent);
    transform: translateY(-2px);
    box-shadow: var(--shadow);
}
.prod-card.out { opacity: .4; cursor: not-allowed; pointer-events: none; }

.pc-emoji { font-size: 24px; margin-bottom: 9px; display: block; }
.pc-name {
    font-size: .77rem; font-weight: 600;
    color: var(--text-main);
    line-height: 1.35; margin-bottom: 4px;
    display: -webkit-box; -webkit-line-clamp: 2;
    -webkit-box-orient: vertical; overflow: hidden;
}
.pc-berat { font-size: .67rem; color: var(--text-muted); margin-bottom: 7px; }
.pc-price { font-size: .8rem; font-weight: 700; color: var(--accent); }
.pc-price-orig {
    font-size: .68rem;
    color: var(--text-muted);
    text-decoration: line-through;
    margin-bottom: 1px;
}

.pc-stok {
    position: absolute; top: 7px; right: 7px;
    font-size: .61rem;
    padding: 2px 6px; border-radius: 5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .04em;
}
.pc-stok.ok   { background: #dcfce7; color: #15803d; }
.pc-stok.low  { background: #fef3c7; color: #d97706; }
.pc-stok.zero { background: #fee2e2; color: #dc2626; }

.pc-badge {
    position: absolute; top: -6px; left: -6px;
    width: 21px; height: 21px;
    background: var(--accent); color: #fff;
    border-radius: 50%; font-size: .63rem; font-weight: 700;
    display: flex; align-items: center; justify-content: center;
    box-shadow: 0 0 0 2px var(--bg-card2);
}

.prod-empty {
    grid-column: 1 / -1; text-align: center;
    padding: 60px 0; color: var(--text-muted); font-size: .84rem;
}
.prod-empty i { font-size: 2rem; display: block; margin-bottom: 8px; opacity: .25; }

/* ── RIGHT (CART) ── */
.pos-right {
    display: flex;
    flex-direction: column;
    background: var(--bg-side);
    overflow: hidden;
}

/* cart header */
.cart-head {
    padding: 14px 18px 11px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
    background: var(--bg-side);
}
.cart-head-top {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 10px;
}
.cart-head-title {
    font-size: .92rem; font-weight: 700; color: var(--text-main);
    display: flex; align-items: center; gap: 8px;
}
.cart-count {
    background: var(--text-main); color: #fff;
    border-radius: 20px; padding: 1px 8px;
    font-size: .67rem; font-weight: 700;
}
.btn-clr {
    background: transparent; border: 1px solid var(--border);
    border-radius: 8px; padding: 5px 11px;
    font-size: .73rem; color: #dc2626; cursor: pointer;
    transition: all .15s; display: inline-flex; align-items: center; gap: 5px;
}
.btn-clr:hover { background: #fee2e2; border-color: #fca5a5; }

/* payment meta */
.pay-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
.pay-meta select, .pay-meta input {
    background: var(--bg-card2);
    border: 1.5px solid var(--border);
    border-radius: 9px; padding: 7px 10px;
    font-size: .76rem;
    color: var(--text-main); outline: none;
    transition: border-color .15s;
}
.pay-meta select:focus, .pay-meta input:focus { border-color: var(--accent); }

/* cart body */
.cart-body { flex: 1; overflow-y: auto; padding: 10px 14px; }
.cart-body::-webkit-scrollbar { width: 4px; }
.cart-body::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }

.cart-empty-msg {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    height: 100%; color: var(--text-muted);
    text-align: center; gap: 10px;
}
.cart-empty-msg i { font-size: 2.8rem; opacity: .15; }
.cart-empty-msg p { font-size: .79rem; line-height: 1.6; }

/* cart item */
.ci {
    display: flex; align-items: center; gap: 9px;
    padding: 9px 10px;
    border: 1.5px solid var(--border);
    border-radius: 12px;
    margin-bottom: 7px;
    background: var(--bg-side);
    animation: ciIn .15s ease;
}
@keyframes ciIn { from { opacity:0; transform:translateX(6px) } to { opacity:1; transform:none } }

.ci-ico {
    font-size: 20px; width: 36px; height: 36px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-card2); border-radius: 9px; flex-shrink: 0;
}
.ci-info { flex: 1; min-width: 0; }
.ci-name {
    font-size: .76rem; font-weight: 600; color: var(--text-main);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ci-berat { font-size: .66rem; color: var(--text-muted); }

.ci-price-inp {
    background: var(--bg-card2);
    border: 1.5px solid var(--border);
    border-radius: 7px; padding: 5px 7px;
    font-size: .72rem; color: var(--text-main);
    width: 86px; text-align: right; outline: none;
    transition: border-color .15s;
}
.ci-price-inp:focus { border-color: var(--accent); background: #fff; }
/* Highlight harga khusus mitra */
.ci-price-inp.harga-khusus {
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--accent);
    font-weight: 700;
}

.ci-qty-ctrl { display: flex; align-items: center; gap: 5px; }
.qb {
    width: 24px; height: 24px;
    background: var(--bg-card2);
    border: 1.5px solid var(--border);
    border-radius: 7px;
    display: flex; align-items: center; justify-content: center;
    font-size: .84rem; cursor: pointer; color: var(--text-main);
    transition: all .12s; flex-shrink: 0;
}
.qb:hover { background: var(--border); }
.qb.del { color: #dc2626; }
.qb.del:hover { background: #fee2e2; border-color: #fca5a5; }

.ci-qty-val {
    font-size: .8rem; font-weight: 700; color: var(--text-main);
    min-width: 17px; text-align: center;
}
.ci-sub {
    font-size: .78rem; font-weight: 700;
    color: var(--text-main); white-space: nowrap;
    min-width: 68px; text-align: right;
}

/* cart footer */
.cart-foot {
    border-top: 1px solid var(--border);
    padding: 13px 16px;
    flex-shrink: 0;
    background: var(--bg-side);
}

.totals { margin-bottom: 11px; }
.tot-row {
    display: flex; justify-content: space-between;
    font-size: .79rem; padding: 3px 0; color: var(--text-muted);
}
.tot-row .tv { color: var(--text-main); font-weight: 600; }
.tot-grand {
    display: flex; justify-content: space-between; align-items: baseline;
    border-top: 1.5px dashed var(--border);
    padding-top: 9px; margin-top: 5px;
}
.tot-grand .tl { font-size: .85rem; font-weight: 700; color: var(--text-main); }
.tot-grand .tv { font-size: 1.12rem; font-weight: 700; color: var(--text-main); }

/* payment type */
.pay-types {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: 6px; margin-bottom: 11px;
}
.pt-btn {
    background: var(--bg-card2); border: 1.5px solid var(--border);
    border-radius: 9px; padding: 7px 4px; text-align: center;
    font-size: .71rem; font-weight: 600;
    color: var(--text-muted); cursor: pointer; transition: all .13s;
}
.pt-btn:hover { color: var(--text-main); border-color: var(--accent); }
.pt-btn.on { background: var(--text-main); color: #fff; border-color: var(--text-main); }

/* bayar input */
.bayar-wrap {
    display: flex; align-items: center; gap: 8px; margin-bottom: 9px;
}
.bayar-wrap label { font-size: .74rem; color: var(--text-muted); white-space: nowrap; font-weight: 600; }
.bayar-wrap input {
    flex: 1; background: var(--bg-card2);
    border: 1.5px solid var(--border); border-radius: 9px;
    padding: 8px 10px; font-size: .87rem;
    text-align: right; color: var(--text-main); outline: none;
    transition: border-color .15s, background .15s;
}
.bayar-wrap input:focus { border-color: #16a34a; background: #fff; }

/* kembalian strip */
.kembali-strip {
    background: #dcfce7; border: 1px solid #a7f3d0;
    border-radius: 9px; padding: 8px 12px;
    display: flex; justify-content: space-between; align-items: center;
    margin-bottom: 10px;
}
.kembali-strip.neg { background: #fee2e2; border-color: #fca5a5; }
.kembali-strip label { font-size: .72rem; color: #15803d; font-weight: 700; }
.kembali-strip.neg label { color: #dc2626; }
.kembali-strip .kv { font-size: .98rem; font-weight: 700; color: #15803d; }
.kembali-strip.neg .kv { color: #dc2626; }

/* submit */
.btn-submit {
    width: 100%; background: var(--text-main); color: #fff;
    border: none; border-radius: 12px; padding: 13px;
    font-size: .9rem; font-weight: 700;
    cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px;
    transition: opacity .15s, transform .1s;
}
.btn-submit:hover:not(:disabled) { opacity: .85; }
.btn-submit:active:not(:disabled) { transform: scale(.98); }
.btn-submit:disabled { opacity: .3; cursor: not-allowed; }
.btn-submit.loading { opacity: .6; pointer-events: none; }

.spin {
    width: 15px; height: 15px;
    border: 2px solid rgba(255,255,255,.3);
    border-top-color: #fff;
    border-radius: 50%;
    animation: spin .6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* toast */
.pos-toast {
    position: fixed; bottom: 24px; left: 50%;
    transform: translateX(-50%); z-index: 99999;
    border-radius: 10px; padding: 10px 20px;
    font-size: .82rem; font-weight: 600;
    pointer-events: none; transition: opacity .25s;
    white-space: nowrap;
    box-shadow: var(--shadow);
}

/* flash alerts */
.flash {
    position: fixed; top: 16px; left: 50%; transform: translateX(-50%);
    z-index: 9999; border-radius: 12px; padding: 12px 20px;
    font-size: .84rem; font-weight: 600;
    display: flex; align-items: center; gap: 8px;
    box-shadow: var(--shadow);
    animation: flashIn .25s ease;
}
@keyframes flashIn {
    from { opacity:0; transform:translateX(-50%) translateY(-10px) }
    to   { opacity:1; transform:translateX(-50%) translateY(0) }
}
.flash.ok  { background: #fff; border: 1px solid #86efac; color: #166534; }
.flash.err { background: #fff; border: 1px solid #fca5a5; color: #991b1b; }

/* modal struk */
.modal-backdrop {
    position: fixed; inset: 0;
    background: rgba(15,22,35,.45);
    backdrop-filter: blur(4px);
    z-index: 10000;
    display: flex; align-items: center; justify-content: center;
    animation: fadeIn .2s ease;
}
@keyframes fadeIn { from { opacity:0 } to { opacity:1 } }

.modal-struk {
    background: var(--bg-side);
    border: 1px solid var(--border);
    border-radius: 20px;
    padding: 26px 28px;
    width: 340px; max-width: 92vw;
    box-shadow: 0 20px 60px rgba(0,0,0,.18);
    animation: slideUp .22s cubic-bezier(.34,1.38,.64,1);
}
@keyframes slideUp {
    from { transform:translateY(16px); opacity:0 }
    to   { transform:none; opacity:1 }
}
.modal-struk h3 { font-size: 1.05rem; font-weight: 700; color: var(--text-main); margin-bottom: 4px; }
.modal-struk .modal-sub { font-size: .77rem; color: var(--text-muted); margin-bottom: 14px; }

.modal-trx {
    background: var(--bg-card2);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 10px 13px;
    margin-bottom: 14px;
}
.modal-trx div { display: flex; justify-content: space-between; padding: 3px 0; font-size: .8rem; }
.modal-trx .key { color: var(--text-muted); }
.modal-trx .val { font-weight: 700; color: var(--text-main); }
.modal-trx .total-row {
    border-top: 1px dashed var(--border);
    margin-top: 6px; padding-top: 6px;
}
.modal-trx .total-row .val { color: #16a34a; font-size: .9rem; }

.modal-btns { display: flex; gap: 8px; }
.modal-btns button {
    flex: 1; padding: 10px; border-radius: 10px;
    font-size: .82rem; font-weight: 700;
    cursor: pointer; transition: opacity .15s;
}
.modal-btns button:hover { opacity: .85; }
.mbtn-ok    { background: var(--text-main); color: #fff; border: none; }
.mbtn-close {
    background: var(--bg-card2); color: var(--text-main);
    border: 1px solid var(--border);
}

@media (max-width: 840px) {
    .pos-shell { grid-template-columns: 1fr; height: auto; }
    .pos-left, .pos-right { height: 50vh; }
    .main-content { overflow: auto !important; height: auto !important; }
}
</style>
<?= $this->endSection() ?>

<?= $this->section('content') ?>

<?php if(session()->getFlashdata('success')): ?>
<div class="flash ok" id="flashMsg">
    <i class="bi bi-check-circle-fill"></i> <?= session()->getFlashdata('success') ?>
</div>
<?php endif; ?>
<?php if(session()->getFlashdata('error')): ?>
<div class="flash err" id="flashMsg">
    <i class="bi bi-exclamation-triangle-fill"></i> <?= session()->getFlashdata('error') ?>
</div>
<?php endif; ?>

<div class="pos-shell">

    <!-- ══ LEFT ══ -->
    <div class="pos-left">
        <div class="pos-topbar">
            <div class="pos-logo">
                <svg viewBox="0 0 24 24"><path d="M7 18c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm10 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-17-16v2h2l3.6 7.59L4.25 14c-.16.28-.25.61-.25.96C4 16.1 4.9 17 6 17h14v-2H6.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63H19c.75 0 1.41-.41 1.75-1.03l3.58-6.49A1 1 0 0023.43 4H5.21l-.94-2H0z"/></svg>
            </div>
            <div class="pos-title">
                Kasir POS
                <small>Pusat Penjualan Omnichannel</small>
            </div>
            <div class="pos-search-wrap">
                <i class="bi bi-search ico"></i>
                <input type="text" id="srchInput" placeholder="Cari produk atau kode…" autocomplete="off">
            </div>
        </div>

        <div class="chan-tabs">
            <button class="chan-tab active" data-chan="kasir" onclick="switchChan(this,'kasir')">
                <span class="dot"></span> Kasir
            </button>
            <button class="chan-tab" data-chan="reseller" onclick="switchChan(this,'reseller')">
                <span class="dot"></span> Reseller
            </button>
            <button class="chan-tab" data-chan="maklon" onclick="switchChan(this,'maklon')">
                <span class="dot"></span> Maklon
            </button>
            <button class="chan-tab" onclick="window.location.href='<?= base_url('/import') ?>'">
                <i class="bi bi-cloud-arrow-down-fill" style="font-size:.74rem"></i> Marketplace
            </button>
        </div>

        <div class="mitra-bar" id="mitraBar">
            <label id="mitraLabel">Reseller</label>
            <select id="mitraSelect" onchange="onMitraChange()">
                <option value="">— Pilih —</option>
            </select>
        </div>

        <div class="prod-area">
            <div class="prod-grid" id="prodGrid">
                <div class="prod-empty"><i class="bi bi-box-seam"></i> Memuat produk…</div>
            </div>
        </div>
    </div>

    <!-- ══ RIGHT (CART) ══ -->
    <div class="pos-right">
        <div class="cart-head">
            <div class="cart-head-top">
                <div class="cart-head-title">
                    <i class="bi bi-bag-check" style="color:var(--accent)"></i>
                    Keranjang
                    <span class="cart-count" id="cartCount">0</span>
                </div>
                <button class="btn-clr" onclick="clearCart()">
                    <i class="bi bi-trash3"></i> Kosongkan
                </button>
            </div>
            <div class="pay-meta">
                <select id="selMetode">
                    <option value="Tunai / Cash">Tunai / Cash</option>
                    <option value="Transfer Bank BCA">Transfer BCA</option>
                    <option value="Transfer Bank Mandiri">Transfer Mandiri</option>
                    <option value="QRIS">QRIS / E-Wallet</option>
                    <option value="Tempo / Hutang">Tempo / Hutang</option>
                </select>
                <input type="text" id="inpCatatan" placeholder="Nama pembeli / catatan" autocomplete="off">
            </div>
        </div>

        <div class="cart-body" id="cartBody">
            <div class="cart-empty-msg" id="cartEmptyMsg">
                <i class="bi bi-cart3"></i>
                <p>Pilih produk di sebelah kiri<br>untuk memulai transaksi</p>
            </div>
        </div>

        <div class="cart-foot">
            <div class="totals">
                <div class="tot-row">
                    <span>Subtotal</span>
                    <span class="tv" id="tSub">Rp 0</span>
                </div>
                <div class="tot-grand">
                    <span class="tl">Total</span>
                    <span class="tv" id="tGrand">Rp 0</span>
                </div>
            </div>

            <div class="pay-types">
                <button class="pt-btn on" data-pay="tunai" onclick="setPay(this,'tunai')">
                    <i class="bi bi-cash-coin" style="display:block;font-size:.95rem;margin-bottom:2px"></i>Tunai
                </button>
                <button class="pt-btn" data-pay="transfer" onclick="setPay(this,'transfer')">
                    <i class="bi bi-bank" style="display:block;font-size:.95rem;margin-bottom:2px"></i>Transfer
                </button>
                <button class="pt-btn" data-pay="qris" onclick="setPay(this,'qris')">
                    <i class="bi bi-qr-code-scan" style="display:block;font-size:.95rem;margin-bottom:2px"></i>QRIS
                </button>
            </div>

            <div id="bayarSection">
                <div class="bayar-wrap">
                    <label>Bayar</label>
                    <input type="number" id="inpBayar" placeholder="0" min="0" oninput="calcKembalian()">
                </div>
                <div class="kembali-strip" id="kembaliBox">
                    <label>Kembalian</label>
                    <span class="kv" id="kembaliVal">Rp 0</span>
                </div>
            </div>

            <button class="btn-submit" id="btnSubmit" disabled onclick="submitTrx()">
                <i class="bi bi-lightning-charge-fill"></i> Proses Pembayaran
            </button>
        </div>
    </div>
</div>

<?= $this->endSection() ?>

<?= $this->section('js') ?>
<script>
/* ─── Data dari server ─── */
const MASTER_PRODUCTS = <?= json_encode($products ?? []) ?>;
const RESELLERS       = <?= json_encode($reseller  ?? []) ?>;
const MAKLONS         = <?= json_encode($maklon    ?? []) ?>;
const BASE_URL        = '<?= base_url() ?>';
const CSRF_TOKEN_NAME = '<?= csrf_token() ?>';
const CSRF_HASH       = '<?= csrf_hash() ?>';

/* ─── State ─── */
let chan         = 'kasir';
let cart         = [];
let payType      = 'tunai';
let selMitraId   = '';
let isSubmitting = false;

/* ─── Helpers ─── */
const EMOJIS = ['🥜','🌿','🍱','🧂','🫙','🥐','🍯','🌾','🧁','🫘','🍵','🍪'];
function emo(nama) {
    const s = [...(nama||'x')].reduce((a,c) => a + c.charCodeAt(0), 0);
    return EMOJIS[s % EMOJIS.length];
}
function rp(n) { return 'Rp ' + Math.round(n||0).toLocaleString('id-ID'); }
function beratLabel(p) { return (p.berat_produk ?? p.berat_gram ?? p.berat ?? 0) + 'g'; }
function hargaNormal(p)  { return parseFloat(p.harga_produk ?? p.harga_jual ?? 0); }
function stokVal(p)      { return parseInt(p.stok_produk ?? p.stok ?? 0); }

/* ─────────────────────────────────────────────────────────────
   getMitraHargaMap()
   Bangun map { "id_produk": harga } dari harga_khusus mitra.
   getHargaKhusus() di PHP mengembalikan:
       [ { id_produk: X, harga_khusus: Y }, ... ]
   ───────────────────────────────────────────────────────────── */
function getMitraHargaMap() {
    if ((chan !== 'reseller' && chan !== 'maklon') || !selMitraId) return {};

    const list   = chan === 'reseller' ? RESELLERS : MAKLONS;
    const idKey  = chan === 'reseller' ? 'id_reseller' : 'id_maklon';
    const mitra  = list.find(m => String(m[idKey]) === String(selMitraId));
    if (!mitra || !mitra.harga_khusus) return {};

    const map = {};

    if (Array.isArray(mitra.harga_khusus)) {
        /* Format: [ {id_produk, harga_khusus}, ... ] */
        mitra.harga_khusus.forEach(h => {
            const pid   = h.id_produk ?? h.id ?? null;
            /* coba beberapa nama field yang mungkin dipakai model */
            const harga = parseFloat(h.harga_khusus ?? h.harga ?? h.price ?? 0);
            if (pid !== null && harga > 0) map[String(pid)] = harga;
        });
    } else if (typeof mitra.harga_khusus === 'object') {
        /* Format: { "1": 5000, "2": 7000 } */
        Object.entries(mitra.harga_khusus).forEach(([pid, harga]) => {
            const h = parseFloat(harga);
            if (h > 0) map[String(pid)] = h;
        });
    }

    return map;
}

/* ─────────────────────────────────────────────────────────────
   defaultPrice(prod)
   Prioritas:
     1. Harga khusus per-produk dari mitra terpilih
     2. Harga default level mitra (data-price di option)
     3. Harga normal produk dari tb_produk
   ───────────────────────────────────────────────────────────── */
function defaultPrice(prod) {
    if (chan === 'reseller' || chan === 'maklon') {
        /* 1. Harga khusus spesifik produk */
        const map      = getMitraHargaMap();
        const spesifik = map[String(prod.id_produk)];
        if (spesifik > 0) return spesifik;

        /* 2. Harga default mitra (satu harga flat, opsional) */
        const sel  = document.getElementById('mitraSelect');
        const opt  = sel.options[sel.selectedIndex];
        const dflt = parseFloat(opt?.getAttribute('data-price')) || 0;
        if (dflt > 0) return dflt;
    }
    /* 3. Harga normal produk */
    return hargaNormal(prod);
}

/* ─────────────────────────────────────────────────────────────
   Apakah harga produk ini pakai harga khusus mitra?
   (untuk highlight visual di kartu & input keranjang)
   ───────────────────────────────────────────────────────────── */
function isHargaKhusus(prod) {
    if (chan !== 'reseller' && chan !== 'maklon') return false;
    if (!selMitraId) return false;
    const map = getMitraHargaMap();
    return !!map[String(prod.id_produk)];
}

/* ─────────────────────────────────────────────────────────────
   Channel switch
   ───────────────────────────────────────────────────────────── */
function switchChan(btn, c) {
    document.querySelectorAll('.chan-tab').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    chan = c; selMitraId = ''; cart = [];
    renderCart();

    const mitraBar   = document.getElementById('mitraBar');
    const mitraLabel = document.getElementById('mitraLabel');
    const mitraSel   = document.getElementById('mitraSelect');

    if (c === 'reseller' || c === 'maklon') {
        mitraBar.classList.add('visible');
        mitraLabel.textContent = c === 'reseller' ? 'Reseller' : 'Mitra Maklon';
        const list     = c === 'reseller' ? RESELLERS : MAKLONS;
        const idKey    = c === 'reseller' ? 'id_reseller'            : 'id_maklon';
        const namaKey  = c === 'reseller' ? 'nama_reseller'          : 'nama_maklon';
        const hargaKey = c === 'reseller' ? 'harga_default_reseller' : 'harga_default_maklon';
        mitraSel.innerHTML = `<option value="">— Pilih ${mitraLabel.textContent} —</option>` +
            list.map(m => `<option value="${m[idKey]}"
                data-price="${m[hargaKey] ?? 0}"
                data-products="${m.id_produk_terkait_reseller ?? m.id_produk_terkait_maklon ?? ''}"
                >${m[namaKey]}</option>`).join('');
    } else {
        mitraBar.classList.remove('visible');
    }
    renderGrid();
}

/* ─────────────────────────────────────────────────────────────
   Saat mitra dipilih / diganti
   ───────────────────────────────────────────────────────────── */
function onMitraChange() {
    const sel  = document.getElementById('mitraSelect');
    selMitraId = sel.value;

    /* Refresh harga tiap item di keranjang sesuai mitra baru */
    cart.forEach(ci => {
        ci.price       = defaultPrice(ci.prod);
        ci.hargaKhusus = isHargaKhusus(ci.prod);
    });

    renderCart();
    renderGrid();
}

/* ─────────────────────────────────────────────────────────────
   Filter produk berdasarkan mitra (id_produk_terkait)
   ───────────────────────────────────────────────────────────── */
function getMitraProductIds() {
    if ((chan !== 'reseller' && chan !== 'maklon') || !selMitraId) return null;
    const sel    = document.getElementById('mitraSelect');
    const opt    = sel.options[sel.selectedIndex];
    const rawIds = opt?.getAttribute('data-products') || '';
    return rawIds ? rawIds.split(',').map(x => x.trim()).filter(Boolean) : null;
}

/* ─────────────────────────────────────────────────────────────
   Render grid produk
   ───────────────────────────────────────────────────────────── */
function renderGrid() {
    const q        = document.getElementById('srchInput').value.trim().toLowerCase();
    const mitraIds = getMitraProductIds();
    const hargaMap = getMitraHargaMap();

    const prods = MASTER_PRODUCTS.filter(p => {
        if ((p.status_produk||'').toLowerCase() !== 'aktif') return false;
        if (mitraIds && !mitraIds.includes(String(p.id_produk))) return false;
        if (q) {
            const nama = (p.nama_produk||'').toLowerCase();
            const kode = (p.kode_produk||'').toLowerCase();
            return nama.includes(q) || kode.includes(q);
        }
        return true;
    });

    const grid = document.getElementById('prodGrid');
    if (!prods.length) {
        grid.innerHTML = `<div class="prod-empty"><i class="bi bi-search"></i> Produk tidak ditemukan</div>`;
        return;
    }

    grid.innerHTML = prods.map(p => {
        const stok    = stokVal(p);
        const out     = stok === 0;
        const ci      = cart.find(c => c.prod.id_produk == p.id_produk);
        const qty     = ci ? ci.qty : 0;
        const stokCls = stok === 0 ? 'zero' : stok <= 5 ? 'low' : 'ok';
        const stokTxt = stok === 0 ? 'Habis' : stok <= 5 ? `Sisa ${stok}` : `${stok}`;

        /* Harga yang akan ditampilkan di kartu */
        const hargaTampil  = defaultPrice(p);
        const adaKhusus    = !!hargaMap[String(p.id_produk)];
        const hargaNorm    = hargaNormal(p);

        /* Tampilkan harga asli dicoret + harga khusus jika berbeda */
        const hargaHtml = adaKhusus && hargaTampil !== hargaNorm
            ? `<div class="pc-price-orig">${rp(hargaNorm)}</div>
               <div class="pc-price">${rp(hargaTampil)} <span class="pc-harga-tag">Khusus</span></div>`
            : `<div class="pc-price">${rp(hargaTampil)}</div>`;

        return `<div class="prod-card ${out ? 'out' : ''}" data-id="${p.id_produk}">
            ${qty > 0 ? `<span class="pc-badge">${qty}</span>` : ''}
            <span class="pc-stok ${stokCls}">${stokTxt}</span>
            <span class="pc-emoji">${emo(p.nama_produk)}</span>
            <div class="pc-name">${p.nama_produk}</div>
            <div class="pc-berat">${beratLabel(p)}</div>
            ${hargaHtml}
        </div>`;
    }).join('');

    grid.querySelectorAll('.prod-card:not(.out)').forEach(el => {
        el.addEventListener('click', () => addToCart(parseInt(el.dataset.id)));
    });
}

/* ─────────────────────────────────────────────────────────────
   Keranjang
   ───────────────────────────────────────────────────────────── */
function addToCart(id) {
    const prod = MASTER_PRODUCTS.find(p => p.id_produk == id);
    if (!prod) return;
    const stok     = stokVal(prod);
    const existing = cart.find(c => c.prod.id_produk == id);
    if (existing) {
        if (existing.qty >= stok) { showToast('Stok tidak mencukupi!', 'err'); return; }
        existing.qty++;
    } else {
        if (stok === 0) return;
        cart.push({
            prod,
            qty:         1,
            price:       defaultPrice(prod),
            hargaKhusus: isHargaKhusus(prod),
        });
    }
    renderCart(); renderGrid();
}

function changeQty(id, delta) {
    const idx = cart.findIndex(c => c.prod.id_produk == id);
    if (idx < 0) return;
    cart[idx].qty += delta;
    if (cart[idx].qty <= 0) cart.splice(idx, 1);
    renderCart(); renderGrid();
}

function setItemPrice(id, val) {
    const ci = cart.find(c => c.prod.id_produk == id);
    if (ci) {
        ci.price       = parseFloat(val) || 0;
        ci.hargaKhusus = false; /* harga diubah manual → hilangkan highlight */
        renderTotals();
    }
}

function clearCart() {
    if (!cart.length) return;
    cart = []; renderCart(); renderGrid();
}

function renderCart() {
    const body  = document.getElementById('cartBody');
    const count = document.getElementById('cartCount');
    count.textContent = cart.reduce((s, c) => s + c.qty, 0);

    if (!cart.length) {
        body.innerHTML = `<div class="cart-empty-msg">
            <i class="bi bi-cart3"></i>
            <p>Pilih produk di sebelah kiri<br>untuk memulai transaksi</p>
        </div>`;
        document.getElementById('btnSubmit').disabled = true;
        renderTotals(); return;
    }

    body.innerHTML = cart.map(ci => `
        <div class="ci">
            <div class="ci-ico">${emo(ci.prod.nama_produk)}</div>
            <div class="ci-info">
                <div class="ci-name">${ci.prod.nama_produk}</div>
                <div class="ci-berat">${beratLabel(ci.prod)}</div>
            </div>
            <input class="ci-price-inp ${ci.hargaKhusus ? 'harga-khusus' : ''}"
                   type="number"
                   value="${ci.price}"
                   onchange="setItemPrice(${ci.prod.id_produk}, this.value)"
                   title="${ci.hargaKhusus ? 'Harga khusus mitra' : 'Harga satuan'}"
                   min="0">
            <div class="ci-qty-ctrl">
                <button class="qb del" onclick="changeQty(${ci.prod.id_produk}, -1)">
                    ${ci.qty === 1
                        ? '<i class="bi bi-trash3" style="font-size:.7rem"></i>'
                        : '−'}
                </button>
                <span class="ci-qty-val">${ci.qty}</span>
                <button class="qb" onclick="changeQty(${ci.prod.id_produk}, 1)">+</button>
            </div>
            <div class="ci-sub">${rp(ci.price * ci.qty)}</div>
        </div>
    `).join('');

    document.getElementById('btnSubmit').disabled = false;
    renderTotals();
}

function getTotal() { return cart.reduce((s, c) => s + c.price * c.qty, 0); }

function renderTotals() {
    const total = getTotal();
    document.getElementById('tSub').textContent   = rp(total);
    document.getElementById('tGrand').textContent = rp(total);
    calcKembalian();
}

function calcKembalian() {
    const total = getTotal();
    const bayar = parseFloat(document.getElementById('inpBayar').value) || 0;
    const kemb  = bayar - total;
    const box   = document.getElementById('kembaliBox');
    document.getElementById('kembaliVal').textContent = rp(Math.abs(kemb));
    if (kemb < 0 && bayar > 0) {
        box.classList.add('neg');
        box.querySelector('label').textContent = 'Kurang';
    } else {
        box.classList.remove('neg');
        box.querySelector('label').textContent = 'Kembalian';
    }
}

/* ─────────────────────────────────────────────────────────────
   Pembayaran
   ───────────────────────────────────────────────────────────── */
function setPay(btn, t) {
    document.querySelectorAll('.pt-btn').forEach(b => b.classList.remove('on'));
    btn.classList.add('on');
    payType = t;
    document.getElementById('bayarSection').style.display = t === 'tunai' ? '' : 'none';
    const metSel = document.getElementById('selMetode');
    if (t === 'transfer') metSel.value = 'Transfer Bank BCA';
    else if (t === 'qris') metSel.value = 'QRIS';
    else metSel.value = 'Tunai / Cash';
}

async function submitTrx() {
    if (!cart.length || isSubmitting) return;
    const total = getTotal();
    const bayar = parseFloat(document.getElementById('inpBayar').value) || 0;
    if (payType === 'tunai' && bayar < total) { showToast('Uang tidak cukup!', 'err'); return; }

    const items = cart.map(ci => ({
        id_produk:   ci.prod.id_produk,
        nama_produk: ci.prod.nama_produk,
        harga_jual:  ci.price,
        qty:         ci.qty,
        subtotal:    ci.price * ci.qty,
    }));

    const payload = {
        channel:      chan === 'kasir' ? 'pos' : chan,
        catatan:      document.getElementById('inpCatatan').value.trim(),
        metode_bayar: document.getElementById('selMetode').value,
        diskon: 0, total,
        bayar: payType === 'tunai' ? bayar : total,
        items,
        ...(selMitraId ? { id_mitra: selMitraId } : {}),
    };

    const headers = {
        'Content-Type': 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
    };
    headers[CSRF_TOKEN_NAME] = CSRF_HASH;

    const btn = document.getElementById('btnSubmit');
    btn.classList.add('loading');
    btn.innerHTML = '<span class="spin"></span> Memproses…';
    isSubmitting  = true;

    try {
        const res  = await fetch(BASE_URL + 'penjualan/store-manual', {
            method: 'POST', headers, body: JSON.stringify(payload),
        });
        if (!res.ok) {
            const txt = await res.text();
            throw new Error(`Server ${res.status}: ${txt.substring(0,120)}`);
        }
        const data = await res.json();
        if (data.success) {
            showStrukModal(data, total, bayar, payType === 'tunai' ? bayar - total : 0);
            cart = []; renderCart(); renderGrid();
            document.getElementById('inpBayar').value   = '';
            document.getElementById('inpCatatan').value = '';
            calcKembalian();
        } else {
            showToast('Gagal: ' + (data.error || 'Terjadi kesalahan'), 'err');
        }
    } catch (err) {
        showToast('Koneksi gagal: ' + err.message, 'err');
    } finally {
        btn.classList.remove('loading');
        btn.innerHTML = '<i class="bi bi-lightning-charge-fill"></i> Proses Pembayaran';
        btn.disabled  = cart.length === 0;
        isSubmitting  = false;
    }
}

/* ─────────────────────────────────────────────────────────────
   Modal struk
   ───────────────────────────────────────────────────────────── */
function showStrukModal(data, total, bayar, kembalian) {
    const backdrop = document.createElement('div');
    backdrop.className = 'modal-backdrop';
    backdrop.innerHTML = `
        <div class="modal-struk">
            <h3>✅ Transaksi Berhasil</h3>
            <div class="modal-sub">${data.no_transaksi || ''}</div>
            <div class="modal-trx">
                <div><span class="key">Metode</span>
                     <span class="val">${document.getElementById('selMetode').value}</span></div>
                <div><span class="key">Item</span>
                     <span class="val">${data.items_count ?? '—'} produk</span></div>
                <div class="total-row">
                    <span class="key">Total</span>
                    <span class="val">${rp(total)}</span>
                </div>
                ${bayar > 0
                    ? `<div><span class="key">Bayar</span><span class="val">${rp(bayar)}</span></div>`
                    : ''}
                ${kembalian > 0
                    ? `<div><span class="key">Kembalian</span><span class="val">${rp(kembalian)}</span></div>`
                    : ''}
            </div>
            <div class="modal-btns">
                <button class="mbtn-close"
                        onclick="this.closest('.modal-backdrop').remove()">Tutup</button>
                <button class="mbtn-ok"
                        onclick="this.closest('.modal-backdrop').remove()">Transaksi Baru</button>
            </div>
        </div>`;
    document.body.appendChild(backdrop);
    backdrop.addEventListener('click', e => { if (e.target === backdrop) backdrop.remove(); });
}

/* ─────────────────────────────────────────────────────────────
   Toast & misc
   ───────────────────────────────────────────────────────────── */
document.getElementById('srchInput').addEventListener('input', () => renderGrid());

let toastEl, toastTimer;
function showToast(msg, type = 'ok') {
    if (!toastEl) {
        toastEl = document.createElement('div');
        toastEl.className = 'pos-toast';
        document.body.appendChild(toastEl);
    }
    toastEl.textContent       = msg;
    toastEl.style.background  = type === 'ok' ? '#dcfce7' : '#fee2e2';
    toastEl.style.border      = type === 'ok' ? '1px solid #86efac' : '1px solid #fca5a5';
    toastEl.style.color       = type === 'ok' ? '#166534' : '#991b1b';
    toastEl.style.opacity     = 1;
    clearTimeout(toastTimer);
    toastTimer = setTimeout(() => { toastEl.style.opacity = 0; }, 2600);
}

const flashEl = document.getElementById('flashMsg');
if (flashEl) setTimeout(() => { flashEl.style.opacity = 0; }, 4000);

/* ─── Inisialisasi ─── */
renderGrid();
</script>
<?= $this->endSection() ?>