/**
 * AragShopAccountingView — حسابداری جمع‌وجور فروش فروشگاه
 * دفتر کل · اسناد · تراز · سود و زیان
 */

const TOKEN_KEY = 'acc_token';

const NAV = [
    { key: 'dashboard', label: 'خلاصه', icon: '📊' },
    { key: 'documents', label: 'اسناد', icon: '📑' },
    { key: 'graph', label: 'گراف فعالیت', icon: '🕸' },
    { key: 'ledger', label: 'دفتر کل', icon: '📒' },
    { key: 'trial', label: 'تراز', icon: '⚖️' },
    { key: 'pl', label: 'سود و زیان', icon: '💹' },
    { key: 'chart', label: 'سرفصل‌ها', icon: '🗂' },
    { key: 'settings', label: 'تنظیمات', icon: '⚙️' },
];

const STATE_LABEL = {
    pending: 'در صف',
    posted: 'پست‌شده',
    confirmed: 'قطعی',
    failed: 'خطا',
    cancelled: 'لغو',
};

export default class AragShopAccountingView {
    constructor() {
        this.root = null;
        this.tab = 'dashboard';
        this.token = sessionStorage.getItem(TOKEN_KEY) || localStorage.getItem(TOKEN_KEY) || '';
        this.meta = {};
        this.portal = {};
        this.config = {};
        this.canPost = false;
        this.dashboard = {};
        this.documents = [];
        this.ledger = [];
        this.trial = {};
        this.pl = {};
        this.pending = [];
        this.chart = [];
        this.graph = {};
        this.activities = [];
        this.roleLabels = {};
        this.dateFrom = this._monthStart();
        this.dateTo = this._today();
        this.selectedDoc = null;
    }

    render(root) {
        this.root = root;
        if (!this.token) { this._paintLogin(); return; }
        this._paintLoading();
        this._load();
    }

    _siteUrl() { return window.ACC_SHOP_CFG?.baseUrl || '/acc-engine/'; }
    _api() { return window.ACC_SHOP_CFG?.api || '/acc-engine/api.php/acc/v1'; }
    _monthStart() { return new Date().toISOString().slice(0, 8) + '01'; }
    _today() { return new Date().toISOString().slice(0, 10); }

    _fmt(n) {
        const v = Number(n) || 0;
        return v.toLocaleString('fa-IR') + ' ریال';
    }

