/**
 * WholesaleAppView.js — پورتال B2B عمده‌فروشی قشم
 * کاتالوگ هوشمند · ورود آزمایشی · MOQ · Tier · PO
 */
const TOKEN_KEY = 'acc_token';
const DEMO_PASS = 'Wholesale1234';

const DEMO_USERS = [
    { id: 'shop',    icon: '🏪', title: 'مغازه / خرده‌فروش',   desc: 'سوپرمارکت پارس — tier retailer',     u: 'wholesale_shop_demo',   tier: 'retailer' },
    { id: 'dist',    icon: '🚚', title: 'عمده‌فروش / توزیع',   desc: 'توزیع‌پخش جنوب — Net 30',            u: 'wholesale_dist_demo',   tier: 'distributor' },
    { id: 'vip',     icon: '💎', title: 'زنجیره VIP',          desc: 'هایپر کیش — بهترین نرخ',              u: 'wholesale_vip_demo',    tier: 'vip' },
    { id: 'chain',   icon: '🏬', title: 'زنجیره ملی',          desc: 'رفاه — سقف اعتبار بالا',              u: 'wholesale_chain_demo',  tier: 'vip' },
    { id: 'pending', icon: '⏳', title: 'در انتظار تأیید',     desc: 'نمایش صفحه pending',                   u: 'wholesale_pending_demo', tier: 'pending' },
    { id: 'admin',   icon: '⚙️', title: 'مدیر B2B',            desc: 'تأیید حساب و سفارش',                  u: 'wholesale_admin',       isAdmin: true },
];

const SORT_OPTIONS = [
    { v: 'default',    l: 'پیش‌فرض (دسته‌بندی)' },
    { v: 'name',       l: 'نام (الفبا)' },
    { v: 'moq_asc',    l: 'کمترین MOQ' },
    { v: 'stock',      l: 'بیشترین موجودی' },
];

export default class WholesaleAppView {
    constructor() {
        this.root = null;
        this.token = sessionStorage.getItem(TOKEN_KEY) || '';
        this.meta = {};
        this.me = null;
        this.catalog = [];
        this.catalogMeta = { total: 0, page: 1, pages: 1, per_page: 24 };
        this.cart = [];
        this.orders = [];
        this.screen = 'landing';
        this.tab = 'catalog';
        this.catFilter = '';
        this.originFilter = '';
        this.searchQ = '';
        this.searchDeb = null;
        this.sort = 'default';
        this.page = 1;
        this.inStockOnly = false;
        this.viewMode = 'grid';
        this.detailProduct = null;
        this.previewCatalog = [];
    }

    _api() {
        return (window.ACC_WHOLESALE_CFG?.api || '/acc-engine/api.php/acc/v1').replace(/\/$/, '');
    }

    _site() {
        const b = window.ACC_WHOLESALE_CFG?.baseUrl || '/acc-engine/';
        return b.endsWith('/') ? b : b + '/';
    }

