/**
 * MelkWorkspace — هسته داشبورد اقتصاد ملک (مستقل از ERP)
 */
import {
    MELK_ROLE_LABELS as ROLE_LABELS,
    renderMelkCaseCollaboration,
    bindMelkCaseTabs,
    filterMelkNotesByMember,
} from './melk-case-detail.js';
import {
    renderRenovationHubSearch,
    renderRenovationHub,
    bindRenovationHub,
} from './melk-renovation-hub.js';
import { renderConstructionPanel, bindConstructionPanel } from './melk-construction-panel.js';
import { renderListingsPanel, bindListingsPanel } from './melk-listings-panel.js';
import { renderServicesPanel, bindServicesPanel } from './melk-services-panel.js';
import { renderCountyAgenciesPanel, bindCountyAgenciesPanel } from './melk-county-agencies-panel.js';
import { renderBuildingSpecialistsPanel, bindBuildingSpecialistsPanel } from './melk-building-specialists-panel.js';
import { renderInvestorPanel, bindInvestorPanel } from './melk-investor-panel.js';
import { renderAdvisoryPanel, bindAdvisoryPanel } from './melk-advisory-panel.js';
import { renderAccountingPanel, bindAccountingPanel } from './melk-accounting-panel.js';
import { PortalChatPanel } from '../../shared/portal-chat-panel.js';

const STATUS_CFG = {
    open:        { label: 'باز',      color: '#3b82f6' },
    in_progress: { label: 'در جریان', color: '#f59e0b' },
    review:      { label: 'بررسی',    color: '#8b5cf6' },
    closed:      { label: 'بسته',     color: '#94a3b8' },
};

export default class MelkWorkspace {
    constructor({ root, request, can, erpUrl, onReady }) {
        this.root = root;
        this.request = request;
        this.can = can || (() => false);
        this.erpUrl = erpUrl || '/acc-engine/';
        this.onReady = onReady || (() => {});
        this._tab = 'dashboard';
        this._overview = null;
        this._data = [];
        this._cases = [];
        this._org = [];
        this._level = 'district';
        this._path = [];
        this._search = '';
        this._caseSearch = '';
        this._caseDistrictFilter = '';
        this._participantRoles = [];
        this._blockCtx = null;
        this._usersCache = [];
        this._renoCode = '';
    }

    _canRenovationHub() {
        return this.can('melk.manage') || this.can('*');
    }

    $(name) {
        return this.root.querySelector(`[data-ref="${name}"]`);
    }

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

    _toast(msg, isErr = false) {
        let el = this.root.querySelector('.em-toast');
        if (!el) {
            el = document.createElement('div');
            el.className = 'em-toast';
            this.root.appendChild(el);
        }
        el.textContent = msg;
        el.className = 'em-toast' + (isErr ? ' em-toast--err' : ' em-toast--ok');
        el.style.display = 'block';
        clearTimeout(this._toastT);
        this._toastT = setTimeout(() => { el.style.display = 'none'; }, 3500);
    }

    _canEditCase(full = false) {
        if (this.can('melk.cases.edit') || this.can('melk.manage')) return true;
        return !full && this.can('melk.cases.participate');
    }

    async init() {
        this.root.innerHTML = this._shellHtml();
        if (this.can('melk.manage')) {
            const orgTab = this.$('mainTabs')?.querySelector('[data-tab="org"]');
            if (orgTab) orgTab.style.display = '';
        }
        try {
            const pr = await this.request('GET', 'melk/participant-roles');
            this._participantRoles = pr?.data ?? [];
        } catch { this._participantRoles = []; }
        if (this._canRenovationHub()) {
            const hubTab = this.$('mainTabs')?.querySelector('[data-tab="reno"]');
            if (hubTab) hubTab.style.display = '';
        }
        if (this.can('melk.investor.manage')) {
            const invTab = this.$('mainTabs')?.querySelector('[data-tab="investor"]');
            if (invTab) invTab.style.display = '';
        }
        if (this.can('melk.advisory.use')) {
            const advTab = this.$('mainTabs')?.querySelector('[data-tab="advisory"]');
            if (advTab) advTab.style.display = '';
        }
        await this._loadOverview();
        this._bindEvents();
        await this._checkGisHandoff();
        this.onReady(this);
    }