    _esc(s) {
        return String(s ?? '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
    }

    async _get(path, qs = '') {
        const url = this._api() + path + (qs ? '?' + qs : '');
        const r = await fetch(url, { headers: { Authorization: 'Bearer ' + this.token } });
        const res = await r.json();
        if (!r.ok) throw new Error(res.message || 'خطای ' + r.status);
        return res;
    }

    async _post(path) {
        const r = await fetch(this._api() + path, {
            method: 'POST',
            headers: { Authorization: 'Bearer ' + this.token, 'Content-Type': 'application/json' },
        });
        const res = await r.json();
        if (!r.ok || !res.success) throw new Error(res.message || 'خطا');
        return res;
    }

    _paintLoading() {
        this.root.innerHTML = `<div class="erp-loading"><div class="erp-loading__spinner"></div><p>بارگذاری حسابداری فروش…</p></div>`;
    }

    _paintLogin() {
        const site = this._siteUrl();
        this.root.innerHTML = `
        <div class="erp-login-wrap">
            <div class="erp-login-box">
                <div class="erp-login-box__head">
                    <div class="erp-login-box__logo">📒</div>
                    <h2>حسابداری فروش فروشگاه</h2>
                    <p>دفتر کل · اسناد · تراز · گزارش سود و زیان</p>
                </div>
                <div class="erp-login-box__body">
                    <form id="sacct-login-form" class="erp-login-box__form">
                        <div class="erp-field"><label>نام کاربری</label>
                            <input class="erp-input" name="username" required placeholder="arag_accountant"></div>
                        <div class="erp-field"><label>رمز عبور</label>
                            <input class="erp-input" name="password" type="password" required></div>
                        <button class="erp-btn erp-btn--primary" type="submit" style="width:100%">ورود به حسابداری</button>
                        <div id="sacct-login-msg" hidden></div>
                    </form>
                    <div class="erp-login-hint" style="margin-top:14px">arag_accountant / Demo@2026</div>
                    <div class="erp-login-box__links">
                        <a href="${site}shop.php">فروشگاه</a> · <a href="${site}shop-erp.php">ERP</a> · <a href="${site}">پورتال</a>
                    </div>
                </div>
            </div>
        </div>`;
        this.root.querySelector('#sacct-login-form').addEventListener('submit', e => this._doLogin(e));
    }

    async _doLogin(e) {
        e.preventDefault();
        const msg = this.root.querySelector('#sacct-login-msg');
        const fd = new FormData(e.target);
        if (msg) msg.hidden = true;
        try {
            const r = await fetch(this._api() + '/public/auth/login', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ username: fd.get('username'), password: fd.get('password') }),
            });
            const res = await r.json();
            if (!r.ok || !res.success || !res.token) throw new Error(res.message || 'ورود ناموفق');
            this.token = res.token;
            sessionStorage.setItem(TOKEN_KEY, res.token);
            localStorage.setItem(TOKEN_KEY, res.token);
            this._paintLoading();
            await this._load();
        } catch (err) {
            if (msg) { msg.hidden = false; msg.className = 'erp-msg erp-msg--err'; msg.textContent = err.message; }
        }
    }

    async _load() {
        try {
            const metaRes = await this._get('/arag/shop-acct/meta');
            this.meta = metaRes.meta || {};
            this.portal = metaRes.portal || {};
            this.config = metaRes.config || {};
            this.canPost = !!metaRes.can_post;
            await this._loadTab();
            this._paint();
        } catch (e) {
            if (String(e.message).match(/403|401|دسترسی/)) {
                this.token = '';
                sessionStorage.removeItem(TOKEN_KEY);
                this._paintLogin();
            } else {
                this.root.innerHTML = `<div class="erp-denied"><p>${this._esc(e.message)}</p></div>`;
            }
        }
    }

    async _loadTab() {
        const qs = `date_from=${this.dateFrom}&date_to=${this.dateTo}`;
        if (this.tab === 'dashboard') {
            const d = await this._get('/arag/shop-acct/dashboard');
            this.dashboard = d.data || {};
            const p = await this._get('/arag/shop-acct/pending');
            this.pending = p.data || [];
        }
        if (this.tab === 'documents') {
            const d = await this._get('/arag/shop-acct/documents', 'limit=100');
            this.documents = d.data || [];
        }
        if (this.tab === 'ledger') {
            const d = await this._get('/arag/shop-acct/ledger', qs + '&limit=300');
            this.ledger = d.data || [];
        }
        if (this.tab === 'trial') {
            const d = await this._get('/arag/shop-acct/trial-balance', qs);
            this.trial = d.data || {};
        }
        if (this.tab === 'pl') {
            const d = await this._get('/arag/shop-acct/income-statement', qs);
            this.pl = d.data || {};
        }
        if (this.tab === 'settings' || this.tab === 'chart') {
            const c = await this._get('/arag/shop-acct/chart');
            this.chart = c.data || [];
        }
        if (this.tab === 'graph') {
            const g = await this._get('/arag/shop-acct/cost-graph', `date_from=${this.dateFrom}&date_to=${this.dateTo}`);
            this.graph = g.data || {};
            const a = await this._get('/arag/shop-acct/activities');
            this.activities = a.data || [];
            this.roleLabels = a.roles || g.data?.role_labels || {};
        }
    }

    _paint() {
        const site = this._siteUrl();
        const tag = this.meta.ledger_tag || 'SHOP';
        this.root.innerHTML = `
        <header class="erp-header sacct-header">
            <div class="erp-header__brand">
                <div class="erp-header__logo">📒</div>
                <div>
                    <div class="sacct-header__tag">${this._esc(tag)} · ${this._esc(this.meta.module || 'arag_shop')}</div>
                    <div class="erp-header__title">حسابداری فروش فروشگاه</div>
                    <div class="erp-header__subtitle">${this._esc(this.portal.office_name || 'عرقیات')}</div>
                </div>
            </div>
            <div class="erp-header__actions">
                <a href="${site}shop.php" class="erp-header__btn">🛒 فروشگاه</a>
                <a href="${site}shop-erp.php" class="erp-header__btn">🏪 ERP</a>
                <button class="erp-header__btn" id="sacct-logout" type="button">خروج</button>
            </div>
        </header>
        <main class="erp-main">
            ${this._bannerHtml()}
            <nav class="sacct-nav">${NAV.map(n =>
                `<button class="sacct-nav__btn${this.tab === n.key ? ' sacct-nav__btn--active' : ''}" data-tab="${n.key}" type="button">${n.icon} ${n.label}</button>`
            ).join('')}</nav>
            ${['ledger', 'trial', 'pl', 'graph'].includes(this.tab) ? this._periodHtml() : ''}
            <div id="sacct-panel">${this._panelHtml()}</div>
        </main>`;

        this.root.querySelector('#sacct-logout')?.addEventListener('click', () => {
            this.token = '';
            sessionStorage.removeItem(TOKEN_KEY);
            this._paintLogin();
        });
        this.root.querySelectorAll('[data-tab]').forEach(btn => {
            btn.addEventListener('click', async () => {
                this.tab = btn.dataset.tab;
                this.selectedDoc = null;
                this._paintLoading();
                await this._loadTab();
                this._paint();
            });
        });
        this._bindPeriod();
        this._bindActions();
    }

    _bannerHtml() {
        const m = this.meta;
        return `
        <div class="sacct-banner">
            <span class="sacct-banner__tag">${this._esc(m.ledger_tag || 'SHOP')}</span>
            <strong>${this._esc(m.subsystem_label || 'حسابداری فروش')}</strong>
            <span>ماژول: <b>${this._esc(m.module || 'arag_shop')}</b></span>
            <span>نوع سند: <b>SHOP_SALE</b></span>
            <small>${this._esc(m.description || '')}</small>
        </div>`;
    }

    _periodHtml() {
        return `
        <div class="sacct-period">
            <label>از</label><input type="date" id="sacct-from" value="${this.dateFrom}">
            <label>تا</label><input type="date" id="sacct-to" value="${this.dateTo}">
            <button class="sacct-btn sacct-btn--ghost" id="sacct-apply" type="button">اعمال بازه</button>
        </div>`;
    }

    _bindPeriod() {
        this.root.querySelector('#sacct-apply')?.addEventListener('click', async () => {
            this.dateFrom = this.root.querySelector('#sacct-from')?.value || this.dateFrom;
            this.dateTo = this.root.querySelector('#sacct-to')?.value || this.dateTo;
            this._paintLoading();
            await this._loadTab();
            this._paint();
        });
    }

    _panelHtml() {
        if (this.tab === 'dashboard') return this._dashboardHtml();
        if (this.tab === 'documents') return this._documentsHtml();
        if (this.tab === 'graph') return this._graphHtml();
        if (this.tab === 'ledger') return this._ledgerHtml();
        if (this.tab === 'trial') return this._trialHtml();
        if (this.tab === 'pl') return this._plHtml();
        if (this.tab === 'chart') return this._chartHtml();
        if (this.tab === 'settings') return this._settingsHtml();
        return '';
    }

    _graphHtml() {
        const g = this.graph || {};
        const nodes = g.nodes || [];
        const edges = g.edges || [];
        const persons = g.person_shares || [];
        const orders = g.orders || [];
        const acts = this.activities || [];
        return `
        <div class="sacct-panel sacct-abc">
            <h3>🕸 حسابداری صنعتی فروش — بهای تمام‌شده فعالیت + گراف سهم</h3>
            <p class="sacct-hint">هر سفارش به فعالیت‌های COGS، بسته‌بندی، ارسال و بازاریابی شکسته می‌شود؛ سهم نفر/کانال مشخص است.</p>
            <div class="sacct-abc__toolbar">
                <label>شناسه سفارش <input type="number" id="sacct-abc-oid" min="1" placeholder="مثلاً ۲"></label>
                <button class="sacct-btn" type="button" id="sacct-abc-load">نمایش سفارش</button>
                <button class="sacct-btn sacct-btn--ghost" type="button" id="sacct-abc-alloc">محاسبه و ذخیره</button>
            </div>
            <div class="sacct-abc__layout">
                <svg id="sacct-abc-svg" class="sacct-abc__svg" viewBox="0 0 900 480"></svg>
                <div>
                    <h4>سهم نفرها / نقش‌ها</h4>
                    <table class="sacct-table"><thead><tr><th>نام</th><th>مبلغ</th></tr></thead>
                    <tbody id="sacct-abc-persons">
                        ${persons.length ? persons.map(p => `<tr>
                            <td>${this._esc(p.name)}</td>
                            <td class="num">${this._fmt(p.amount)}</td>
                        </tr>`).join('') : '<tr><td colspan="2">هنوز تخصیصی نیست</td></tr>'}
                    </tbody></table>
                    <h4 style="margin-top:14px">سفارش‌ها</h4>
                    <table class="sacct-table"><thead><tr><th>سفارش</th><th>درآمد</th><th>بهای فعالیت</th></tr></thead>
                    <tbody>
                        ${orders.length ? orders.map(o => `<tr>
                            <td><button type="button" class="sacct-link-btn" data-abc-oid="${o.order_id}">${this._esc(o.order_number || o.order_id)}</button></td>
                            <td class="num">${this._fmt(o.revenue)}</td>
                            <td class="num">${this._fmt(o.cost)}</td>
                        </tr>`).join('') : '<tr><td colspan="3">—</td></tr>'}
                    </tbody></table>
                </div>
            </div>
            <div id="sacct-abc-detail"></div>
            <details style="margin-top:16px"><summary>کاتالوگ فعالیت‌ها (${acts.length})</summary>
                <table class="sacct-table"><thead><tr><th>کد</th><th>نام</th><th>استخر</th><th>وزن</th></tr></thead>
                <tbody>${acts.map(a => `<tr>
                    <td><code>${this._esc(a.code)}</code></td>
                    <td>${this._esc(a.name)}</td>
                    <td>${this._esc(a.pool)}</td>
                    <td>${a.weight}</td>
                </tr>`).join('')}</tbody></table>
            </details>
        </div>`;
    }

    _paintAbcGraph(svg, nodes, edges) {
        if (!svg) return;
        const W = 900, H = 480;
        const TYPE_POS = { order: { x: W * .18, y: H * .5 }, activity: { x: W * .5, y: H * .5 }, person: { x: W * .82, y: H * .5 } };
        const COLOR = { order: '#1F6B4A', activity: '#B8923A', person: '#0F3D2A' };
        const placed = (nodes || []).map((n, i) => {
            const seed = TYPE_POS[n.type] || { x: W / 2, y: H / 2 };
            return { ...n, x: seed.x, y: Math.max(40, Math.min(H - 40, seed.y + (i % 8) * 36 - 120)), vx: 0, vy: 0 };
        });
        const map = Object.fromEntries(placed.map(n => [n.id, n]));
        for (let t = 0; t < 70; t++) {
            placed.forEach(n => { n.fx = 0; n.fy = 0; });
            for (let i = 0; i < placed.length; i++) {
                for (let j = i + 1; j < placed.length; j++) {
                    const a = placed[i], b = placed[j];
                    const dx = b.x - a.x, dy = b.y - a.y;
                    const d2 = dx * dx + dy * dy + 0.01;
                    const f = 2400 / d2, d = Math.sqrt(d2);
                    a.fx -= f * dx / d; a.fy -= f * dy / d;
                    b.fx += f * dx / d; b.fy += f * dy / d;
                }
            }
            (edges || []).forEach(e => {
                const a = map[e.from], b = map[e.to];
                if (!a || !b) return;
                const dx = b.x - a.x, dy = b.y - a.y;
                const d = Math.sqrt(dx * dx + dy * dy) + 0.01;
                const f = (d - 110) * 0.05;
                a.fx += f * dx / d; a.fy += f * dy / d;
                b.fx -= f * dx / d; b.fy -= f * dy / d;
            });
            placed.forEach(n => {
                const anchor = TYPE_POS[n.type] || { x: W / 2, y: H / 2 };
                n.vx = (n.vx + n.fx) * 0.8 - (n.x - anchor.x) * 0.02;
                n.vy = (n.vy + n.fy) * 0.8 - (n.y - anchor.y) * 0.02;
                n.x = Math.max(50, Math.min(W - 50, n.x + n.vx));
                n.y = Math.max(36, Math.min(H - 36, n.y + n.vy));
            });
        }
        const maxAmt = Math.max(1, ...(edges || []).map(e => Number(e.amount || 0)));
        const lines = (edges || []).map(e => {
            const a = map[e.from], b = map[e.to];
            if (!a || !b) return '';
            const w = 1 + 4 * (Number(e.amount || 0) / maxAmt);
            return `<line x1="${a.x}" y1="${a.y}" x2="${b.x}" y2="${b.y}" stroke="#94a3b8" stroke-width="${w}" opacity=".5"/>
                <text x="${(a.x+b.x)/2}" y="${(a.y+b.y)/2-5}" font-size="10" fill="#64748b" text-anchor="middle">${Number(e.amount||0).toLocaleString('fa-IR')}</text>`;
        }).join('');
        const circles = placed.map(n => {
            const r = n.type === 'order' ? 20 : 16;
            const c = COLOR[n.type] || '#64748b';
            return `<g><circle cx="${n.x}" cy="${n.y}" r="${r}" fill="${c}"/><text x="${n.x}" y="${n.y + r + 12}" font-size="11" fill="#1e293b" text-anchor="middle">${this._esc((n.label||'').slice(0,20))}</text></g>`;
        }).join('');
        svg.innerHTML = `<rect width="${W}" height="${H}" fill="#f8fafc"/>${lines}${circles}`;
    }

    _dashboardHtml() {
        const s = this.dashboard.stats || {};
        return `
        <div class="sacct-kpi-grid">
            <div class="sacct-kpi sacct-kpi--amber"><div class="sacct-kpi__label">صف صدور</div><div class="sacct-kpi__val">${s.queue_orders ?? 0}</div></div>
            <div class="sacct-kpi"><div class="sacct-kpi__label">اسناد قطعی</div><div class="sacct-kpi__val">${s.confirmed ?? 0}</div></div>
            <div class="sacct-kpi sacct-kpi--green"><div class="sacct-kpi__label">درآمد ماه</div><div class="sacct-kpi__val">${this._fmt(s.month_revenue)}</div></div>
            <div class="sacct-kpi sacct-kpi--red"><div class="sacct-kpi__label">هزینه ماه</div><div class="sacct-kpi__val">${this._fmt(s.month_expense)}</div></div>
            <div class="sacct-kpi sacct-kpi--green"><div class="sacct-kpi__label">سود ماه</div><div class="sacct-kpi__val">${this._fmt(s.month_profit)}</div></div>
            <div class="sacct-kpi"><div class="sacct-kpi__label">موقعیت نقد</div><div class="sacct-kpi__val">${this._fmt(s.cash_position)}</div></div>
        </div>
        ${this._pendingQueueHtml()}
        <div class="sacct-panel" style="margin-top:16px">
            <p class="sacct-hint">🗂 <strong>سرفصل‌های حسابداری</strong> را در تب <button type="button" class="sacct-link-btn" data-goto="chart">سرفصل‌ها</button> ببینید — به‌صورت خودکار برای فروشگاه ساخته شده‌اند.</p>
        </div>
        <div class="sacct-panel" style="margin-top:16px">
            <h3>📋 آخرین اسناد</h3>
            <div id="sacct-mini-docs"><p class="sacct-empty">در حال بارگذاری…</p></div>
        </div>`;
    }

    _pendingQueueHtml() {
        if (!this.pending.length) return `<div class="sacct-panel"><p class="sacct-empty">صف صدور خالی است ✓</p></div>`;
        return `
        <div class="sacct-panel">
            <h3>⏳ صف صدور سند (SHOP_SALE)</h3>
            <table class="sacct-table">
                <thead><tr><th>سفارش</th><th>مشتری</th><th>مبلغ</th><th>وضعیت</th><th></th></tr></thead>
                <tbody>${this.pending.map(o => `
                <tr>
                    <td>#${this._esc(o.order_number || o.id)}</td>
                    <td>${this._esc(o.billing_name)}</td>
                    <td class="num">${this._fmt(o.subtotal)}</td>
                    <td><span class="sacct-badge sacct-badge--pending">${STATE_LABEL[o.workflow_state] || o.workflow_state}</span></td>
                    <td>${this.canPost ? `<button class="sacct-btn" data-post="${o.id}">صدور سند</button>` : ''}</td>
                </tr>`).join('')}</tbody>
            </table>
        </div>`;
    }

    async _miniDocsHtml() {
        try {
            const d = await this._get('/arag/shop-acct/documents', 'limit=8');
            const rows = d.data || [];
            if (!rows.length) return '<p class="sacct-empty">هنوز سندی ثبت نشده</p>';
            return `<table class="sacct-table"><thead><tr><th>سند</th><th>سفارش</th><th>مبلغ</th><th>وضعیت</th></tr></thead><tbody>
                ${rows.map(r => `<tr>
                    <td>#${r.id}</td><td>${this._esc(r.order_number || '—')}</td>
                    <td class="num">${this._fmt(r.amount)}</td>
                    <td><span class="sacct-badge sacct-badge--${r.workflow_state}">${STATE_LABEL[r.workflow_state] || r.workflow_state}</span></td>
                </tr>`).join('')}
            </tbody></table>`;
        } catch { return '<p class="sacct-empty">—</p>'; }
    }

    _documentsHtml() {
        if (!this.documents.length) return `<div class="sacct-panel"><p class="sacct-empty">سندی یافت نشد</p></div>`;
        return `
        <div class="sacct-panel">
            <h3>📑 اسناد حسابداری فروش (${this.documents.length})</h3>
            <table class="sacct-table">
                <thead><tr><th>سند</th><th>سفارش</th><th>مشتری</th><th>مبلغ</th><th>وضعیت</th><th>تاریخ</th><th></th></tr></thead>
                <tbody>${this.documents.map(r => `
                <tr>
                    <td>#${r.id}<br><small>${this._esc(r.source_module || 'arag_shop')}</small></td>
                    <td>${this._esc(r.order_number || '—')}</td>
                    <td>${this._esc(r.billing_name || '—')}</td>
                    <td class="num">${this._fmt(r.amount)}</td>
                    <td><span class="sacct-badge sacct-badge--${r.workflow_state}">${STATE_LABEL[r.workflow_state] || r.workflow_state}</span></td>
                    <td class="num">${this._esc((r.created_at || '').slice(0, 10))}</td>
                    <td><button class="sacct-btn sacct-btn--ghost" data-doc="${r.id}">جزئیات</button></td>
                </tr>`).join('')}</tbody>
            </table>
            <div id="sacct-doc-detail">${this.selectedDoc ? this._docDetailHtml(this.selectedDoc) : ''}</div>
        </div>`;
    }

    _docDetailHtml(doc) {
        const flows = doc.flows || [];
        return `
        <div class="sacct-detail">
            <h4>سند #${doc.id} — ${STATE_LABEL[doc.workflow_state] || doc.workflow_state}</h4>
            <p>مبلغ: <b>${this._fmt(doc.amount)}</b> · نوع: SHOP_SALE · ماژول: arag_shop</p>
            ${flows.length ? `<table class="sacct-table"><thead><tr><th>بدهکار</th><th>بستانکار</th><th>مبلغ</th><th>شرح</th></tr></thead><tbody>
                ${flows.map(f => `<tr>
                    <td>${this._esc(f.from_code)} ${this._esc(f.from_name)}</td>
                    <td>${this._esc(f.to_code)} ${this._esc(f.to_name)}</td>
                    <td class="num">${this._fmt(f.amount)}</td>
                    <td>${this._esc(f.description)}</td>
                </tr>`).join('')}
            </tbody></table>` : '<p>ردیف دفتر هنوز ایجاد نشده (در صف)</p>'}
        </div>`;
    }

    _ledgerHtml() {
        if (!this.ledger.length) return `<div class="sacct-panel"><p class="sacct-empty">ردیف دفتر کل در این بازه نیست — ابتدا اسناد را صادر کنید</p></div>`;
        return `
        <div class="sacct-panel">
            <h3>📒 دفتر کل — فقط اسناد فروشگاه (SHOP)</h3>
            <table class="sacct-table">
                <thead><tr><th>تاریخ</th><th>سند</th><th>سفارش</th><th>بدهکار</th><th>بستانکار</th><th>مبلغ</th><th>شرح</th></tr></thead>
                <tbody>${this.ledger.map(r => `
                <tr>
                    <td class="num">${this._esc((r.created_at || '').slice(0, 10))}</td>
                    <td>#${r.event_id}</td>
                    <td>${this._esc(r.order_number || '—')}</td>
                    <td>${this._esc(r.dr_code)} ${this._esc(r.dr_name)}</td>
                    <td>${this._esc(r.cr_code)} ${this._esc(r.cr_name)}</td>
                    <td class="num">${this._fmt(r.amount)}</td>
                    <td>${this._esc(r.description)}</td>
                </tr>`).join('')}</tbody>
            </table>
        </div>`;
    }

    _trialHtml() {
        const rows = this.trial.rows || [];
        if (!rows.length) return `<div class="sacct-panel"><p class="sacct-empty">تراز خالی — اسناد را صادر و تأیید کنید</p></div>`;
        return `
        <div class="sacct-panel">
            <h3>⚖️ تراز آزمایشی — ${this.trial.balanced ? '✓ متوازن' : '⚠ نامتوازن'}</h3>
            <table class="sacct-table">
                <thead><tr><th>کد</th><th>حساب</th><th>بدهکار</th><th>بستانکار</th><th>مانده</th></tr></thead>
                <tbody>${rows.map(r => `
                <tr>
                    <td>${this._esc(r.code)}</td><td>${this._esc(r.name)}</td>
                    <td class="num">${this._fmt(r.total_debit)}</td>
                    <td class="num">${this._fmt(r.total_credit)}</td>
                    <td class="num">${this._fmt(r.net_balance)}</td>
                </tr>`).join('')}
                <tr style="font-weight:700;background:#f0fdf4">
                    <td colspan="2">جمع</td>
                    <td class="num">${this._fmt(this.trial.total_dr)}</td>
                    <td class="num">${this._fmt(this.trial.total_cr)}</td>
                    <td></td>
                </tr>
            </tbody></table>
        </div>`;
    }

    _plHtml() {
        const t = this.pl.totals || {};
        const plLine = (rows) => rows?.length
            ? rows.map(r => `<tr><td>${this._esc(r.code)}</td><td>${this._esc(r.name)}</td><td class="num">${this._fmt(r.amount)}</td></tr>`).join('')
            : '<tr><td colspan="3" class="sacct-empty">—</td></tr>';
        return `
        <div class="sacct-panel">
            <h3>💹 صورت سود و زیان — فروش فروشگاه</h3>
            <div class="sacct-pl-section"><h4>درآمد (GL)</h4>
                <table class="sacct-table"><tbody>${plLine(this.pl.revenue)}</tbody></table>
                <div class="sacct-pl-total"><span>جمع درآمد</span><span>${this._fmt(t.revenue)}</span></div>
            </div>
            <div class="sacct-pl-section"><h4>کسورات</h4>
                <table class="sacct-table"><tbody>${plLine(this.pl.contra)}</tbody></table>
            </div>
            <div class="sacct-pl-section"><h4>هزینه دفتر (GL)</h4>
                <table class="sacct-table"><tbody>${plLine(this.pl.expense_gl)}</tbody></table>
            </div>
            <div class="sacct-pl-section"><h4>هزینه عملیاتی (ERP)</h4>
                <table class="sacct-table"><tbody>${plLine(this.pl.expense_op)}</tbody></table>
                <div class="sacct-pl-total"><span>جمع هزینه</span><span>${this._fmt(t.expense_total)}</span></div>
            </div>
            <div class="sacct-pl-total sacct-pl-total--net"><span>سود خالص</span><span>${this._fmt(t.net_income)}</span></div>
        </div>`;
    }

    _chartHtml() {
        const rows = this._chartRows();
        if (!rows.length) {
            return `<div class="sacct-panel"><p class="sacct-empty">سرفصل‌ها در حال بارگذاری… اگر خالی ماند یک‌بار <code>php run-portal-accounting-install.php</code> را اجرا کنید.</p></div>`;
        }
        return `<div class="sacct-panel">
            <h3>🗂 سرفصل‌های حسابداری — ${this._esc(this.meta.ledger_tag || 'SHOP')}</h3>
            <p class="sacct-hint">این سرفصل‌ها مخصوص پورتال <strong>فروشگاه عرقیات</strong> است و جدا از ERP مرکزی و پورتال‌های دیگر (خدمات، هواداران) است. نیازی به تعریف دستی نیست.</p>
            <table class="sacct-table"><thead><tr><th>کد</th><th>نام سر فصل / حساب</th><th>نوع</th></tr></thead>
            <tbody>${rows.map(a => `<tr>
                <td><code>${this._esc(a.code)}</code></td>
                <td style="padding-right:${(a.depth||0)*16}px">${a.depth ? '└ ' : ''}${this._esc(a.name)}</td>
                <td><span class="sacct-type sacct-type--${this._esc(a.account_type)}">${this._esc(a.account_type)}</span></td>
            </tr>`).join('')}</tbody></table>
            <p class="sacct-hint" style="margin-top:12px">ماژول: <code>arag_shop</code> · ${rows.length} حساب</p>
        </div>`;
    }

    _settingsHtml() {
        const cfg = this.config;
        return `
        <div class="sacct-panel">
            <h3>⚙️ تنظیمات حسابداری فروش</h3>
            <form id="sacct-config-form">
                <div class="sacct-config-grid">
                    <div class="sacct-config-item"><label>بهای تمام‌شده COGS (%)</label>
                        <input type="number" name="cogs_pct" value="${cfg.cogs_pct ?? 55}" min="0" max="100" step="0.1"></div>
                    <div class="sacct-config-item"><label>بسته‌بندی / fulfillment (%)</label>
                        <input type="number" name="fulfillment_pct" value="${cfg.fulfillment_pct ?? 4}" min="0" max="100" step="0.1"></div>
                    <div class="sacct-config-item"><label>هزینه ارسال (%)</label>
                        <input type="number" name="shipping_cost_pct" value="${cfg.shipping_cost_pct ?? 3}" min="0" max="100" step="0.1"></div>
                    <div class="sacct-config-item"><label>بازاریابی / معرف (%)</label>
                        <input type="number" name="marketing_pct" value="${cfg.marketing_pct ?? 2}" min="0" max="100" step="0.1"></div>
                    <div class="sacct-config-item"><label>عملیات / درگاه (%)</label>
                        <input type="number" name="ops_pct" value="${cfg.ops_pct ?? 1.5}" min="0" max="100" step="0.1"></div>
                    <div class="sacct-config-item"><label>صدور خودکار سند</label>
                        <input type="checkbox" name="auto_post" ${cfg.auto_post ? 'checked' : ''}></div>
                </div>
                ${this.canPost ? `<button class="sacct-btn" type="submit" style="margin-top:12px">ذخیره</button>` : '<p><small>فقط حسابدار می‌تواند تنظیمات را ویرایش کند</small></p>'}
            </form>
            <p class="sacct-hint" style="margin-top:16px">مشاهده درخت سرفصل‌ها: تب <button type="button" class="sacct-link-btn" data-goto="chart">🗂 سرفصل‌ها</button></p>
        </div>`;
    }

    _bindActions() {
        this.root.querySelectorAll('[data-post]').forEach(btn => {
            btn.addEventListener('click', async () => {
                btn.disabled = true;
                try {
                    await this._post('/arag/shop-acct/post/' + btn.dataset.post);
                    this._paintLoading();
                    await this._loadTab();
                    this._paint();
                } catch (e) { alert(e.message); btn.disabled = false; }
            });
        });
        this.root.querySelectorAll('[data-doc]').forEach(btn => {
            btn.addEventListener('click', async () => {
                try {
                    const d = await this._get('/arag/shop-acct/documents/' + btn.dataset.doc);
                    this.selectedDoc = d.data;
                    const el = this.root.querySelector('#sacct-doc-detail');
                    if (el) el.innerHTML = this._docDetailHtml(this.selectedDoc);
                } catch (e) { alert(e.message); }
            });
        });
        this.root.querySelector('#sacct-config-form')?.addEventListener('submit', async e => {
            e.preventDefault();
            const fd = new FormData(e.target);
            try {
                await fetch(this._api() + '/arag/erp/accounting/config', {
                    method: 'PUT',
                    headers: { Authorization: 'Bearer ' + this.token, 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        cogs_pct: parseFloat(fd.get('cogs_pct')) || 55,
                        fulfillment_pct: parseFloat(fd.get('fulfillment_pct')) || 4,
                        shipping_cost_pct: parseFloat(fd.get('shipping_cost_pct')) || 3,
                        marketing_pct: parseFloat(fd.get('marketing_pct')) || 2,
                        ops_pct: parseFloat(fd.get('ops_pct')) || 1.5,
                        auto_post: !!fd.get('auto_post'),
                    }),
                });
                alert('ذخیره شد');
            } catch { alert('خطا در ذخیره'); }
        });

        if (this.tab === 'dashboard') {
            this._loadMiniDocs();
        }
        if (this.tab === 'graph') {
            this._paintAbcGraph(
                this.root.querySelector('#sacct-abc-svg'),
                this.graph?.nodes || [],
                this.graph?.edges || []
            );
            const loadOne = async (oid) => {
                if (!oid) return;
                const g = await this._get('/arag/shop-acct/cost-graph', 'order_id=' + oid);
                this._paintAbcGraph(this.root.querySelector('#sacct-abc-svg'), g.data?.nodes || [], g.data?.edges || []);
                const c = await this._get('/arag/shop-acct/activity-cost/' + oid);
                const alloc = c.data || {};
                const detail = this.root.querySelector('#sacct-abc-detail');
                if (detail) {
                    detail.innerHTML = `
                    <h4 style="margin-top:16px">جزئیات سفارش #${this._esc(String(oid))}</h4>
                    <div class="sacct-kpi-grid">
                        ${Object.entries(alloc.pools || {}).map(([k, v]) =>
                            `<div class="sacct-kpi"><div class="sacct-kpi__label">${this._esc(k)}</div><div class="sacct-kpi__val">${this._fmt(v)}</div></div>`
                        ).join('')}
                    </div>
                    <table class="sacct-table" style="margin-top:12px"><thead><tr><th>فعالیت</th><th>نفر/نقش</th><th>سهم٪</th><th>مبلغ</th></tr></thead>
                    <tbody>${(alloc.lines || []).map(l => `<tr>
                        <td>${this._esc(l.activity_name)}</td>
                        <td>${this._esc(l.person_label)}</td>
                        <td>${Number(l.share_pct || 0).toLocaleString('fa-IR')}</td>
                        <td class="num">${this._fmt(l.amount)}</td>
                    </tr>`).join('')}</tbody></table>`;
                }
                const pe = this.root.querySelector('#sacct-abc-persons');
                if (pe) {
                    pe.innerHTML = (alloc.person_shares || []).map(p => `<tr>
                        <td>${this._esc(p.name)}</td><td class="num">${this._fmt(p.amount)}</td>
                    </tr>`).join('') || '<tr><td colspan="2">—</td></tr>';
                }
            };
            this.root.querySelector('#sacct-abc-load')?.addEventListener('click', () => {
                loadOne(this.root.querySelector('#sacct-abc-oid')?.value);
            });
            this.root.querySelector('#sacct-abc-alloc')?.addEventListener('click', async () => {
                const oid = this.root.querySelector('#sacct-abc-oid')?.value;
                if (!oid) return alert('شناسه سفارش را وارد کنید');
                await this._post('/arag/shop-acct/allocate/' + oid);
                await loadOne(oid);
                alert('تخصیص ذخیره شد');
            });
            this.root.querySelectorAll('[data-abc-oid]').forEach(btn => {
                btn.addEventListener('click', () => {
                    this.root.querySelector('#sacct-abc-oid').value = btn.dataset.abcOid;
                    loadOne(btn.dataset.abcOid);
                });
            });
        }
        this.root.querySelectorAll('[data-goto]').forEach(btn => {
            btn.addEventListener('click', async () => {
                this.tab = btn.dataset.goto;
                this._paintLoading();
                await this._loadTab();
                this._paint();
            });
        });
    }

    async _loadMiniDocs() {
        const el = this.root.querySelector('#sacct-mini-docs');
        if (!el) return;
        el.innerHTML = await this._miniDocsHtml();
    }

    _chartRows() {
        const byId = Object.fromEntries(this.chart.map(a => [a.id, a]));
        const roots = this.chart.filter(a => !a.parent_id || !byId[a.parent_id]);
        const out = [];
        const walk = (node, depth) => {
            out.push({ ...node, depth });
            this.chart.filter(c => c.parent_id == node.id).forEach(ch => walk(ch, depth + 1));
        };
        roots.forEach(r => walk(r, 0));
        return out.length ? out : this.chart.map(a => ({ ...a, depth: 0 }));
    }
}