    esc(t) {
        return String(t ?? '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    }

    fmt(n) {
        if (n == null) return '—';
        return Number(n).toLocaleString('fa-IR');
    }

    _stockBadge(qty, moq) {
        if (qty <= 0) return '<span class="ws-stock ws-stock--out">ناموجود</span>';
        if (qty < moq * 3) return '<span class="ws-stock ws-stock--low">موجودی محدود</span>';
        return '<span class="ws-stock ws-stock--ok">موجود</span>';
    }

    async _req(method, path, body) {
        const opts = {
            method,
            headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
        };
        if (this.token) opts.headers.Authorization = `Bearer ${this.token}`;
        if (body && method !== 'GET') opts.body = JSON.stringify(body);
        const r = await fetch(`${this._api()}/${path.replace(/^\//, '')}`, opts);
        const j = await r.json().catch(() => ({}));
        if (!r.ok) throw new Error(j.message || j.data?.message || `HTTP ${r.status}`);
        return j;
    }

    _catalogQuery(extra = {}) {
        const p = new URLSearchParams();
        if (this.catFilter) p.set('category', this.catFilter);
        if (this.originFilter) p.set('origin', this.originFilter);
        if (this.searchQ.trim()) p.set('q', this.searchQ.trim());
        if (this.sort) p.set('sort', this.sort);
        if (this.inStockOnly) p.set('in_stock', '1');
        p.set('page', String(this.page));
        p.set('per_page', '24');
        Object.entries(extra).forEach(([k, v]) => { if (v != null && v !== '') p.set(k, v); });
        const qs = p.toString();
        return qs ? `?${qs}` : '';
    }

    async render(root) {
        this.root = root;
        try {
            const m = await this._req('GET', 'public/wholesale/meta');
            this.meta = m.data || {};
        } catch { this.meta = {}; }

        if (this.token) {
            try {
                await this._loadMe();
                const ok = this.me?.account?.status === 'approved' || this.me?.can_manage;
                this.screen = ok ? 'app' : 'pending';
            } catch {
                this.token = '';
                sessionStorage.removeItem(TOKEN_KEY);
                this.screen = 'landing';
            }
        }

        if (this.screen === 'landing') {
            try {
                const prev = await this._req('GET', 'public/wholesale/catalog?per_page=8&in_stock=1');
                this.previewCatalog = prev.data || [];
            } catch { this.previewCatalog = []; }
        }

        this._paint();
    }

    async _loadMe() {
        const res = await this._req('GET', 'wholesale/me');
        this.me = res.data;
    }

    async _loadCatalog() {
        const res = await this._req('GET', `wholesale/catalog${this._catalogQuery()}`);
        this.catalog = res.data || [];
        this.catalogMeta = res.meta || { total: this.catalog.length, page: 1, pages: 1, per_page: 24 };
    }

    async _loadOrders() {
        const res = await this._req('GET', 'wholesale/orders');
        this.orders = res.data || [];
    }

    _paint() {
        if (this.screen === 'app') {
            this.root.innerHTML = this._appShell();
            this._bindApp();
            this._renderTab();
            return;
        }
        if (this.screen === 'pending') {
            this.root.innerHTML = this._pendingHtml();
            this._bindPending();
            return;
        }
        this.root.innerHTML = this._landingHtml();
        this._bindLanding();
    }

    _demoRowsHtml() {
        return DEMO_USERS.map(d => {
            const cls = d.isAdmin ? ' ws-demo-row--admin' : (d.tier === 'pending' ? ' ws-demo-row--pending' : '');
            return `<button type="button" class="ws-demo-row${cls}" data-demo-u="${d.u}" data-demo-p="${DEMO_PASS}" title="${this.esc(d.desc)}">
                <span class="ws-demo-row__icon">${d.icon}</span>
                <span class="ws-demo-row__body">
                    <strong>${this.esc(d.title)}</strong>
                    <small>${this.esc(d.desc)}</small>
                </span>
                <code class="ws-demo-row__user">${d.u}</code>
                <span class="ws-demo-row__badge">ورود خودکار ↗</span>
            </button>`;
        }).join('');
    }

    _landingHtml() {
        const s = this.meta.stats || {};
        const cats = this.meta.categories || [];
        return `<div class="ws-app ws-landing" dir="rtl">
            <header class="ws-header">
                <a href="${this._site()}wholesale.php" class="ws-brand">🏝️ عمده‌فروشی قشم</a>
                <nav class="ws-nav">
                    <a href="#ws-preview">کاتالوگ</a>
                    <a href="#ws-apply">ثبت‌نام</a>
                    <a href="${this._site()}shop.php">فروشگاه خرده</a>
                    <a href="${this._site()}">ACC Engine</a>
                </nav>
                <button type="button" class="ws-demo-toggle" id="ws-demo-btn">🧪 ورود آزمایشی</button>
            </header>

            <div class="ws-demo-panel" id="ws-demo-panel" style="display:none;">
                <div class="ws-demo-panel__inner">
                    <div class="ws-demo-panel__head">
                        <span>🧪</span>
                        <span class="ws-demo-panel__title">ورود آزمایشی — کلیک کنید تا مستقیم وارد شوید</span>
                        <button type="button" class="ws-demo-close" id="ws-demo-close">✕</button>
                    </div>
                    <p class="ws-demo-panel__note">رمز همه کاربران: <code>${DEMO_PASS}</code></p>
                    <div class="ws-demo-list">${this._demoRowsHtml()}</div>
                </div>
            </div>

            <section class="ws-hero">
                <div class="ws-hero__badge">B2B · Free Trade Zone · Price List · MOQ · PO · Net 30</div>
                <h1>از قشم تا مغازه شما</h1>
                <p>پورتال توزیع عمده — ${s.products ?? '—'} SKU فعال در ${cats.length || '—'} دسته · قیمت پلکانی بر اساس tier خریدار</p>
                <div class="ws-hero-stats">
                    <div class="ws-stat"><strong>${s.products ?? '—'}</strong><span>SKU فعال</span></div>
                    <div class="ws-stat"><strong>${s.buyers ?? '—'}</strong><span>خریدار تأییدشده</span></div>
                    <div class="ws-stat"><strong>${s.orders_month ?? '—'}</strong><span>سفارش ۳۰ روز</span></div>
                </div>
            </section>

            <section class="ws-preview" id="ws-preview">
                <div class="ws-preview__head">
                    <h2>📦 پیش‌نمایش کاتالوگ</h2>
                    <p>پس از ورود و تأیید حساب، قیمت tier شما و پلکان حجم نمایش داده می‌شود.</p>
                </div>
                <div class="ws-cat-pills ws-cat-pills--readonly">
                    ${cats.map(c => `<span class="ws-cat-pill">${this.esc(c.label)} <em>${c.count}</em></span>`).join('')}
                </div>
                <div class="ws-preview-grid">
                    ${this.previewCatalog.map(p => `
                        <article class="ws-preview-card">
                            <span class="ws-preview-card__emoji">${this.esc(p.image_emoji)}</span>
                            <strong>${this.esc(p.name)}</strong>
                            <code>${this.esc(p.sku)}</code>
                            <span class="ws-preview-card__meta">MOQ ${p.moq} ${this.esc(p.unit)} · ${this.esc(p.category_label || p.category)}</span>
                            <span class="ws-preview-card__lock">🔒 قیمت پس از ورود B2B</span>
                        </article>`).join('')}
                </div>
                <p class="ws-preview__cta"><button type="button" class="ws-btn ws-btn--primary" id="ws-demo-open">🧪 ورود آزمایشی برای دیدن قیمت</button></p>
            </section>

            <section class="ws-features">
                <div class="ws-feat"><h3>📊 Price List</h3><p>retailer · distributor · VIP</p></div>
                <div class="ws-feat"><h3>📦 MOQ</h3><p>حداقل سفارش هر SKU</p></div>
                <div class="ws-feat"><h3>🌐 Incoterms</h3><p>EXW · FCA · DAP</p></div>
                <div class="ws-feat"><h3>📋 PO</h3><p>شماره سفارش خرید</p></div>
                <div class="ws-feat"><h3>💳 Net 30</h3><p>اعتبار B2B</p></div>
                <div class="ws-feat"><h3>🏝️ FTZ</h3><p>انبار منطقه آزاد قشم</p></div>
            </section>

            <section class="ws-apply" id="ws-apply">
                <h2>ثبت‌نام خریدار B2B</h2>
                <form class="ws-apply-form" id="ws-apply-form">
                    <div class="ws-form-grid">
                        <label>نام کسب‌وکار *<input name="business_name" required></label>
                        <label>نوع<select name="business_type"><option value="retailer">مغازه / خرده</option><option value="distributor">عمده‌فروش</option></select></label>
                        <label>نام تماس<input name="contact_name"></label>
                        <label>تلفن *<input name="phone" required></label>
                        <label>ایمیل<input name="email" type="email"></label>
                        <label>شهر<input name="city"></label>
                        <label>منطقه<select name="zone">
                            ${Object.entries(this.meta.zones || {}).map(([k,v]) => `<option value="${k}">${this.esc(v)}</option>`).join('')}
                        </select></label>
                        <label>شناسه ملی/اقتصادی<input name="tax_id"></label>
                    </div>
                    <label>آدرس<textarea name="address" rows="2"></textarea></label>
                    <button type="submit" class="ws-btn ws-btn--primary">ارسال درخواست همکاری</button>
                    <div class="ws-msg" id="ws-apply-msg"></div>
                </form>
            </section>
        </div>`;
    }

    _pendingHtml() {
        return `<div class="ws-app ws-pending" dir="rtl">
            <header class="ws-header"><span class="ws-brand">🏝️ عمده‌فروشی قشم</span></header>
            <div class="ws-pending-box">
                <h2>⏳ در انتظار تأیید</h2>
                <p>حساب B2B شما هنوز تأیید نشده. پس از بررسی مدیر، دسترسی به قیمت و سفارش فعال می‌شود.</p>
                <p class="ws-pending-hint">کاربر آزمایشی: <code>wholesale_pending_demo</code></p>
                <button type="button" class="ws-btn" id="ws-logout" data-ws-logout>خروج</button>
            </div>
        </div>`;
    }

    _appShell() {
        const acc = this.me?.account || {};
        const cartN = this.cart.reduce((s, i) => s + i.qty, 0);
        return `<div class="ws-app ws-workspace" dir="rtl">
            <header class="ws-header ws-header--app">
                <span class="ws-brand">🏝️ ${this.esc(acc.business_name || 'B2B')}</span>
                <span class="ws-tier">${this.esc(acc.tier_label || '')}</span>
                <nav class="ws-tabs">
                    <button type="button" class="ws-tab ${this.tab === 'catalog' ? 'ws-tab--on' : ''}" data-tab="catalog">📦 کاتالوگ</button>
                    <button type="button" class="ws-tab ${this.tab === 'cart' ? 'ws-tab--on' : ''}" data-tab="cart">🛒 سبد (${cartN})</button>
                    <button type="button" class="ws-tab ${this.tab === 'orders' ? 'ws-tab--on' : ''}" data-tab="orders">📋 سفارش‌ها</button>
                </nav>
                <button type="button" class="ws-btn ws-btn--ghost ws-logout-btn" id="ws-logout" data-ws-logout>خروج</button>
            </header>
            <main class="ws-main" id="ws-main"></main>
            <div class="ws-modal" id="ws-modal" hidden></div>
        </div>`;
    }

    _bindLanding() {
        const panel = this.root.querySelector('#ws-demo-panel');
        const btn = this.root.querySelector('#ws-demo-btn');
        const close = this.root.querySelector('#ws-demo-close');
        const toggle = (open) => {
            if (!panel || !btn) return;
            const show = open ?? panel.style.display === 'none';
            panel.style.display = show ? 'block' : 'none';
            btn.classList.toggle('ws-demo-toggle--active', show);
        };
        btn?.addEventListener('click', () => toggle());
        close?.addEventListener('click', () => toggle(false));
        this.root.querySelector('#ws-demo-open')?.addEventListener('click', () => toggle(true));

        this.root.querySelectorAll('[data-demo-u]').forEach(row => {
            row.addEventListener('click', () => this._demoLogin(row));
        });

        this.root.querySelector('#ws-apply-form')?.addEventListener('submit', async (e) => {
            e.preventDefault();
            const msg = this.root.querySelector('#ws-apply-msg');
            const fd = new FormData(e.target);
            msg.textContent = '';
            try {
                await this._req('POST', 'public/wholesale/apply', Object.fromEntries(fd));
                msg.textContent = '✅ درخواست ثبت شد — پس از تأیید با شما تماس می‌گیریم.';
                msg.className = 'ws-msg ws-msg--ok';
                e.target.reset();
            } catch (err) {
                msg.textContent = err.message;
                msg.className = 'ws-msg ws-msg--err';
            }
        });
    }

    async _demoLogin(rowEl) {
        const u = rowEl.dataset.demoU;
        const p = rowEl.dataset.demoP;
        const badge = rowEl.querySelector('.ws-demo-row__badge');
        rowEl.classList.add('ws-demo-row--loading');
        if (badge) badge.textContent = '⏳ در حال ورود…';
        try {
            await this._login(u, p);
            this.root.querySelector('#ws-demo-panel') && (this.root.querySelector('#ws-demo-panel').style.display = 'none');
        } catch (e) {
            alert(e.message);
        } finally {
            rowEl.classList.remove('ws-demo-row--loading');
            if (badge) badge.textContent = 'ورود خودکار ↗';
        }
    }

    _bindPending() {
        this._bindLogout();
    }

    _bindApp() {
        this._bindLogout();
        this.root.querySelectorAll('[data-tab]').forEach(b => {
            b.addEventListener('click', () => { this.tab = b.dataset.tab; this._paint(); });
        });
    }

    _bindLogout() {
        this.root.querySelectorAll('#ws-logout, [data-ws-logout]').forEach(btn => {
            btn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                this._logout();
            });
        });
    }