    _shellHtml() {
        return `<div class="em-wrap red-wrap em-standalone" dir="rtl">
            <div class="red-hero em-hero">
                <div class="red-hero-title">
                    <span class="red-hero-icon">🏛️</span>
                    <div>
                        <div class="red-hero-name">اقتصاد ملک</div>
                        <div class="red-hero-sub">منطقه → محله → بلوک → ملک → پرونده همکاری</div>
                    </div>
                </div>
                <div class="red-kpis">
                    <div class="red-kpi"><div class="red-kpi-val" data-ref="kDistricts">—</div><div class="red-kpi-lbl">منطقه</div></div>
                    <div class="red-kpi"><div class="red-kpi-val" data-ref="kCases">—</div><div class="red-kpi-lbl">پرونده باز</div></div>
                    <div class="red-kpi"><div class="red-kpi-val em-role-chip" data-ref="kRole">—</div><div class="red-kpi-lbl">نقش شما</div></div>
                </div>
            </div>
            <div class="em-main-tabs" data-ref="mainTabs">
                <button class="em-main-tab em-main-tab--active" data-tab="dashboard">🗺️ داشبورد</button>
                <button class="em-main-tab" data-tab="cases">📋 پرونده‌ها</button>
                <button class="em-main-tab" data-tab="listings">🏠 بازار ملک</button>
                <button class="em-main-tab em-main-tab--investor" data-tab="investor" style="display:none">💎 سرمایه‌گذار</button>
                <button class="em-main-tab em-main-tab--advisory" data-tab="advisory" style="display:none">📑 مالیات و حقوق</button>
                <button class="em-main-tab" data-tab="construction">🔨 ساخت‌وساز</button>
                <button class="em-main-tab em-main-tab--acct" data-tab="accounting">📒 حسابداری مشارکت</button>
                <button class="em-main-tab" data-tab="county">🏘️ بنگاه شهرستان</button>
                <button class="em-main-tab" data-tab="specialists">👷 متخصصان</button>
                <button class="em-main-tab" data-tab="services">🔧 خدمات</button>
                <button class="em-main-tab em-main-tab--reno" data-tab="reno" style="display:none">🔗 کد نوسازی</button>
                <button class="em-main-tab em-main-tab--org" data-tab="org" style="display:none">👥 سازمان</button>
                <button class="em-main-tab" data-tab="chat">💬 چت پشتیبانی</button>
            </div>
            <div data-ref="panelDashboard">
                <div class="em-toolbar red-toolbar">
                    <input class="red-inp" placeholder="🔍 جستجو..." data-ref="searchInput">
                    <div class="red-crumbs" data-ref="crumbs"></div>
                    <button class="red-btn" data-ref="backBtn" style="display:none">← بازگشت</button>
                    <button class="red-btn red-btn--primary" data-ref="refreshBtn">↻</button>
                    <button class="red-btn" data-ref="newCaseBtn" style="display:none">➕ پرونده</button>
                    <button class="red-btn" data-ref="mapBtn">🗺️ نقشه ERP</button>
                </div>
                <div class="em-grid red-grid" data-ref="grid"></div>
            </div>
            <div data-ref="panelCases" style="display:none">
                <div class="em-toolbar red-toolbar">
                    <input class="red-inp" placeholder="🔍 جستجوی پرونده..." data-ref="caseSearchInput">
                    <select class="red-sel" data-ref="caseDistrictFilter"><option value="">همه مناطق</option></select>
                    <select class="red-sel" data-ref="caseStatusFilter">
                        <option value="">همه وضعیت‌ها</option>
                        <option value="open">باز</option>
                        <option value="in_progress">در جریان</option>
                        <option value="review">بررسی</option>
                        <option value="closed">بسته</option>
                    </select>
                    <button class="red-btn red-btn--primary" data-ref="reloadCasesBtn">↻</button>
                </div>
                <div class="em-cases-full" data-ref="casesFull"></div>
            </div>
            <div data-ref="panelOrg" style="display:none">
                <div class="em-org-form" data-ref="orgForm"></div>
                <div class="em-org-list" data-ref="orgList"></div>
            </div>
            <div data-ref="panelReno" style="display:none">
                <div class="em-reno-panel" data-ref="renoPanel"></div>
            </div>
            <div data-ref="panelListings" style="display:none" data-ref-panel="listings"></div>
            <div data-ref="panelInvestor" style="display:none" data-ref-panel="investor"></div>
            <div data-ref="panelAdvisory" style="display:none" data-ref-panel="advisory"></div>
            <div data-ref="panelConstruction" style="display:none" data-ref-panel="construction"></div>
            <div data-ref="panelAccounting" style="display:none" data-ref-panel="accounting"></div>
            <div data-ref="panelCounty" style="display:none" data-ref-panel="county"></div>
            <div data-ref="panelSpecialists" style="display:none" data-ref-panel="specialists"></div>
            <div data-ref="panelServices" style="display:none" data-ref-panel="services"></div>
            <div data-ref="panelChat" style="display:none;height:calc(100vh - 160px);"></div>
            <div class="em-case-overlay" data-ref="detailOverlay" style="display:none" aria-hidden="true">
                <div class="em-case-modal" role="dialog" aria-modal="true">
                    <div class="em-case-modal-head">
                        <div class="em-case-modal-head-text" data-ref="detailHead"></div>
                        <button type="button" class="em-case-modal-close" data-ref="detailClose" aria-label="بستن">✕</button>
                    </div>
                    <div class="em-case-modal-body" data-ref="detailBody"></div>
                </div>
            </div>
        </div>`;
    }

    async _checkGisHandoff() {
        try {
            const raw = sessionStorage.getItem('acc_melk_create_parcel');
            if (!raw) return;
            sessionStorage.removeItem('acc_melk_create_parcel');
            const p = JSON.parse(raw);
            if (p?.parcel_id) await this._createCaseFromParcel(p);
        } catch { /* */ }
    }

    async _loadOverview() {
        try {
            const roleHint = sessionStorage.getItem('melk_selected_role') || '';
            const res = await this.request('GET', `melk/overview${roleHint ? '?role_hint=' + encodeURIComponent(roleHint) : ''}`);
            this._overview = res?.data ?? res;
            if (this._overview?.code === 'rest_forbidden' || this._overview?.data?.status === 403) {
                throw new Error(this._overview?.message || 'دسترسی به داشبورد ندارید');
            }
            this._data = this._overview?.districts ?? [];
            this._level = 'district';
            this._path = [];
            this._blockCtx = null;
            this._updateKpis();
            if (this._tab === 'dashboard') {
                this._renderGrid();
                this._renderCrumbs();
            }
        } catch (e) {
            this._overview = null;
            this._data = [];
            this._updateKpis();
            const grid = this.$('grid');
            if (grid) grid.innerHTML = `<div class="em-empty">${this.esc(e.message || 'خطا در بارگذاری داشبورد')}</div>`;
            this._toast(e.message || 'خطا در بارگذاری داشبورد', true);
        }
    }