    async _login(u, p) {
        const res = await this._req('POST', 'public/auth/login', { username: u, password: p });
        if (!res.success || !res.token) throw new Error(res.message || 'ورود ناموفق');
        this.token = res.token;
        sessionStorage.setItem(TOKEN_KEY, res.token);
        await this._loadMe();
        const ok = this.me?.account?.status === 'approved' || this.me?.can_manage;
        this.screen = ok ? 'app' : 'pending';
        this.page = 1;
        if (this.screen === 'app') await this._loadCatalog();
        this._paint();
    }

    _logout() {
        this.token = '';
        try {
            sessionStorage.removeItem(TOKEN_KEY);
            localStorage.removeItem(TOKEN_KEY);
        } catch { /* ignore */ }
        this.me = null;
        this.cart = [];
        this.orders = [];
        this.catalog = [];
        this.tab = 'catalog';
        this.page = 1;
        this.screen = 'landing';
        /* فوری به لندینگ — منتظر API نمان (علت اصلی «خروج کار نمی‌کند») */
        this._paint();
        this._refreshAfterLogout();
    }

    async _refreshAfterLogout() {
        try {
            const m = await this._req('GET', 'public/wholesale/meta');
            this.meta = m.data || this.meta || {};
        } catch { /* keep prior meta */ }
        try {
            const prev = await this._req('GET', 'public/wholesale/catalog?per_page=8&in_stock=1');
            this.previewCatalog = prev.data || [];
        } catch { this.previewCatalog = []; }
        if (this.screen === 'landing') this._paint();
    }