    async _switchMainTab(tab) {
        this._tab = tab;
        this.$('mainTabs')?.querySelectorAll('.em-main-tab').forEach(b =>
            b.classList.toggle('em-main-tab--active', b.dataset.tab === tab));
        this.$('panelDashboard').style.display = tab === 'dashboard' ? '' : 'none';
        this.$('panelCases').style.display = tab === 'cases' ? '' : 'none';
        this.$('panelOrg').style.display = tab === 'org' ? '' : 'none';
        this.$('panelReno').style.display = tab === 'reno' ? '' : 'none';
        this.$('panelListings').style.display = tab === 'listings' ? '' : 'none';
        this.$('panelInvestor').style.display = tab === 'investor' ? '' : 'none';
        this.$('panelAdvisory').style.display = tab === 'advisory' ? '' : 'none';
        this.$('panelConstruction').style.display = tab === 'construction' ? '' : 'none';
        if (this.$('panelAccounting')) this.$('panelAccounting').style.display = tab === 'accounting' ? '' : 'none';
        this.$('panelCounty').style.display = tab === 'county' ? '' : 'none';
        this.$('panelSpecialists').style.display = tab === 'specialists' ? '' : 'none';
        this.$('panelServices').style.display = tab === 'services' ? '' : 'none';
        this.$('panelChat').style.display = tab === 'chat' ? '' : 'none';
        if (tab === 'cases') {
            await this._populateCaseDistrictFilter();
            await this._loadCases();
        }
        if (tab === 'org') await this._loadOrg();
        if (tab === 'reno') this._renderRenovationPanel();
        if (tab === 'listings') await this._renderListingsPanel();
        if (tab === 'investor') await this._renderInvestorPanel();
        if (tab === 'advisory') await this._renderAdvisoryPanel();
        if (tab === 'construction') await this._renderConstructionPanel();
        if (tab === 'accounting') await this._renderAccountingPanel();
        if (tab === 'county') await this._renderCountyPanel();
        if (tab === 'specialists') await this._renderSpecialistsPanel();
        if (tab === 'services') this._renderServicesPanel();
        if (tab === 'chat') this._renderChatPanel();
    }

    async _renderListingsPanel() {
        const panel = this.$('panelListings');
        if (!panel || panel.dataset.bound) return;
        const canPublish = this.can('melk.manage') || this.can('melk.listings.publish') || this.can('*');
        panel.innerHTML = renderListingsPanel((t) => this.esc(t), { canPublish });
        panel.dataset.bound = '1';
        await bindListingsPanel(panel, {
            request: (m, p, b) => this.request(m, p, b),
            esc: (t) => this.esc(t),
            toast: (m, e) => this._toast(m, e),
            can: (k) => this.can(k),
        });
    }

    async _renderAccountingPanel() {
        const panel = this.$('panelAccounting');
        if (!panel || panel.dataset.bound) return;
        panel.innerHTML = renderAccountingPanel((t) => this.esc(t));
        panel.dataset.bound = '1';
        await bindAccountingPanel(panel, {
            request: (m, p, b) => this.request(m, p, b),
            esc: (t) => this.esc(t),
            toast: (m, e) => this._toast(m, e),
        });
    }

    async _renderConstructionPanel() {
        const panel = this.$('panelConstruction');
        if (!panel || panel.dataset.bound) return;
        panel.innerHTML = renderConstructionPanel((t) => this.esc(t));
        panel.dataset.bound = '1';
        await bindConstructionPanel(panel, {
            request: (m, p, b) => this.request(m, p, b),
            esc: (t) => this.esc(t),
            toast: (m, e) => this._toast(m, e),
        });
    }

    async _renderAdvisoryPanel() {
        const panel = this.$('panelAdvisory');
        if (!panel || panel.dataset.bound) return;
        panel.innerHTML = renderAdvisoryPanel((t) => this.esc(t));
        panel.dataset.bound = '1';
        await bindAdvisoryPanel(panel, {
            request: (m, p, b) => this.request(m, p, b),
            esc: (t) => this.esc(t),
            toast: (m, e) => this._toast(m, e),
        });
    }

    async _renderInvestorPanel() {
        const panel = this.$('panelInvestor');
        if (!panel || panel.dataset.bound) return;
        panel.innerHTML = renderInvestorPanel((t) => this.esc(t));
        panel.dataset.bound = '1';
        await bindInvestorPanel(panel, {
            request: (m, p, b) => this.request(m, p, b),
            esc: (t) => this.esc(t),
            toast: (m, e) => this._toast(m, e),
        });
    }

    async _renderCountyPanel() {
        const panel = this.$('panelCounty');
        if (!panel || panel.dataset.bound) return;
        const canManage = this.can('melk.manage') || this.can('melk.county.manage') || this.can('*');
        panel.innerHTML = renderCountyAgenciesPanel((t) => this.esc(t), { canManage });
        panel.dataset.bound = '1';
        await bindCountyAgenciesPanel(panel, {
            request: (m, p, b) => this.request(m, p, b),
            esc: (t) => this.esc(t),
            toast: (m, e) => this._toast(m, e),
            can: (k) => this.can(k),
        });
    }

    async _renderSpecialistsPanel() {
        const panel = this.$('panelSpecialists');
        if (!panel || panel.dataset.bound) return;
        const canApprove = this.can('melk.manage') || this.can('melk.specialists.approve') || this.can('*');
        const canRegister = this.can('melk.specialists.register') || canApprove;
        panel.innerHTML = renderBuildingSpecialistsPanel((t) => this.esc(t), { canApprove, canRegister });
        panel.dataset.bound = '1';
        await bindBuildingSpecialistsPanel(panel, {
            request: (m, p, b) => this.request(m, p, b),
            esc: (t) => this.esc(t),
            toast: (m, e) => this._toast(m, e),
            can: (k) => this.can(k),
        });
    }

    _renderServicesPanel() {
        const panel = this.$('panelServices');
        if (!panel || panel.dataset.bound) return;
        const apiBase = (window.ACC_MELK_CFG?.api || '/acc-engine/api.php/acc/v1').replace(/\/$/, '');
        panel.innerHTML = renderServicesPanel((t) => this.esc(t), this.erpUrl);
        panel.dataset.bound = '1';
        bindServicesPanel(panel, {
            apiBase,
            esc: (t) => this.esc(t),
            toast: (m, e) => this._toast(m, e),
        });
    }

    _renderChatPanel() {
        const panel = this.$('panelChat');
        if (!panel || panel.dataset.bound) return;
        panel.dataset.bound = '1';
        const token   = sessionStorage.getItem('acc_token') || localStorage.getItem('acc_token') || '';
        const apiBase = (window.ACC_MELK_CFG?.api || '/acc-engine/api.php/acc/v1').replace(/\/$/, '');
        const chatPanel = new PortalChatPanel({ container: panel, source: 'melk', token, apiBase });
        chatPanel.mount();
        // نگهداری برای destroy در صورت نیاز
        this._chatPanelInstance = chatPanel;
    }

    _renderRenovationPanel(prefill = '') {
        const panel = this.$('renoPanel');
        if (!panel) return;
        panel.innerHTML = renderRenovationHubSearch((t) => this.esc(t))
            + `<div data-ref="renoResult" class="em-reno-result">${this._renoHubHtml || ''}</div>`;
        if (prefill) {
            const inp = panel.querySelector('[data-ref="renoCodeInput"]');
            if (inp) inp.value = prefill;
        }
        bindRenovationHub(panel, {
            request: (m, p) => this.request(m, p),
            esc: (t) => this.esc(t),
            erpUrl: this.erpUrl,
            onOpenCase: (id) => this._openCase(id),
            onSearch: (code) => this._loadRenovationHub(code),
        });
        if (prefill) this._loadRenovationHub(prefill);
    }

    async _loadRenovationHub(code) {
        const result = this.$('renoPanel')?.querySelector('[data-ref="renoResult"]');
        if (!result) return;
        result.innerHTML = '<div class="em-empty-inline">در حال بارگذاری...</div>';
        try {
            const res = await this.request('GET', `melk/renovation-hub?code=${encodeURIComponent(code)}`);
            const data = res?.data?.data ?? res?.data;
            let parcelFull = null;
            const pid = data?.gis?.parcel_id;
            if (pid) {
                try {
                    const [pRes, uRes] = await Promise.all([
                        this.request('GET', `gis/parcels/${pid}`),
                        this.request('GET', `gis/parcels/${pid}/units`).catch(() => null),
                    ]);
                    parcelFull = pRes?.data?.data ?? pRes?.data ?? null;
                    if (parcelFull) {
                        parcelFull.units = uRes?.data?.data ?? uRes?.data ?? data?.gis?.units ?? [];
                    }
                } catch { /* خلاصه hub کافی است */ }
            }
            data.parcel_full = parcelFull;
            this._renoCode = code;
            this._renoHubHtml = renderRenovationHub(data, (t) => this.esc(t), { erpUrl: this.erpUrl });
            result.innerHTML = this._renoHubHtml;
            bindRenovationHub(result, {
                esc: (t) => this.esc(t),
                erpUrl: this.erpUrl,
                onOpenCase: (id) => this._openCase(id),
                parcelFull,
            });
        } catch (e) {
            result.innerHTML = `<div class="em-empty-inline">${this.esc(e.message || 'خطا')}</div>`;
        }
    }

    _openRenovationHub(code) {
        if (!code || !this._canRenovationHub()) return;
        this._switchMainTab('reno');
        this._renderRenovationPanel(code);
    }

    async _loadCases(filters = {}) {
        const st = this.$('caseStatusFilter')?.value;
        const df = this.$('caseDistrictFilter')?.value;
        if (st) filters.status = st;
        if (df) filters.district_id = df;
        const qs = new URLSearchParams(filters).toString();
        try {
            const res = await this.request('GET', `melk/cases${qs ? '?' + qs : ''}`);
            this._cases = res?.data?.data ?? res?.data ?? [];
            this._renderCasesList(this.$('casesFull'));
        } catch (e) {
            this._toast(e.message || 'خطا در بارگذاری پرونده‌ها', true);
        }
    }

    async _populateCaseDistrictFilter() {
        const sel = this.$('caseDistrictFilter');
        if (!sel || sel.options.length > 1) return;
        try {
            const districts = this._overview?.districts?.length
                ? this._overview.districts
                : ((await this.request('GET', 'melk/overview'))?.districts
                    ?? (await this.request('GET', 'melk/overview'))?.data?.districts
                    ?? []);
            districts.forEach(d => {
                const o = document.createElement('option');
                o.value = d.id;
                o.textContent = d.name;
                sel.appendChild(o);
            });
        } catch { /* */ }
    }

    async _loadOrg() {
        const res = await this.request('GET', 'melk/org-assignments');
        this._org = res?.data?.data ?? res?.data ?? [];
        this._renderOrg();
    }

    async _drill(item) {
        if (this._level === 'district') {
            this._path.push({ level: 'district', id: item.id, label: item.name });
            this._level = 'neighborhood';
            const res = await this.request('GET', `melk/hierarchy?level=neighborhood&district=${item.id}`);
            this._data = res?.data?.data ?? res?.data ?? [];
        } else if (this._level === 'neighborhood') {
            this._path.push({ level: 'neighborhood', id: item.id, label: item.name });
            this._level = 'block';
            const res = await this.request('GET', `melk/hierarchy?level=block&neighborhood=${item.id}`);
            this._data = res?.data?.data ?? res?.data ?? [];
        } else if (this._level === 'block') {
            this._path.push({ level: 'block', id: item.block_code, label: item.block_code, block: item });
            this._level = 'parcel';
            this._blockCtx = item;
            const res = await this.request('GET', `gis/parcels?block=${encodeURIComponent(item.block_code)}`);
            this._data = res?.data?.data ?? res?.data ?? [];
        } else return;
        this._renderGrid();
        this._renderCrumbs();
        this.$('backBtn').style.display = '';
        this._toggleNewCaseBtn();
    }