    async _renderTab() {
        const main = this.root.querySelector('#ws-main');
        if (!main) return;
        if (this.tab === 'catalog') {
            await this._loadCatalog();
            main.innerHTML = this._catalogHtml();
            this._bindCatalog(main);
        } else if (this.tab === 'cart') {
            if (!this.catalog.length) await this._loadCatalog();
            main.innerHTML = this._cartHtml();
            this._bindCart(main);
        } else if (this.tab === 'orders') {
            await this._loadOrders();
            main.innerHTML = this._ordersHtml();
        }
    }

    _catalogHtml() {
        const cats = this.meta.categories || [];
        const m = this.catalogMeta;
        const from = m.total ? (m.page - 1) * m.per_page + 1 : 0;
        const to = Math.min(m.page * m.per_page, m.total);

        return `<div class="ws-catalog-hub">
            <div class="ws-catalog-top">
                <div class="ws-search-wrap">
                    <span class="ws-search-icon">🔍</span>
                    <input type="search" id="ws-search" class="ws-search" placeholder="جستجو: نام، SKU، توضیحات…" value="${this.esc(this.searchQ)}">
                    ${this.searchQ ? '<button type="button" class="ws-search-clear" id="ws-search-clear">✕</button>' : ''}
                </div>
                <div class="ws-catalog-controls">
                    <select id="ws-sort" class="ws-sel ws-sel--sm">
                        ${SORT_OPTIONS.map(o => `<option value="${o.v}" ${o.v === this.sort ? 'selected' : ''}>${o.l}</option>`).join('')}
                    </select>
                    <select id="ws-origin" class="ws-sel ws-sel--sm">
                        <option value="">همه مبدأ</option>
                        ${Object.entries(this.meta.zones || {}).map(([k,v]) => `<option value="${k}" ${k === this.originFilter ? 'selected' : ''}>${this.esc(v)}</option>`).join('')}
                    </select>
                    <label class="ws-check"><input type="checkbox" id="ws-in-stock" ${this.inStockOnly ? 'checked' : ''}> فقط موجود</label>
                    <div class="ws-view-toggle">
                        <button type="button" class="ws-view-btn ${this.viewMode === 'grid' ? 'ws-view-btn--on' : ''}" data-view="grid" title="شبکه">▦</button>
                        <button type="button" class="ws-view-btn ${this.viewMode === 'list' ? 'ws-view-btn--on' : ''}" data-view="list" title="لیست">☰</button>
                    </div>
                </div>
            </div>

            <div class="ws-cat-pills" id="ws-cat-pills">
                <button type="button" class="ws-cat-pill ${!this.catFilter ? 'ws-cat-pill--on' : ''}" data-cat="">همه <em>${m.total && !this.catFilter ? m.total : cats.reduce((s,c)=>s+c.count,0)}</em></button>
                ${cats.map(c => `<button type="button" class="ws-cat-pill ${c.key === this.catFilter ? 'ws-cat-pill--on' : ''}" data-cat="${c.key}">${this.esc(c.label)} <em>${c.count}</em></button>`).join('')}
            </div>

            <div class="ws-catalog-summary">
                <span>${m.total ? `نمایش ${from}–${to} از ${m.total} محصول` : 'محصولی یافت نشد'}</span>
                ${this.searchQ ? `<span class="ws-filter-tag">جستجو: «${this.esc(this.searchQ)}»</span>` : ''}
                ${this.catFilter ? `<span class="ws-filter-tag">${this.esc(cats.find(c=>c.key===this.catFilter)?.label || this.catFilter)}</span>` : ''}
            </div>

            <div class="ws-catalog ws-catalog--${this.viewMode}">
                ${this.catalog.length ? this.catalog.map(p => this._productCard(p)).join('') : `
                    <div class="ws-empty ws-empty--wide">
                        <span>🔍</span>
                        <p>محصولی با این فیلتر یافت نشد.</p>
                        <button type="button" class="ws-btn" id="ws-reset-filters">پاک کردن فیلترها</button>
                    </div>`}
            </div>

            ${m.pages > 1 ? `<div class="ws-pager">
                <button type="button" class="ws-btn ws-btn--sm" id="ws-page-prev" ${m.page <= 1 ? 'disabled' : ''}>قبلی</button>
                <span>صفحه ${m.page} از ${m.pages}</span>
                <button type="button" class="ws-btn ws-btn--sm" id="ws-page-next" ${m.page >= m.pages ? 'disabled' : ''}>بعدی</button>
            </div>` : ''}
        </div>`;
    }

    _productCard(p) {
        const breaks = (p.price_breaks || []).length > 1
            ? `<div class="ws-breaks" title="قیمت پلکانی">${p.price_breaks.map(b => `≥${b.min_qty}: ${this.fmt(b.unit_price)}`).join(' · ')}</div>`
            : '';
        return `<article class="ws-product" data-id="${p.id}">
            <div class="ws-product__top">
                <span class="ws-product__emoji">${this.esc(p.image_emoji)}</span>
                ${this._stockBadge(p.stock_qty, p.moq)}
            </div>
            <strong class="ws-product__name">${this.esc(p.name)}</strong>
            <code class="ws-product__sku">${this.esc(p.sku)}</code>
            <div class="ws-product__meta">
                <span class="ws-tag">${this.esc(p.category_label)}</span>
                <span>MOQ ${p.moq} ${this.esc(p.unit)}</span>
                <span>${this.esc(p.origin_label)}</span>
            </div>
            <div class="ws-product__price">${this.fmt(p.your_price)} <small>ریال/${this.esc(p.unit)}</small></div>
            ${breaks}
            <div class="ws-product__actions">
                <button type="button" class="ws-btn ws-btn--ghost ws-btn--sm" data-detail="${p.id}">جزئیات</button>
                <div class="ws-qty-row">
                    <input type="number" min="${p.moq}" step="1" value="${p.moq}" data-qty="${p.id}" class="ws-qty-inp" aria-label="تعداد">
                    <button type="button" class="ws-btn ws-btn--sm ws-btn--primary" data-add="${p.id}" ${p.stock_qty <= 0 ? 'disabled' : ''}>+ سبد</button>
                </div>
            </div>
        </article>`;
    }