    _toggleNewCaseBtn() {
        const btn = this.$('newCaseBtn');
        if (!btn) return;
        btn.style.display = this.can('melk.cases.create') && (this._level === 'block' || this._level === 'parcel') ? '' : 'none';
    }

    _updateKpis() {
        const o = this._overview || {};
        if (this.$('kDistricts')) this.$('kDistricts').textContent = o.district_count ?? '—';
        if (this.$('kCases')) this.$('kCases').textContent = o.open_cases ?? '—';
        if (this.$('kRole')) this.$('kRole').textContent = o.user_role || 'کاربر';
    }

    _renderCrumbs() {
        const el = this.$('crumbs');
        if (!el) return;
        const city = this._overview?.city || 'شیراز';
        const parts = [{ label: `🏛️ ${city}` }, ...this._path.map(p => ({ label: p.label }))];
        el.innerHTML = parts.map((p, i) =>
            `<span class="red-crumb${i === parts.length - 1 ? ' red-crumb--active' : ''}" data-idx="${i}">${this.esc(p.label)}</span>`
        ).join('<span class="red-crumb-sep">›</span>');
        el.querySelectorAll('.red-crumb').forEach(c => {
            c.addEventListener('click', () => this._crumbNav(parseInt(c.dataset.idx, 10)));
        });
    }

    async _crumbNav(idx) {
        if (idx <= 0) {
            await this._loadOverview();
            this.$('backBtn').style.display = 'none';
            this._toggleNewCaseBtn();
            return;
        }
        const target = this._path[idx - 1];
        this._path = this._path.slice(0, idx);
        if (target.level === 'district') {
            this._level = 'neighborhood';
            const res = await this.request('GET', `melk/hierarchy?level=neighborhood&district=${target.id}`);
            this._data = res?.data?.data ?? res?.data ?? [];
        } else if (target.level === 'neighborhood') {
            this._level = 'block';
            const res = await this.request('GET', `melk/hierarchy?level=block&neighborhood=${target.id}`);
            this._data = res?.data?.data ?? res?.data ?? [];
            this._blockCtx = null;
        } else if (target.level === 'block') {
            this._level = 'parcel';
            this._blockCtx = target.block;
            const res = await this.request('GET', `gis/parcels?block=${encodeURIComponent(target.id)}`);
            this._data = res?.data?.data ?? res?.data ?? [];
        }
        this._renderGrid();
        this._renderCrumbs();
        this._toggleNewCaseBtn();
    }

    _renderGrid() {
        const grid = this.$('grid');
        if (!grid) return;
        const q = this._search.toLowerCase();
        const items = (this._data || []).filter(r => {
            const name = (r.name || r.block_code || r.code || '').toLowerCase();
            return !q || name.includes(q);
        });
        if (!items.length) {
            grid.innerHTML = `<div class="em-empty">موردی یافت نشد.</div>`;
            return;
        }
        if (this._level === 'district') {
            grid.innerHTML = items.map(d => `
                <div class="red-card em-card" data-id="${d.id}">
                    <div class="em-card-badge" style="background:${d.color || '#6366f1'}">${this.esc(d.code || d.id)}</div>
                    <div class="red-card-title">${this.esc(d.name)}</div>
                    <div class="red-card-meta"><span>🏘️ ${d.neighborhood_count || 0}</span><span>📍 ${d.parcel_count || 0}</span></div>
                    ${d.lead_name ? `<div class="em-lead">👤 ${this.esc(d.lead_name)}</div>` : `<div class="em-lead em-lead--empty">سرگروه تعیین نشده</div>`}
                </div>`).join('');
        } else if (this._level === 'neighborhood') {
            grid.innerHTML = items.map(n => `
                <div class="red-card em-card" data-id="${n.id}">
                    <div class="red-card-title">${this.esc(n.name)}</div>
                    <div class="red-card-meta"><span>🧱 ${n.block_count || 0}</span><span>📍 ${n.parcel_count || 0}</span></div>
                    ${n.manager_name ? `<div class="em-lead">👤 ${this.esc(n.manager_name)}</div>` : ''}
                </div>`).join('');
        } else if (this._level === 'block') {
            grid.innerHTML = items.map(b => `
                <div class="red-card em-card" data-block="${this.esc(b.block_code)}">
                    <div class="red-card-title">🧱 ${this.esc(b.block_code)}</div>
                    <div class="red-card-meta"><span>📍 ${b.parcel_count || 0}</span><span>🏢 ${b.bld_count || 0}</span></div>
                    ${b.open_cases > 0 ? `<div class="em-case-badge">${b.open_cases} پرونده</div>` : ''}
                </div>`).join('');
        } else {
            grid.innerHTML = items.map(p => `
                <div class="red-card em-card em-card--parcel" data-parcel="${p.id}">
                    <div class="red-card-title">${this.esc(p.code || 'ملک #' + p.id)}</div>
                    <div class="red-card-meta"><span>${this.esc(p.status || '')}</span>${p.area_sqm ? `<span>${p.area_sqm} m²</span>` : ''}</div>
                    <div class="em-card-actions">
                        ${this.can('melk.cases.create') ? `<button class="em-mini-btn" data-action="case" data-id="${p.id}">➕ پرونده</button>` : ''}
                        <button class="em-mini-btn em-mini-btn--map" data-action="map" data-id="${p.id}" data-block="${this.esc(p.block_code || '')}">🗺️ نقشه</button>
                    </div>
                </div>`).join('');
        }
        grid.querySelectorAll('.red-card').forEach(card => {
            card.addEventListener('click', (e) => {
                if (e.target.closest('[data-action]')) return;
                if (this._level === 'parcel') return;
                const item = items.find(x => String(x.id) === card.dataset.id || x.block_code === card.dataset.block);
                if (item) this._drill(item);
            });
        });
        grid.querySelectorAll('[data-action="case"]').forEach(btn => {
            btn.addEventListener('click', async (e) => {
                e.stopPropagation();
                const p = items.find(x => String(x.id) === btn.dataset.id);
                if (p) await this._createCaseFromParcel(p);
            });
        });
        grid.querySelectorAll('[data-action="map"]').forEach(btn => {
            btn.addEventListener('click', (e) => {
                e.stopPropagation();
                const block = btn.dataset.block;
                if (block) sessionStorage.setItem('acc_gis_focus_block', JSON.stringify({ block }));
                window.open(this.erpUrl + 'index.php?tab=gis', '_blank');
            });
        });
    }

    _renderCasesList(el) {
        if (!el) return;
        const q = this._caseSearch.toLowerCase();
        const filtered = (this._cases || []).filter(c => {
            if (!q) return true;
            const hay = [c.case_key, c.title, c.district_name, c.neighborhood_name, c.block_code, c.parcel_code, c.renovation_code, c.renovation_code_display].join(' ').toLowerCase();
            return hay.includes(q);
        });
        if (!filtered.length) {
            el.innerHTML = `<div class="em-empty">پرونده‌ای یافت نشد.</div>`;
            return;
        }
        el.innerHTML = `<div class="em-case-grid">${filtered.map(c => {
            const st = STATUS_CFG[c.status] || STATUS_CFG.open;
            const loc = [c.district_name, c.neighborhood_name, c.block_code].filter(Boolean).join(' › ');
            const reno = c.renovation_code_display || c.renovation_code || c.parcel_code || '';
            return `<button type="button" class="em-case-card" data-case="${c.id}">
                <div class="em-case-card-top">
                    <span class="em-case-key">${this.esc(c.case_key)}</span>
                    <span class="em-status" style="background:${st.color}">${st.label}</span>
                </div>
                ${reno ? `<div class="em-case-reno" dir="ltr">🔗 ${this.esc(reno)}</div>` : ''}
                <div class="em-case-title">${this.esc(c.title)}</div>
                <div class="em-case-loc">📍 ${this.esc(loc || '—')}</div>
                <div class="em-case-card-cta">مشاهده پرونده ←</div>
            </button>`;
        }).join('')}</div>`;
        el.querySelectorAll('.em-case-card').forEach(row => {
            row.addEventListener('click', () => this._openCase(parseInt(row.dataset.case, 10)));
        });
    }

    async _createCaseFromParcel(p) {
        if (!this.can('melk.cases.create')) return alert('مجوز ندارید');
        const title = prompt('عنوان پرونده:', `پرونده ${p.code || p.id}`);
        if (title === null) return;
        const res = await this.request('POST', 'melk/cases', {
            parcel_id: p.id || p.parcel_id, title: title || `پرونده ${p.code || p.id}`,
            district_id: p.district_id, neighborhood_id: p.neighborhood_id, block_code: p.block_code,
        });
        const id = res?.id ?? res?.data?.id;
        if (id) { await this._openCase(id); await this._loadOverview(); }
    }

    async _createCaseFromContext() {
        const d = this._path.find(x => x.level === 'district');
        const n = this._path.find(x => x.level === 'neighborhood');
        const b = this._path.find(x => x.level === 'block');
        const title = prompt('عنوان پرونده:', b ? `پرونده بلوک ${b.label}` : 'پرونده جدید');
        if (title === null) return;
        const res = await this.request('POST', 'melk/cases', {
            title, district_id: d?.id, neighborhood_id: n?.id, block_code: b?.id || this._blockCtx?.block_code,
        });
        const id = res?.id ?? res?.data?.id;
        if (id) await this._openCase(id);
    }