    _showDetail(productId) {
        const p = this.catalog.find(x => x.id === productId);
        if (!p) return;
        const modal = this.root.querySelector('#ws-modal');
        if (!modal) return;
        const breaks = (p.price_breaks || []).map(b =>
            `<tr><td>≥ ${b.min_qty} ${this.esc(p.unit)}</td><td>${this.fmt(b.unit_price)} ریال</td></tr>`
        ).join('');
        modal.hidden = false;
        modal.removeAttribute('hidden');
        modal.innerHTML = `<div class="ws-modal__backdrop" id="ws-modal-close"></div>
            <div class="ws-modal__box" role="dialog">
                <button type="button" class="ws-modal__x" id="ws-modal-x">✕</button>
                <div class="ws-modal__hero">${this.esc(p.image_emoji)}</div>
                <h3>${this.esc(p.name)}</h3>
                <code>${this.esc(p.sku)}</code>
                <p class="ws-modal__desc">${this.esc(p.description || '—')}</p>
                <dl class="ws-modal__dl">
                    <dt>دسته</dt><dd>${this.esc(p.category_label)}</dd>
                    <dt>MOQ</dt><dd>${p.moq} ${this.esc(p.unit)}</dd>
                    <dt>موجودی</dt><dd>${this.fmt(p.stock_qty)} ${this.esc(p.unit)}</dd>
                    <dt>مبدأ</dt><dd>${this.esc(p.origin_label)}</dd>
                    <dt>قیمت شما</dt><dd><strong>${this.fmt(p.your_price)}</strong> ریال/${this.esc(p.unit)}</dd>
                </dl>
                ${breaks ? `<table class="ws-table ws-table--compact"><thead><tr><th>حجم</th><th>قیمت واحد</th></tr></thead><tbody>${breaks}</tbody></table>` : ''}
                <div class="ws-qty-row ws-modal__qty">
                    <input type="number" min="${p.moq}" value="${p.moq}" id="ws-modal-qty" class="ws-qty-inp">
                    <button type="button" class="ws-btn ws-btn--primary" id="ws-modal-add" ${p.stock_qty <= 0 ? 'disabled' : ''}>افزودن به سبد</button>
                </div>
            </div>`;
        const close = () => {
            modal.hidden = true;
            modal.setAttribute('hidden', '');
            modal.innerHTML = '';
        };
        modal.querySelector('#ws-modal-close')?.addEventListener('click', close);
        modal.querySelector('#ws-modal-x')?.addEventListener('click', close);
        modal.querySelector('#ws-modal-add')?.addEventListener('click', () => {
            const qty = parseInt(modal.querySelector('#ws-modal-qty')?.value, 10) || 0;
            this._addToCart(p.id, qty);
            close();
        });
    }