    async _openCase(id) {
        try {
            const res = await this.request('GET', `melk/cases/${id}`);
            const c = res?.data?.data ?? res?.data;
            const st = STATUS_CFG[c.status] || STATUS_CFG.open;
            const canEditFull = this.can('melk.cases.edit') || this.can('melk.manage');
            const canEditPart = canEditFull || this.can('melk.cases.participate');
            const roleOpts = (this._participantRoles.length ? this._participantRoles : Object.entries(ROLE_LABELS).map(([key, label]) => ({ key, label })))
                .map(r => `<option value="${r.key}">${this.esc(r.label)}</option>`).join('');
            const loc = [c.district_name, c.neighborhood_name, c.block_code, c.parcel_code].filter(Boolean).join(' › ');
            const reno = c.renovation_code_display || c.renovation_code || c.parcel_code || '';
            const head = this.$('detailHead');
            const body = this.$('detailBody');
            if (head) {
                head.innerHTML = `
                    <h2 class="em-case-modal-title">${this.esc(c.title)}</h2>
                    <div class="em-detail-meta">
                        <span class="em-status" style="background:${st.color}">${st.label}</span>
                        <span class="em-case-key">${this.esc(c.case_key)}</span>
                    </div>
                    <p class="em-detail-loc">📍 ${this.esc(loc)}</p>
                    ${reno && this._canRenovationHub() ? `<p class="em-detail-reno">کد نوسازی: <button type="button" class="em-reno-link" data-ref="openRenoHub" dir="ltr">${this.esc(reno)}</button></p>` : (reno ? `<p class="em-detail-reno">کد نوسازی: <span dir="ltr">${this.esc(reno)}</span></p>` : '')}
                    ${c.assigned_name ? `<p class="em-detail-assign">مسئول: <strong>${this.esc(c.assigned_name)}</strong>${c.assigned_login ? ` <span class="em-detail-login">@${this.esc(c.assigned_login)}</span>` : ''}</p>` : ''}`;
            }
            const collabHtml = renderMelkCaseCollaboration(c, {
                esc: (t) => this.esc(t),
                canEditFull,
                roleOpts,
            });
            body.innerHTML = `
            ${c.parcel_id ? `<div class="em-case-section em-case-section--actions"><button type="button" class="em-mini-btn em-mini-btn--map" data-ref="openGisBtn">🗺️ باز کردن در نقشه ERP</button></div>` : ''}
            ${canEditPart ? `<div class="em-case-section">
                <h3 class="em-case-section-title">✏️ ویرایش پرونده</h3>
                <div class="em-detail-edit">
                ${canEditFull ? `<label>عنوان</label><input class="red-inp" data-ref="caseTitle" value="${this.esc(c.title)}">` : ''}
                ${canEditFull ? `<label>وضعیت</label><select data-ref="caseStatusSel">${Object.entries(STATUS_CFG).map(([k,v]) =>
                    `<option value="${k}" ${c.status===k?'selected':''}>${v.label}</option>`).join('')}</select>` : ''}
                <label>خلاصه</label><textarea data-ref="caseSummary" rows="4">${this.esc(c.summary || '')}</textarea>
                ${canEditFull ? `<label>مسئول پرونده</label><input data-ref="assignUserQ" class="red-inp" placeholder="جستجوی کاربر..." value="${this.esc(c.assigned_name || '')}"><input type="hidden" data-ref="assignUserId" value="${c.assigned_to || ''}"><div data-ref="assignUserPick" class="em-user-results"></div>` : ''}
                <button type="button" class="red-btn red-btn--primary" data-ref="saveCaseBtn">💾 ذخیره</button></div></div>` : ''}
            <div class="em-case-section em-case-section--collab">
                <h3 class="em-case-section-title">👥 همکاری و نظرات اعضا</h3>
                ${collabHtml}
            </div>`;
            bindMelkCaseTabs(body.querySelector('.em-case-collab'));
            head?.querySelector('[data-ref="openRenoHub"]')?.addEventListener('click', () => {
                this._showCaseOverlay(false);
                this._openRenovationHub(reno);
            });
            body.querySelectorAll('.em-member-card').forEach(card => {
                card.addEventListener('click', (e) => {
                    if (e.target.closest('[data-rm-part]')) return;
                    filterMelkNotesByMember(body.querySelector('.em-case-collab'), +card.dataset.memberUid);
                });
            });
            this._showCaseOverlay(true);
            body.querySelector('[data-ref="openGisBtn"]')?.addEventListener('click', () => {
                if (c.block_code) sessionStorage.setItem('acc_gis_focus_block', JSON.stringify({ block: c.block_code }));
                window.open(this.erpUrl + 'index.php?tab=gis', '_blank');
            });
            body.querySelector('[data-ref="noteSubmit"]')?.addEventListener('click', () => this._submitNote(id, body));
            body.querySelector('[data-ref="saveCaseBtn"]')?.addEventListener('click', () => this._saveCase(id, body, canEditFull));
            body.querySelectorAll('[data-rm-part]').forEach(btn => {
                btn.addEventListener('click', async () => {
                    await this.request('DELETE', `melk/cases/${id}/participants/${btn.dataset.rmPart}`);
                    await this._openCase(id);
                });
            });
            this._bindUserSearch(body.querySelector('[data-ref="partUserQ"]'), body.querySelector('[data-ref="partUserResults"]'), async (uid) => {
                await this.request('POST', `melk/cases/${id}/participants`, {
                    user_id: uid, role_type: body.querySelector('[data-ref="partRoleSel"]')?.value || 'other',
                });
                await this._openCase(id);
            });
            if (canEditFull) {
                this._bindUserSearch(body.querySelector('[data-ref="assignUserQ"]'), body.querySelector('[data-ref="assignUserPick"]'), (uid, name) => {
                    body.querySelector('[data-ref="assignUserId"]').value = uid;
                    body.querySelector('[data-ref="assignUserQ"]').value = name;
                });
            }
        } catch (e) {
            this._toast(e.message || 'خطا در باز کردن پرونده', true);
        }
    }

    _bindUserSearch(input, resultsEl, onPick) {
        if (!input || !resultsEl) return;
        let t;
        input.addEventListener('input', () => {
            clearTimeout(t);
            t = setTimeout(async () => {
                const q = input.value.trim();
                if (!q) { resultsEl.innerHTML = ''; return; }
                try {
                    const ur = await this.request('GET', `melk/users?q=${encodeURIComponent(q)}`);
                    resultsEl.innerHTML = (ur?.data ?? []).map(u =>
                        `<button type="button" class="em-user-pick" data-uid="${u.id}">${this.esc(u.display_name)} <span class="em-user-pick-login">@${this.esc(u.user_login)}</span></button>`).join('');
                    resultsEl.querySelectorAll('.em-user-pick').forEach(pb => {
                        pb.addEventListener('click', () => onPick(+pb.dataset.uid, pb.textContent));
                    });
                } catch { /* */ }
            }, 300);
        });
    }

    async _saveCase(id, body, canEditFull) {
        const payload = { summary: body.querySelector('[data-ref="caseSummary"]')?.value };
        if (canEditFull) {
            payload.status = body.querySelector('[data-ref="caseStatusSel"]')?.value;
            payload.title = body.querySelector('[data-ref="caseTitle"]')?.value;
            const aid = body.querySelector('[data-ref="assignUserId"]')?.value;
            if (aid) payload.assigned_to = +aid;
        }
        await this.request('PUT', `melk/cases/${id}`, payload);
        this._toast('ذخیره شد');
        await this._openCase(id);
        await this._loadOverview();
    }