    _addToCart(id, qty) {
        const p = this.catalog.find(x => x.id === id);
        if (!p || qty < p.moq) { alert(`حداقل سفارش: ${p?.moq} ${p?.unit}`); return; }
        if (p.stock_qty < qty) { alert('موجودی کافی نیست'); return; }
        const ex = this.cart.find(c => c.product_id === id);
        if (ex) ex.qty = qty;
        else this.cart.push({ product_id: id, qty, name: p.name, unit: p.unit, unit_price: p.your_price });
        this.tab = 'cart';
        this._paint();
    }

    _bindCatalog(main) {
        main.querySelector('#ws-search')?.addEventListener('input', e => {
            clearTimeout(this.searchDeb);
            this.searchDeb = setTimeout(async () => {
                this.searchQ = e.target.value;
                this.page = 1;
                await this._renderTab();
            }, 350);
        });
        main.querySelector('#ws-search-clear')?.addEventListener('click', async () => {
            this.searchQ = '';
            this.page = 1;
            await this._renderTab();
        });
        main.querySelector('#ws-sort')?.addEventListener('change', async e => {
            this.sort = e.target.value;
            this.page = 1;
            await this._renderTab();
        });
        main.querySelector('#ws-origin')?.addEventListener('change', async e => {
            this.originFilter = e.target.value;
            this.page = 1;
            await this._renderTab();
        });
        main.querySelector('#ws-in-stock')?.addEventListener('change', async e => {
            this.inStockOnly = e.target.checked;
            this.page = 1;
            await this._renderTab();
        });
        main.querySelectorAll('[data-view]').forEach(b => {
            b.addEventListener('click', () => { this.viewMode = b.dataset.view; this._renderTab(); });
        });
        main.querySelectorAll('[data-cat]').forEach(b => {
            b.addEventListener('click', async () => {
                this.catFilter = b.dataset.cat;
                this.page = 1;
                await this._renderTab();
            });
        });
        main.querySelector('#ws-reset-filters')?.addEventListener('click', async () => {
            this.catFilter = '';
            this.searchQ = '';
            this.originFilter = '';
            this.inStockOnly = false;
            this.page = 1;
            await this._renderTab();
        });
        main.querySelector('#ws-page-prev')?.addEventListener('click', async () => {
            if (this.page > 1) { this.page--; await this._renderTab(); }
        });
        main.querySelector('#ws-page-next')?.addEventListener('click', async () => {
            if (this.page < this.catalogMeta.pages) { this.page++; await this._renderTab(); }
        });
        main.querySelectorAll('[data-add]').forEach(btn => {
            btn.addEventListener('click', () => {
                const id = parseInt(btn.dataset.add, 10);
                const qtyInp = main.querySelector(`[data-qty="${id}"]`);
                this._addToCart(id, parseInt(qtyInp?.value, 10) || 0);
            });
        });
        main.querySelectorAll('[data-detail]').forEach(btn => {
            btn.addEventListener('click', () => this._showDetail(parseInt(btn.dataset.detail, 10)));
        });
    }