    async _submitNote(caseId, body) {
        const root = body || this.$('detailBody');
        const text = root?.querySelector('[data-ref="noteInput"]')?.value?.trim();
        const noteType = root?.querySelector('[data-ref="noteTypeSel"]')?.value || 'note';
        if (!text) return;
        await this.request('POST', `melk/cases/${caseId}/notes`, { body: text, note_type: noteType });
        await this._openCase(caseId);
    }

    async _renderOrg() {
        const form = this.$('orgForm');
        const list = this.$('orgList');
        const dr = await this.request('GET', 'gis/districts');
        const nr = await this.request('GET', 'gis/neighborhoods');
        const districts = dr?.data?.data ?? dr?.data ?? [];
        const neighborhoods = nr?.data?.data ?? nr?.data ?? [];
        form.innerHTML = `<h3>تعیین سرگروه / مدیر محله</h3><div class="em-org-row">
            <select data-ref="orgUnitType"><option value="district">منطقه</option><option value="neighborhood">محله</option></select>
            <select data-ref="orgUnitId">${districts.map(d=>`<option value="${d.id}">${this.esc(d.name)}</option>`).join('')}</select>
            <input data-ref="orgUserQ" class="red-inp" placeholder="کاربر..."><input type="hidden" data-ref="orgUserId" value="">
            <div data-ref="orgUserPick"></div><button class="red-btn red-btn--primary" data-ref="orgSaveBtn">ذخیره</button></div>`;
        const unitType = form.querySelector('[data-ref="orgUnitType"]');
        const unitId = form.querySelector('[data-ref="orgUnitId"]');
        unitType.addEventListener('change', () => {
            const t = unitType.value;
            unitId.innerHTML = (t === 'district' ? districts : neighborhoods).map(u => `<option value="${u.id}">${this.esc(u.name)}</option>`).join('');
        });
        let ot;
        const qInp = form.querySelector('[data-ref="orgUserQ"]');
        const pick = form.querySelector('[data-ref="orgUserPick"]');
        const hid = form.querySelector('[data-ref="orgUserId"]');
        qInp.addEventListener('input', () => {
            clearTimeout(ot);
            ot = setTimeout(async () => {
                const q = qInp.value.trim();
                if (!q) return;
                const ur = await this.request('GET', `melk/users?q=${encodeURIComponent(q)}`);
                pick.innerHTML = (ur?.data ?? []).map(u => `<button type="button" class="em-user-pick" data-uid="${u.id}">${this.esc(u.display_name)}</button>`).join('');
                pick.querySelectorAll('.em-user-pick').forEach(b => b.addEventListener('click', () => { hid.value = b.dataset.uid; qInp.value = b.textContent; pick.innerHTML = ''; }));
            }, 300);
        });
        form.querySelector('[data-ref="orgSaveBtn"]').addEventListener('click', async () => {
            if (!+hid.value) return alert('کاربر را انتخاب کنید');
            await this.request('POST', 'melk/org-assignments', {
                unit_type: unitType.value, unit_id: +unitId.value, user_id: +hid.value,
                role_slug: unitType.value === 'district' ? 'district_lead' : 'neighborhood_manager',
            });
            await this._loadOrg();
            await this._loadOverview();
        });
        list.innerHTML = `<h3>انتصاب‌ها</h3>` + (this._org.length ? `<table class="em-org-table"><tbody>${this._org.map(o=>`<tr><td>${o.unit_type==='district'?'منطقه':'محله'}</td><td>${this.esc(o.district_name||o.neighborhood_name||'')}</td><td>${this.esc(o.user_name)}</td><td><button class="em-link-btn" data-del-org="${o.id}">حذف</button></td></tr>`).join('')}</tbody></table>` : '<p class="em-empty">—</p>');
        list.querySelectorAll('[data-del-org]').forEach(btn => btn.addEventListener('click', async () => {
            if (!confirm('حذف؟')) return;
            await this.request('DELETE', `melk/org-assignments/${btn.dataset.delOrg}`);
            await this._loadOrg();
            await this._loadOverview();
        }));
    }

    _showCaseOverlay(show) {
        const ov = this.$('detailOverlay');
        if (!ov) return;
        ov.style.display = show ? 'flex' : 'none';
        ov.setAttribute('aria-hidden', show ? 'false' : 'true');
        document.body.classList.toggle('em-case-open', !!show);
    }

    _bindEvents() {
        this.$('mainTabs')?.querySelectorAll('.em-main-tab').forEach(b => b.addEventListener('click', () => this._switchMainTab(b.dataset.tab)));
        this.$('searchInput')?.addEventListener('input', e => { this._search = e.target.value; this._renderGrid(); });
        this.$('refreshBtn')?.addEventListener('click', () => this._loadOverview());
        this.$('reloadCasesBtn')?.addEventListener('click', () => this._loadCases());
        this.$('caseStatusFilter')?.addEventListener('change', () => this._loadCases());
        this.$('caseDistrictFilter')?.addEventListener('change', () => this._loadCases());
        this.$('caseSearchInput')?.addEventListener('input', e => {
            this._caseSearch = e.target.value;
            this._renderCasesList(this.$('casesFull'));
        });
        this.$('newCaseBtn')?.addEventListener('click', () => this._createCaseFromContext());
        this.$('backBtn')?.addEventListener('click', () => { if (this._path.length) this._crumbNav(this._path.length); });
        this.$('detailClose')?.addEventListener('click', () => this._showCaseOverlay(false));
        this.$('detailOverlay')?.addEventListener('click', e => {
            if (e.target === this.$('detailOverlay')) this._showCaseOverlay(false);
        });
        this.$('mapBtn')?.addEventListener('click', () => {
            if (this._blockCtx?.block_code) {
                sessionStorage.setItem('acc_gis_focus_block', JSON.stringify({ block: this._blockCtx.block_code }));
            }
            window.open(this.erpUrl + 'index.php?tab=gis', '_blank');
        });
    }
}