    _cartHtml() {
        if (!this.cart.length) return '<div class="ws-empty">سبد خالی — از کاتالوگ اضافه کنید</div>';
        let sub = 0;
        const lines = this.cart.map(it => {
            const p = this.catalog.find(x => x.id === it.product_id);
            const price = p?.your_price ?? it.unit_price ?? 0;
            const line = price * it.qty;
            sub += line;
            return `<tr><td>${this.esc(it.name)}</td><td>${it.qty} ${this.esc(it.unit)}</td><td>${this.fmt(price)}</td><td>${this.fmt(line)}</td>
                <td><button type="button" class="ws-link" data-rm="${it.product_id}">حذف</button></td></tr>`;
        }).join('');
        const inco = this.meta.incoterms || {};
        const pay = this.meta.payment_terms || {};
        const credit = this.me?.account?.credit_limit || 0;
        return `<table class="ws-table"><thead><tr><th>کالا</th><th>تعداد</th><th>قیمت واحد</th><th>جمع</th><th></th></tr></thead><tbody>${lines}</tbody></table>
            <div class="ws-checkout">
                <p><strong>جمع:</strong> ${this.fmt(sub)} ریال</p>
                ${credit > 0 ? `<p class="ws-credit">💳 سقف اعتبار Net 30: ${this.fmt(credit)} ریال</p>` : ''}
                <label>شماره PO<input id="ws-po" class="ws-inp" placeholder="PO-2026-001"></label>
                <label>Incoterm<select id="ws-inco" class="ws-sel">${Object.entries(inco).map(([k,v]) => `<option value="${k}">${this.esc(v)}</option>`).join('')}</select></label>
                <label>شرایط پرداخت<select id="ws-pay" class="ws-sel">${Object.entries(pay).map(([k,v]) => `<option value="${k}">${this.esc(v)}</option>`).join('')}</select></label>
                <label>آدرس تحویل<textarea id="ws-ship" class="ws-inp" rows="2">${this.esc(this.me?.account?.address || '')}</textarea></label>
                <button type="button" class="ws-btn ws-btn--primary" id="ws-place-order">ثبت سفارش B2B</button>
                <div id="ws-order-msg" class="ws-msg"></div>
            </div>`;
    }

    _bindCart(main) {
        main.querySelectorAll('[data-rm]').forEach(b => {
            b.addEventListener('click', () => {
                this.cart = this.cart.filter(c => c.product_id !== parseInt(b.dataset.rm, 10));
                this._paint();
            });
        });
        main.querySelector('#ws-place-order')?.addEventListener('click', async () => {
            const msg = main.querySelector('#ws-order-msg');
            try {
                const res = await this._req('POST', 'wholesale/orders', {
                    items: this.cart.map(c => ({ product_id: c.product_id, qty: c.qty })),
                    po_number: main.querySelector('#ws-po')?.value,
                    incoterm: main.querySelector('#ws-inco')?.value,
                    payment_terms: main.querySelector('#ws-pay')?.value,
                    ship_to_address: main.querySelector('#ws-ship')?.value,
                });
                this.cart = [];
                msg.textContent = `✅ سفارش ${res.order_key || ''} ثبت شد — مبلغ: ${this.fmt(res.total)} ریال`;
                msg.className = 'ws-msg ws-msg--ok';
                await this._loadCatalog();
            } catch (e) {
                msg.textContent = e.message;
                msg.className = 'ws-msg ws-msg--err';
            }
        });
    }

    _ordersHtml() {
        if (!this.orders.length) return '<div class="ws-empty">سفارشی ثبت نشده — نمونه‌ها پس از seed نمایش داده می‌شوند</div>';
        const statusCls = { submitted: '', confirmed: 'ws-badge--ok', shipped: 'ws-badge--ship', delivered: 'ws-badge--done', picking: 'ws-badge--warn' };
        return `<div class="ws-orders">${this.orders.map(o => `
            <article class="ws-order">
                <div class="ws-order__head"><strong>${this.esc(o.order_key)}</strong>
                    <span class="ws-badge ${statusCls[o.status] || ''}">${this.esc(o.status_label)}</span></div>
                <div class="ws-order__meta">
                    <span>${this.fmt(o.total)} ریال</span>
                    <span>${this.esc(o.incoterm_label)}</span>
                    <span>${this.esc(o.payment_label)}</span>
                    ${o.po_number ? `<span>PO: ${this.esc(o.po_number)}</span>` : ''}
                </div>
                <ul>${(o.items || []).map(i => `<li>${this.esc(i.name)} × ${i.qty} = ${this.fmt(i.line_total)}</li>`).join('')}</ul>
                <small>${this.esc(o.created_at)}</small>
            </article>`).join('')}</div>`;
    }
}
