/**
 * EducationAppView — EduBrain Applied (Campus Lumen)
 */
import EducationMapView from './education/EducationMapView.js';
import * as P from './education/EduPanels.js';
import * as R from './education/EduRequestFlow.js';
import * as LC from './education/EduLifeCompanion.js';
import { renderEduAbcPanel, bindEduAbcPanel } from './education/edu-accounting-panel.js';

const TOKEN_KEY = 'acc_token';
const ROLE_KEY = 'edu_role';
const DEMO_PASS = 'Edu@1404';

const EDU_ROLES = [
    { id: 'learner', icon: '👨‍🎓', title: 'دانش‌آموز', desc: 'درخواست، آزمون سطح، همراه زندگی و برنامه', tag: 'Learner', cls: 'ea-portal--learner', tab: 'companion' },
    { id: 'parent', icon: '👪', title: 'والد', desc: 'نظارت خانواده، بودجه و تأیید مسیر', tag: 'Family', cls: '', tab: 'family' },
    { id: 'mentor', icon: '🧑‍🏫', title: 'مربی', desc: 'صف جلسات، رزومه و دیسپاچ هوشمند', tag: 'Mentor', cls: 'ea-portal--mentor', tab: 'dispatch' },
    { id: 'teacher', icon: '📐', title: 'معلم', desc: 'تدریس، ارزیابی و پروفایل حرفه‌ای', tag: 'Faculty', cls: '', tab: 'profile' },
    { id: 'org_admin', icon: '🏫', title: 'مؤسسه', desc: 'امکانات، برنامه کلاس و GIS', tag: 'Campus', cls: '', tab: 'schedule' },
    { id: 'accountant', icon: '📊', title: 'حسابدار', desc: 'ERP، بهای تمام‌شده و گراف ABC', tag: 'Finance', cls: 'ea-portal--admin', tab: 'cost' },
];

const EDU_DEMO = [
    { role: 'learner', icon: '👨‍🎓', title: 'دانش‌آموز کنکور', u: 'edu_student_konkur', tab: 'companion' },
    { role: 'learner', icon: '🧠', title: 'دانش‌آموز تیزهوش', u: 'edu_student_tiz', tab: 'companion' },
    { role: 'learner', icon: '🎵', title: 'دانش‌آموز مهارت', u: 'edu_student_skill', tab: 'companion' },
    { role: 'parent', icon: '👪', title: 'والد — سارا', u: 'edu_parent_konkur', tab: 'family' },
    { role: 'mentor', icon: '⚛️', title: 'مربی فیزیک', u: 'edu_mentor_physics', tab: 'dispatch' },
    { role: 'mentor', icon: '🎹', title: 'مربی موسیقی', u: 'edu_mentor_music', tab: 'dispatch' },
    { role: 'teacher', icon: '📐', title: 'معلم ریاضی', u: 'edu_teacher_math', tab: 'profile' },
    { role: 'org_admin', icon: '🏫', title: 'مدیر مؤسسه', u: 'edu_org_alpha', tab: 'schedule' },
    { role: 'accountant', icon: '📊', title: 'حسابدار', u: 'edu_accountant', tab: 'cost' },
];

export default class EducationAppView {
    constructor() {
        this.root = null;
        this.screen = 'landing';
        this.tab = (sessionStorage.getItem(ROLE_KEY) || 'learner') === 'learner' ? 'companion' : 'dashboard';
        this.token = sessionStorage.getItem(TOKEN_KEY) || '';
        this.role = sessionStorage.getItem(ROLE_KEY) || 'learner';
        this.user = null;
        this.meta = null;
        this.dashboard = null;
        this.err = '';
        this.mapView = null;
        this.aiHistory = [];
        this.schedOrgId = null;
        this.flowStep = 'form';
        this.flowRequestId = null;
        this.flowTest = null;
        this.flowPhaseIdx = 0;
        this.flowAnswers = {};
        this.flowResults = null;
        this.flowRequest = null;
        this.flowRefCode = '';
        this.flowSessionType = 'academic';
        this.pendingLoginTab = 'companion';
        this.compSection = 'overview';
        this.orgEditId = null;
        this.selectedRole = sessionStorage.getItem(ROLE_KEY) || '';
    }

    _siteUrl() {
        return window.ACC_EDU_CFG?.baseUrl || '/acc-engine/';
    }

    _roleById(id) {
        return EDU_ROLES.find(r => r.id === id) || null;
    }

    _asArray(r) {
        if (Array.isArray(r)) return r;
        if (r?.sessions) return r.sessions;
        if (r?.organizations) return r.organizations;
        return [];
    }

    api(path, opts = {}) {
        const base = window.ACC_EDU_CFG?.api || '/acc-engine/api.php/acc/v1';
        const headers = { ...(opts.headers || {}) };
        if (this.token) headers.Authorization = `Bearer ${this.token}`;
        if (opts.body && !headers['Content-Type']) headers['Content-Type'] = 'application/json';
        return fetch(`${base}${path}`, { ...opts, headers }).then(async r => {
            const j = await r.json().catch(() => ({}));
            if (!r.ok) throw new Error(j.message || j.code || 'خطای سرور');
            return j;
        });
    }

    esc(s) { return P.esc(s); }
    fmt(n) { return P.fmt(n); }

    async render(root) {
        this.root = root;
        if (this.token) {
            try {
                await this._loadApp();
                this.screen = 'app';
            } catch {
                this._logout(false);
            }
        }
        this._paint();
    }

    async _loadApp() {
        this.meta = await this.api('/education/meta');
        const me = await this.api('/education/me');
        if (me.role && me.role !== 'guest') this.role = me.role;
        this.user = me;
        this.dashboard = await this.api(`/education/dashboard?role=${encodeURIComponent(this.role)}`);
    }

    _logout(repaint = true) {
        this.token = '';
        sessionStorage.removeItem(TOKEN_KEY);
        this.screen = 'landing';
        this.dashboard = null;
        if (repaint) this._paint();
    }

    _paint() {
        if (!this.root) return;
        if (this.mapView) { this.mapView.destroy(); this.mapView = null; }
        if (this.screen === 'landing') {
            this.root.innerHTML = this._landingHtml();
            this._bindLanding();
        } else if (this.screen === 'login') {
            this.root.innerHTML = this._loginHtml();
            this._bindLogin();
        } else {
            this.root.innerHTML = this._appHtml();
            this._bindApp();
            this._hydrateTab();
        }
    }

    _landingHtml() {
        const site = this._siteUrl();
        const portals = EDU_ROLES.map(r => `
            <button type="button" class="ea-portal ${r.cls}" data-role="${r.id}">
                <span class="ea-portal__tag">${r.tag}</span>
                <strong>${this.esc(r.title)}</strong>
                <small>${this.esc(r.desc)}</small>
                <span class="ea-portal__go">ورود نقش ←</span>
            </button>`).join('');

        const demoRows = EDU_DEMO.map(d => `
            <button type="button" class="edu-demo-row" data-demo-u="${d.u}" data-demo-role="${d.role}" data-demo-tab="${d.tab}">
                <span class="edu-demo-row__icon">${d.icon}</span>
                <span class="edu-demo-row__name">${this.esc(d.title)}</span>
                <code class="edu-demo-row__user">${d.u}</code>
                <span class="edu-demo-row__badge">ورود خودکار ↗</span>
            </button>`).join('');

        return `
        <div class="edu-app edu-landing ea-applied" dir="rtl">
            <div class="ea-util">
                <a href="${site}">ACC Engine</a>
                <a href="${site}shop.php">فروشگاه</a>
                <a href="${site}service.php">خدمات</a>
                <a href="${site}melk.php">اقتصاد ملک</a>
                <a href="#ea-accounting" class="ea-util__accent">گراف هزینه ABC</a>
            </div>

            <header class="ea-header" id="ea-header">
                <a href="${site}education.php" class="ea-brand">
                    <span class="ea-brand__mark">E</span>
                    <span class="ea-brand__text">
                        <span class="ea-brand__name">EduBrain <em>Applied</em></span>
                        <span class="ea-brand__sub">Campus Lumen Network</span>
                    </span>
                </a>
                <nav class="ea-nav">
                    <a href="#ea-pillars">اکوسیستم</a>
                    <a href="#ea-portals">ورود نقش‌ها</a>
                    <a href="#ea-story">مسیر یادگیری</a>
                    <a href="#ea-accounting">حسابداری</a>
                    <button type="button" id="edu-demo-btn">ورود آزمایشی</button>
                </nav>
                <button type="button" class="ea-header__cta" data-role="learner">شروع یادگیری</button>
            </header>

            <div class="edu-demo-panel" id="edu-demo-panel" style="display:none">
                <div class="edu-demo-panel__inner">
                    <div class="edu-demo-panel__head">
                        <span>🧪 ورود آزمایشی — رمز: <code>${DEMO_PASS}</code></span>
                        <button type="button" class="edu-demo-close" id="edu-demo-close">✕</button>
                    </div>
                    <div class="edu-demo-list">${demoRows}</div>
                </div>
            </div>

            <section class="ea-hero">
                <div class="ea-hero__media" aria-hidden="true"></div>
                <div class="ea-hero__grain" aria-hidden="true"></div>
                <div class="ea-hero__content">
                    <p class="ea-hero__brand">EduBrain <span>Applied</span></p>
                    <h1>آموزش هوشمند<br><em>از تعیین سطح تا بهای تمام‌شده</em></h1>
                    <p class="ea-hero__lead">پلتفرم بین‌المللی کنکور، تیزهوشان و مهارت — همراه زندگی، شبکه مربیان و شفافیت سهم هر نقش روی گراف هزینه.</p>
                    <div class="ea-hero__actions">
                        <a href="#ea-portals" class="ea-btn ea-btn--garnet">ورود به پردیس</a>
                        <a href="#ea-story" class="ea-btn ea-btn--ghost">کشف مسیر</a>
                    </div>
                </div>
            </section>

            <section class="ea-section" id="ea-pillars">
                <div class="ea-section__head ea-reveal">
                    <span class="ea-kicker">Ecosystem</span>
                    <h2>چهار ستون EduBrain Applied</h2>
                    <p>طراحی‌شده برای مسیر تحصیلی واقعی — نه فقط کلاس آنلاین، بلکه حاکمیت یادگیری و هزینه.</p>
                </div>
                <div class="ea-pillars ea-reveal">
                    <article class="ea-pillar"><span class="ea-pillar__num">01</span><strong>همراه زندگی</strong><span>پروفایل ۳۶۰°، کارنامه، بودجه خانواده و مسیر شغلی</span></article>
                    <article class="ea-pillar"><span class="ea-pillar__num">02</span><strong>بازار یادگیری</strong><span>مؤسسه، مربی، رزرو جلسه و دیسپاچ هوشمند</span></article>
                    <article class="ea-pillar"><span class="ea-pillar__num">03</span><strong>ارزیابی هوشمند</strong><span>تعیین سطح، برنامه شخصی و EduBrain AI</span></article>
                    <article class="ea-pillar"><span class="ea-pillar__num">04</span><strong>شفافیت هزینه</strong><span>بهای جلسه، سهم نقش‌ها و گراف ABC فعالیت‌ها</span></article>
                </div>
            </section>

            <section class="ea-section ea-section--ink ea-reveal">
                <div class="ea-stats">
                    <div class="ea-stat"><strong>۶</strong><span>نقش تخصصی</span></div>
                    <div class="ea-stat"><strong>۱</strong><span>پورتال یکپارچه</span></div>
                    <div class="ea-stat"><strong>۳۶۰°</strong><span>پروفایل یادگیرنده</span></div>
                    <div class="ea-stat"><strong>ABC</strong><span>گراف سهم فعالیت</span></div>
                </div>
            </section>

            <section class="ea-section ea-section--mist" id="ea-portals">
                <div class="ea-section__head ea-reveal">
                    <span class="ea-kicker">Access</span>
                    <h2>ورود به پورتال نقش شما</h2>
                    <p>هر نقش فضای کاری اختصاصی دارد — از دانش‌آموز و والد تا مؤسسه و حسابدار.</p>
                </div>
                <div class="ea-portals ea-reveal">${portals}</div>
            </section>

            <section class="ea-section" id="ea-story">
                <div class="ea-story ea-reveal">
                    <div class="ea-story__media" role="img" aria-label="کتابخانه و فضای یادگیری"></div>
                    <div class="ea-story__body">
                        <span class="ea-kicker">Learning Path</span>
                        <h3>از درخواست تا کلاس — روی یک پرونده مشترک</h3>
                        <p>تعیین سطح، جایابی مربی، برنامه مؤسسه، GIS و حسابداری جلسه در یک زبان بصری بین‌المللی. مسیر کنکور، تیزهوشان و مهارت بدون پراکندگی ابزارها.</p>
                        <div style="display:flex;flex-wrap:wrap;gap:10px">
                            <button type="button" class="ea-btn ea-btn--dark" data-role="learner">ثبت درخواست</button>
                            <button type="button" class="ea-btn ea-btn--outline" data-role="mentor">پورتال مربی</button>
                            <button type="button" class="ea-btn ea-btn--outline" data-role="org_admin">مدیریت مؤسسه</button>
                        </div>
                    </div>
                </div>
            </section>

            <section class="ea-section ea-section--mist" id="ea-accounting">
                <div class="ea-section__head ea-reveal">
                    <span class="ea-kicker">Cost Graph</span>
                    <h2>حسابداری صنعتی آموزش</h2>
                    <p>بهای تمام‌شده فعالیت‌های جلسه — سهم معلم، مربی، مؤسسه و پلتفرم روی گراف جلسه ↔ فعالیت ↔ نقش.</p>
                </div>
                <div class="ea-reveal" style="max-width:720px">
                    <button type="button" class="ea-btn ea-btn--dark" data-role="accountant" data-tab="cost">ورود به گراف ABC ←</button>
                    <p style="margin-top:14px;color:var(--ea-muted);font-size:.92rem">پس از ورود، تب «گراف ABC» را باز کنید یا از ورود آزمایشی حسابدار استفاده کنید.</p>
                    <p style="margin-top:8px"><a href="${site}education-accounting.php" class="ea-btn ea-btn--outline">دفتر کل ERP ↗</a></p>
                </div>
            </section>

            <section class="ea-help">
                <div class="ea-help__inner">
                    <div>
                        <h2>چطور کمک کنیم؟</h2>
                        <p>یادگیری، خانواده، تدریس، مؤسسه یا حسابداری — مسیر درست را انتخاب کنید.</p>
                    </div>
                    <div class="ea-help__actions">
                        <button type="button" class="ea-btn ea-btn--solid" data-role="learner">دانش‌آموز</button>
                        <button type="button" class="ea-btn" data-role="parent">والد</button>
                        <button type="button" class="ea-btn" data-role="mentor">مربی</button>
                        <button type="button" class="ea-btn" data-role="accountant">حسابداری</button>
                    </div>
                </div>
            </section>

            <footer class="ea-footer">
                <span>© EduBrain Applied — Campus Lumen</span>
                <span>
                    <a href="${site}">ACC Engine</a> ·
                    <a href="${site}shop.php">فروشگاه</a> ·
                    <a href="${site}service.php">خدمات</a> ·
                    <a href="${site}melk.php">ملک</a>
                </span>
            </footer>
        </div>`;
    }

    _loginHtml() {
        const site = this._siteUrl();
        const role = this._roleById(this.selectedRole);
        const roleBadge = role
            ? `<div class="ea-login__role"><span>${role.icon}</span> ورود به عنوان <strong>${this.esc(role.title)}</strong></div>`
            : '';

        return `
        <div class="edu-app ea-applied ea-login-screen" dir="rtl">
            <div class="ea-util">
                <a href="${site}">ACC Engine</a>
                <a href="#" id="edu-back-landing">بازگشت به لندینگ</a>
            </div>
            <div class="ea-login">
                <div class="ea-login__card">
                    <p class="ea-login__brand">EduBrain <em>Applied</em></p>
                    ${roleBadge}
                    <h3>ورود به پردیس آموزشی</h3>
                    <p class="ea-login__hint">با حساب ERP وارد شوید — همان توکن برای همه پورتال‌ها.</p>
                    <div class="edu-field"><label>نام کاربری</label><input id="edu-login-user" type="text" dir="ltr" autocomplete="username"></div>
                    <div class="edu-field"><label>رمز عبور</label><input id="edu-login-pass" type="password" dir="ltr" autocomplete="current-password"></div>
                    <button class="ea-btn ea-btn--dark" id="edu-login-btn" style="width:100%;justify-content:center">ورود</button>
                    ${this.err ? `<div class="edu-err" style="margin-top:12px">${this.esc(this.err)}</div>` : ''}
                </div>
            </div>
        </div>`;
    }

    _tabsForRole() {
        const all = [
            { key: 'companion', label: 'همراه من', roles: ['learner'] },
            { key: 'request', label: 'درخواست', roles: ['learner'] },
            { key: 'family', label: 'پنل خانواده', roles: ['parent'] },
            { key: 'dashboard', label: 'داشبورد' },
            { key: 'brain', label: 'EduBrain', roles: ['learner'] },
            { key: 'timeline', label: 'پروفایل ۳۶۰°', roles: ['learner'] },
            { key: 'marketplace', label: 'Marketplace', roles: ['learner'] },
            { key: 'book', label: 'رزرو جلسه', roles: ['learner'] },
            { key: 'sessions', label: 'جلسات', roles: ['learner'] },
            { key: 'dispatch', label: 'صف جلسات', roles: ['mentor', 'teacher'] },
            { key: 'profile', label: 'رزومه', roles: ['mentor', 'teacher'] },
            { key: 'orgs', label: 'امکانات مؤسسه', roles: ['org_admin'] },
            { key: 'schedule', label: 'برنامه کلاس', roles: ['org_admin'] },
            { key: 'accounting', label: 'حسابداری', roles: ['accountant'] },
            { key: 'cost', label: 'گراف ABC', roles: ['accountant'] },
            { key: 'map', label: '🗺 GIS' },
            { key: 'ai', label: '🤖 AI' },
        ];
        return all.filter(t => !t.roles || t.roles.includes(this.role));
    }

    _appHtml() {
        const site = this._siteUrl();
        const roleMeta = this._roleById(this.role);
        const roleLabel = roleMeta ? `${roleMeta.icon} ${roleMeta.title}` : ({ learner: 'دانش‌آموز', parent: 'والد', mentor: 'مربی', teacher: 'معلم', org_admin: 'مؤسسه', accountant: 'حسابدار' }[this.role] || this.role);
        const tabs = this._tabsForRole();
        return `<div class="edu-app ea-applied" dir="rtl">
            <header class="edu-header ea-ws-header">
                <a class="ea-brand ea-brand--ws" href="${site}education.php">
                    <span class="ea-brand__mark">E</span>
                    <span class="ea-brand__text">
                        <span class="ea-brand__name">EduBrain <em>Applied</em></span>
                        <span class="ea-brand__sub">Workspace</span>
                    </span>
                </a>
                <nav class="edu-header__nav edu-header__nav--scroll">
                    ${tabs.map(t => `<button type="button" data-tab="${t.key}" class="${this.tab === t.key ? 'active' : ''}">${t.label}</button>`).join('')}
                </nav>
                <span class="edu-header__role">${roleLabel}</span>
                <button class="edu-header__btn" id="edu-logout">خروج</button>
            </header>
            <main class="edu-main" id="edu-tab-root"><div class="edu-loading">در حال بارگذاری…</div></main>
        </div>`;
    }

    async _hydrateTab() {
        const mount = this.root.querySelector('#edu-tab-root');
        if (!mount) return;
        try {
            let html = '';
            const d = this.dashboard || {};
            switch (this.tab) {
                case 'family': {
                    const pd = await this.api('/education/parent/dashboard');
                    this.parentDash = pd;
                    html = LC.renderParentDashboard(pd);
                    break;
                }
                case 'companion': {
                    const st = await this.api('/education/companion/state');
                    this.companionState = st;
                    html = LC.renderCompanion(st, this.compSection);
                    break;
                }
                case 'request': {
                    const requests = d.requests || [];
                    html = R.renderRequestWizard(this.meta, requests, this.flowStep, {
                        test: this.flowTest,
                        phaseIdx: this.flowPhaseIdx,
                        results: this.flowResults,
                        request: this.flowRequest,
                        ref_code: this.flowRefCode,
                        session_type: this.flowSessionType,
                    });
                    break;
                }
                case 'brain': {
                    const st = await this.api('/education/brain/state');
                    html = P.renderBrainState(st, this.meta);
                    break;
                }
                case 'timeline': {
                    const tl = await this.api('/education/learner/timeline');
                    html = P.renderTimeline(tl);
                    break;
                }
                case 'ai':
                    html = P.renderAiChat();
                    break;
                case 'marketplace': {
                    const orgs = this._asArray(await this.api('/education/orgs'));
                    const eds = this._asArray(await this.api('/education/educators?verified=1'));
                    html = P.renderMarketplace(orgs, eds);
                    break;
                }
                case 'book': {
                    const orgs = this._asArray(await this.api('/education/orgs'));
                    html = P.renderBookForm(this.meta, orgs);
                    break;
                }
                case 'sessions':
                    html = P.renderSessionsList(d.sessions || []);
                    break;
                case 'dispatch':
                    html = this._dispatchHtml();
                    break;
                case 'profile': {
                    const ed = await this.api('/education/educator/profile');
                    html = LC.renderEducatorFull(ed, this.meta);
                    break;
                }
                case 'orgs': {
                    const list = this._asArray(d.organizations?.length ? d.organizations : await this.api('/education/orgs'));
                    const oid = this.orgEditId || list[0]?.id;
                    if (oid) {
                        const r = await this.api(`/education/orgs/${oid}`);
                        html = LC.renderOrgFacilities(r.org, this.meta);
                        this.orgEditId = oid;
                    } else {
                        html = P.renderMarketplace(list, []);
                    }
                    break;
                }
                case 'schedule': {
                    const list = this._asArray(d.organizations?.length ? d.organizations : await this.api('/education/orgs'));
                    if (list.length) this.schedOrgId = this.schedOrgId || list[0].id;
                    const sch = this.schedOrgId
                        ? this._asArray(await this.api(`/education/orgs/${this.schedOrgId}/schedule`))
                        : [];
                    html = P.renderScheduleAdmin(list, sch, this.schedOrgId);
                    break;
                }
                case 'accounting':
                    html = P.renderAccountingEnhanced(d.accounting?.sessions || []);
                    break;
                case 'cost':
                    html = `<div class="edu-panel">
                        <div id="edu-cost-report" style="margin-bottom:20px">
                            <h2 style="margin:0 0 10px;font-size:1.1rem">گزارش بهای جلسات</h2>
                            <div id="edu-cost-out" class="edu-muted">در حال بارگذاری…</div>
                        </div>
                        ${renderEduAbcPanel(this.esc.bind(this))}
                    </div>`;
                    break;
                case 'map':
                    html = `<div class="edu-panel"><h2>GIS — OpenStreetMap</h2><div id="edu-map-mount"></div></div>`;
                    break;
                default:
                    html = this._dashboardHtml();
            }
            mount.innerHTML = html;
            this._bindTabActions();
            if (this.tab === 'map') await this._renderMap();
            if (this.tab === 'cost') {
                await this._loadCostAuto();
                const abcRoot = mount.querySelector('.ea-abc');
                if (abcRoot) {
                    await bindEduAbcPanel(abcRoot, {
                        api: (path, opts) => this.api(path, opts),
                        esc: (s) => this.esc(s),
                        toast: (msg) => { if (msg) alert(msg); },
                    });
                }
            }
        } catch (e) {
            mount.innerHTML = `<div class="edu-err">${this.esc(e.message)}</div>`;
        }
    }

    _dashboardHtml() {
        const d = this.dashboard || {};
        if (this.role === 'learner') {
            const l = d.learner || {};
            const reqs = d.requests || [];
            return `<div class="edu-panel"><h2>داشبورد دانش‌آموز</h2>
                <div class="edu-stat-row">
                    <div class="edu-stat"><strong>${this.esc(l.grade_level||'—')}</strong><span>پایه</span></div>
                    <div class="edu-stat"><strong>${this.esc(l.track||'—')}</strong><span>مسیر</span></div>
                    <div class="edu-stat"><strong>${reqs.length}</strong><span>درخواست</span></div>
                </div>
                <div class="edu-form-actions" style="margin-top:16px">
                    <button type="button" class="edu-btn edu-btn--accent edu-btn--sm" id="edu-dash-new-req">درخواست جدید</button>
                </div>
            </div>`;
        }
        if (this.role === 'accountant') {
            return `<div class="edu-panel"><h2>داشبورد حسابدار — EduBrain Applied</h2>
                <div class="edu-stat-row">
                    <div class="edu-stat"><strong>${d.accounting?.count||0}</strong><span>سند در انتظار</span></div>
                    <div class="edu-stat"><strong>ABC</strong><span>گراف فعالیت</span></div>
                </div>
                <div class="edu-form-actions" style="margin-top:16px">
                    <button type="button" class="edu-btn edu-btn--sm" data-tab="cost">گراف ABC ←</button>
                    <a href="/acc-engine/education-accounting.php" class="edu-link">دفتر کل ERP ↗</a>
                </div></div>`;
        }
        return `<div class="edu-panel"><h2>داشبورد</h2><p class="edu-muted">نقش: ${this.esc(this.role)}</p></div>`;
    }

    _dispatchHtml() {
        const pending = this.dashboard?.pending || [];
        const mine = this.dashboard?.queue || [];
        return `<div class="edu-panel"><h2>صف Snapp-like</h2>
            <table class="edu-table"><thead><tr><th>#</th><th>حوزه</th><th>محل</th><th>مبلغ</th><th></th></tr></thead>
            <tbody>${pending.map(s=>`<tr><td>${s.id}</td><td>${this.esc(s.domain)}</td><td>${this.esc(s.venue_type)}</td>
                <td>${this.fmt(s.amount_total)}</td><td><button class="edu-btn edu-btn--sm" data-assign="${s.id}">پذیرش</button></td></tr>`).join('')||'<tr><td colspan="5">خالی</td></tr>'}
            </tbody></table>
            <h3 class="edu-subtitle">جلسات من</h3>
            <table class="edu-table"><tbody>${mine.map(s=>`<tr><td>#${s.id}</td><td>${this.esc(s.status)}</td>
                <td><button class="edu-btn edu-btn--sm" data-complete="${s.id}">تکمیل</button></td></tr>`).join('')||'<tr><td>—</td></tr>'}
            </tbody></table></div>`;
    }

    async _renderMap() {
        const mount = this.root.querySelector('#edu-map-mount');
        if (!mount) return;
        this.gisData = await this.api('/education/gis/map');
        this.mapView = new EducationMapView({ container: mount, data: this.gisData });
        await this.mapView.render(this.gisData);
    }

    _bindLanding() {
        const header = this.root.querySelector('#ea-header');
        const onScroll = () => header?.classList.toggle('ea-header--scrolled', window.scrollY > 12);
        window.addEventListener('scroll', onScroll, { passive: true });
        onScroll();

        this.root.querySelectorAll('.ea-reveal').forEach(el => {
            const io = new IntersectionObserver(entries => {
                entries.forEach(e => { if (e.isIntersecting) e.target.classList.add('is-in'); });
            }, { threshold: 0.12 });
            io.observe(el);
        });

        this.root.querySelector('#edu-demo-btn')?.addEventListener('click', () => {
            const p = this.root.querySelector('#edu-demo-panel');
            if (!p) return;
            p.style.display = p.style.display === 'none' ? 'block' : 'none';
        });
        this.root.querySelector('#edu-demo-close')?.addEventListener('click', () => {
            const p = this.root.querySelector('#edu-demo-panel');
            if (p) p.style.display = 'none';
        });
        this.root.querySelectorAll('[data-demo-u]').forEach(row => {
            row.addEventListener('click', () => this._demoLogin(row.dataset.demoRole, row.dataset.demoU, row.dataset.demoTab, row));
        });

        const openLogin = (role, tab) => {
            this.selectedRole = role || 'learner';
            this.role = this.selectedRole;
            const meta = this._roleById(this.selectedRole);
            this.pendingLoginTab = tab || meta?.tab || ({ learner: 'companion', parent: 'family', accountant: 'cost' }[this.role] || 'dashboard');
            sessionStorage.setItem(ROLE_KEY, this.role);
            this.err = '';
            this.screen = 'login';
            this._paint();
        };

        this.root.querySelectorAll('[data-role]').forEach(btn => {
            btn.addEventListener('click', () => openLogin(btn.dataset.role, btn.dataset.tab));
        });
    }

    _bindLogin() {
        this.root.querySelector('#edu-back-landing')?.addEventListener('click', (e) => {
            e.preventDefault();
            this.screen = 'landing';
            this.err = '';
            this._paint();
        });
        this.root.querySelector('#edu-login-btn')?.addEventListener('click', () => this._login());
        this.root.querySelector('#edu-login-pass')?.addEventListener('keydown', (e) => {
            if (e.key === 'Enter') this._login();
        });
    }

    _bindApp() {
        this.root.querySelector('#edu-logout')?.addEventListener('click', () => this._logout());
        this.root.querySelectorAll('[data-tab]').forEach(b => {
            b.addEventListener('click', () => { this.tab = b.dataset.tab; this._paint(); });
        });
        this.root.querySelector('#edu-tab-root')?.addEventListener('click', (e) => {
            const t = e.target.closest('[data-tab]');
            if (t && this.root.contains(t) && t.closest('#edu-tab-root')) {
                this.tab = t.dataset.tab;
                this._paint();
            }
        });
    }

    _bindTabActions() {
        this.root.querySelector('#edu-run-placement')?.addEventListener('click', () => this._runPlacement());
        this.root.querySelector('#edu-calc-quote')?.addEventListener('click', () => this._calcQuote());
        this.root.querySelector('#edu-submit-session')?.addEventListener('click', () => this._submitSession());
        this.root.querySelector('#edu-save-educator')?.addEventListener('click', () => this._saveEducator());
        this.root.querySelector('#edu-load-cost')?.addEventListener('click', () => this._loadCost());
        this.root.querySelector('#edu-add-log')?.addEventListener('click', () => this._addLog());
        this.root.querySelector('#edu-add-slot')?.addEventListener('click', () => this._addSlot());
        this.root.querySelector('#edu-sched-org')?.addEventListener('change', e => {
            this.schedOrgId = +e.target.value;
            this._hydrateTab();
        });
        this.root.querySelector('#edu-ai-send')?.addEventListener('click', () => this._sendAi());
        this.root.querySelector('#edu-ai-input')?.addEventListener('keydown', e => {
            if (e.key === 'Enter') this._sendAi();
        });
        this.root.querySelectorAll('.edu-ai-chip').forEach(c => {
            c.addEventListener('click', () => {
                const inp = this.root.querySelector('#edu-ai-input');
                if (inp) { inp.value = c.dataset.msg || ''; this._sendAi(); }
            });
        });
        this.root.querySelectorAll('[data-assign]').forEach(b => b.addEventListener('click', () => this._assign(+b.dataset.assign)));
        this.root.querySelectorAll('[data-complete]').forEach(b => b.addEventListener('click', () => this._complete(+b.dataset.complete)));
        this.root.querySelectorAll('[data-post]').forEach(b => b.addEventListener('click', () => this._postSession(+b.dataset.post)));
        this.root.querySelectorAll('.edu-session-view').forEach(b => b.addEventListener('click', () => this._viewSession(+b.dataset.sid)));
        this.root.querySelectorAll('.edu-splits-btn').forEach(b => b.addEventListener('click', () => this._viewSplits(+b.dataset.sid)));
        this.root.querySelectorAll('.edu-org-detail').forEach(b => b.addEventListener('click', () => this._viewOrg(+b.dataset.org)));
        this._bindRequestFlow();
        this._bindCompanion();
    }

    _bindCompanion() {
        this.root.querySelectorAll('[data-comp-section]').forEach(b => {
            b.addEventListener('click', () => {
                this.compSection = b.dataset.compSection;
                this._hydrateCompanionSection();
            });
        });
        this.root.querySelector('#edu-comp-identity-form')?.addEventListener('submit', e => { e.preventDefault(); this._saveIdentity(); });
        this.root.querySelector('#edu-comp-career-form')?.addEventListener('submit', e => { e.preventDefault(); this._saveCareer(); });
        this.root.querySelector('#edu-comp-budget-form')?.addEventListener('submit', e => { e.preventDefault(); this._saveBudget(); });
        this.root.querySelector('#edu-save-history')?.addEventListener('click', () => this._saveHistory());
        this.root.querySelector('#edu-add-history-row')?.addEventListener('click', () => this._addHistoryRow());
        this.root.querySelectorAll('.edu-h-remove').forEach(b => b.addEventListener('click', e => {
            e.target.closest('.edu-history-row')?.remove();
        }));
        this.root.querySelector('#edu-save-educator-full')?.addEventListener('click', () => this._saveEducatorFull());
        this.root.querySelector('#edu-add-cv')?.addEventListener('click', () => this._addCvRow());
        this.root.querySelector('#edu-add-work')?.addEventListener('click', () => this._addWorkRow());
        this.root.querySelector('#edu-save-org-fac')?.addEventListener('click', () => this._saveOrgFac());
        this.root.querySelector('#edu-report-import-form')?.addEventListener('submit', async e => {
            e.preventDefault();
            try { await this._importReport(); } catch (err) { alert(err.message || 'خطا'); }
        });
        this.root.querySelector('#edu-parent-approve-form')?.addEventListener('submit', e => { e.preventDefault(); this._parentApprove(); });
        this.root.querySelector('#edu-match-domain')?.addEventListener('change', e => this._refreshMatching(e.target.value));
        this.root.querySelector('#edu-learner-request-approve')?.addEventListener('click', () => alert('لینک تأیید برای والد ارسال شد (دمو)'));
    }

    _hydrateCompanionSection() {
        if (!this.companionState) return;
        const mount = this.root.querySelector('#edu-companion-body');
        if (!mount) return;
        mount.innerHTML = LC.renderCompanionSection(this.companionState, this.compSection);
        this.root.querySelectorAll('.edu-companion-nav__btn').forEach(b => {
            b.classList.toggle('active', b.dataset.compSection === this.compSection);
        });
        this._bindCompanion();
    }

    async _saveCompanion(payload) {
        const r = await this.api('/education/companion/profile', { method: 'PUT', body: JSON.stringify(payload) });
        this.companionState = { ...this.companionState, learner: r.learner, life_path: r.life_path, profile: r.learner?.profile };
        alert('ذخیره شد');
        if (this.tab === 'companion') {
            const st = await this.api('/education/companion/state');
            this.companionState = st;
            this._hydrateCompanionSection();
        }
    }

    async _importReport() {
        const f = this.root.querySelector('#edu-report-import-form');
        if (!f) return;
        const fd = new FormData(f);
        const base = window.ACC_EDU_CFG?.api || '/acc-engine/api.php/acc/v1';
        const headers = {};
        if (this.token) headers.Authorization = `Bearer ${this.token}`;
        const r = await fetch(`${base}/education/companion/report-import`, { method: 'POST', headers, body: fd });
        const j = await r.json().catch(() => ({}));
        if (!r.ok || !j.success) throw new Error(j.message || 'خطا در بارگذاری');
        alert('کارنامه ثبت شد');
        const st = await this.api('/education/companion/state');
        this.companionState = st;
        this.compSection = 'reports';
        this._hydrateCompanionSection();
    }

    async _parentApprove() {
        const f = this.root.querySelector('#edu-parent-approve-form');
        if (!f) return;
        const fd = new FormData(f);
        await this.api('/education/companion/parent/approve', {
            method: 'POST',
            body: JSON.stringify({
                learner_user_id: +(fd.get('learner_user_id') || 0),
                monthly_budget_rial: +(fd.get('monthly_budget_rial') || 0),
                parent_notes: fd.get('parent_notes') || '',
            }),
        });
        alert('بودجه تأیید شد');
        this.tab = 'family';
        await this._hydrateTab();
    }

    async _refreshMatching(domain) {
        const match = await this.api(`/education/matching?domain=${encodeURIComponent(domain)}`);
        if (this.companionState) this.companionState.matching = match;
        if (this.tab === 'companion' && this.compSection === 'matching') {
            const mount = this.root.querySelector('#edu-companion-body');
            if (mount) {
                mount.innerHTML = LC.renderCompanionSection(this.companionState, 'matching');
                this._bindCompanion();
            }
        } else if (this.tab === 'family' && this.parentDash) {
            this.parentDash.matching = match;
            const mount = this.root.querySelector('#edu-tab-root');
            if (mount) {
                mount.innerHTML = LC.renderParentDashboard(this.parentDash);
                this._bindTabActions();
            }
        }
    }

    async _saveIdentity() {
        const f = this.root.querySelector('#edu-comp-identity-form');
        if (!f) return;
        const fd = new FormData(f);
        await this._saveCompanion({
            grade_level: fd.get('grade_level'),
            profile: {
                identity: {
                    full_name: fd.get('full_name'),
                    birth_year: fd.get('birth_year') ? +fd.get('birth_year') : null,
                    entry_grade: fd.get('entry_grade'),
                    city: fd.get('city'),
                },
            },
        });
    }

    async _saveHistory() {
        const rows = LC.collectHistoryRows(this.root);
        await this._saveCompanion({ profile: { academic_history: rows } });
    }

    async _saveCareer() {
        const f = this.root.querySelector('#edu-comp-career-form');
        if (!f) return;
        const jobs = [...f.querySelectorAll('[name=dream_jobs]:checked')].map(el => el.value);
        const skills = [...f.querySelectorAll('[name=skills_wanted]:checked')].map(el => el.value);
        const uni = (f.querySelector('[name=university_targets]')?.value || '').split(/[,،]/).map(s => s.trim()).filter(Boolean);
        const interests = (f.querySelector('[name=interests]')?.value || '').split(/[,،]/).map(s => s.trim()).filter(Boolean);
        await this._saveCompanion({ profile: { career: { dream_jobs: jobs, skills_wanted: skills, university_targets: uni, interests } } });
    }

    async _saveBudget() {
        const f = this.root.querySelector('#edu-comp-budget-form');
        if (!f) return;
        const fd = new FormData(f);
        await this._saveCompanion({
            profile: {
                family: {
                    monthly_budget_rial: +(fd.get('monthly_budget_rial') || 0),
                    budget_tier: fd.get('budget_tier'),
                    parent_name: fd.get('parent_name'),
                    parent_phone: fd.get('parent_phone'),
                },
            },
        });
    }

    _addHistoryRow() {
        const box = this.root.querySelector('#edu-history-rows');
        if (!box || !this.companionState) return;
        const grades = this.companionState.schema?.grades || {};
        const i = box.querySelectorAll('.edu-history-row').length;
        const div = document.createElement('div');
        div.className = 'edu-history-row';
        div.innerHTML = `<div class="edu-grid-2">
            <div class="edu-field"><label>پایه</label><select class="edu-h-grade">${Object.entries(grades).filter(([k])=>k!=='graduate').map(([k,v])=>`<option value="${k}">${v}</option>`).join('')}</select></div>
            <div class="edu-field"><label>سال</label><input class="edu-h-year"></div>
            <div class="edu-field"><label>مدرسه</label><input class="edu-h-school"></div>
            <div class="edu-field"><label>معلم</label><input class="edu-h-teacher"></div>
            <div class="edu-field"><label>معدل</label><input class="edu-h-avg" type="number" step="0.01"></div>
        </div><button type="button" class="edu-btn edu-btn--ghost edu-btn--sm edu-h-remove">حذف</button>`;
        box.appendChild(div);
        div.querySelector('.edu-h-remove')?.addEventListener('click', () => div.remove());
    }

    async _saveEducatorFull() {
        const payload = LC.collectEducatorProfile(this.root);
        await this.api('/education/educator/profile', { method: 'PUT', body: JSON.stringify(payload) });
        alert('رزومه ذخیره شد');
    }

    _addCvRow() {
        const box = this.root.querySelector('#edu-cv-rows');
        if (!box) return;
        const d = document.createElement('div');
        d.className = 'edu-cv-row';
        d.innerHTML = '<input class="edu-cv-degree" placeholder="مدرک"><input class="edu-cv-inst" placeholder="مؤسسه"><input class="edu-cv-years" type="number" placeholder="سال">';
        box.appendChild(d);
    }

    _addWorkRow() {
        const box = this.root.querySelector('#edu-work-rows');
        if (!box) return;
        const d = document.createElement('div');
        d.className = 'edu-work-row';
        d.innerHTML = '<input class="edu-w-org" placeholder="مؤسسه"><input class="edu-w-role" placeholder="سمت"><input class="edu-w-years" type="number"><input class="edu-w-subject" placeholder="درس">';
        box.appendChild(d);
    }

    async _saveOrgFac() {
        const facilities = [...this.root.querySelectorAll('.edu-fac-cb:checked')].map(el => el.value);
        const programs = (this.root.querySelector('#edu-org-programs')?.value || '').split(/[,،]/).map(s => s.trim()).filter(Boolean);
        const facility_notes = this.root.querySelector('#edu-org-fac-notes')?.value || '';
        await this.api(`/education/orgs/${this.orgEditId}`, {
            method: 'PUT',
            body: JSON.stringify({ facilities, programs, profile: { facility_notes, programs } }),
        });
        alert('امکانات ذخیره شد');
    }

    _bindRequestFlow() {
        const form = this.root.querySelector('#edu-request-form');
        form?.addEventListener('submit', e => { e.preventDefault(); this._submitRequest(); });

        this.root.querySelectorAll('.edu-choice-card').forEach(card => {
            card.addEventListener('click', () => {
                this.root.querySelectorAll('.edu-choice-card').forEach(c => c.classList.remove('edu-choice-card--active'));
                card.classList.add('edu-choice-card--active');
                const st = card.dataset.stype || 'academic';
                this._syncTrackDomain(st);
            });
        });

        this.root.querySelectorAll('.edu-resume-test').forEach(b => {
            b.addEventListener('click', () => this._resumeTest(+b.dataset.rid));
        });
        this.root.querySelector('#edu-test-next')?.addEventListener('click', () => this._nextTestPhase());
        this.root.querySelector('#edu-test-prev')?.addEventListener('click', () => this._prevTestPhase());
        this.root.querySelector('#edu-submit-test')?.addEventListener('click', () => this._submitTest());
        this.root.querySelector('#edu-goto-book')?.addEventListener('click', () => { this.tab = 'book'; this._paint(); });
        this.root.querySelector('#edu-goto-brain')?.addEventListener('click', () => { this.tab = 'brain'; this._paint(); });
        this.root.querySelector('#edu-new-request')?.addEventListener('click', () => this._resetFlow());
        this.root.querySelector('#edu-dash-new-req')?.addEventListener('click', () => { this.tab = 'request'; this._resetFlow(); });
    }

    _syncTrackDomain(sessionType) {
        const tracks = this.meta?.tracks || {};
        const domains = this.meta?.skill_domains || {};
        const trackSel = this.root.querySelector('#edu-req-track');
        const domainSel = this.root.querySelector('#edu-req-domain');
        const goalsGrid = this.root.querySelector('#edu-goals-grid');
        if (!trackSel || !domainSel) return;

        const isSkill = sessionType === 'skill';
        const trackKeys = isSkill ? R.TRACK_DOMAINS.SKILL_TRACKS : R.TRACK_DOMAINS.ACADEMIC_TRACKS;
        const domainKeys = isSkill ? R.TRACK_DOMAINS.SKILL_DOMAINS : R.TRACK_DOMAINS.ACADEMIC_DOMAINS;

        trackSel.innerHTML = trackKeys.map(k => `<option value="${k}">${this.esc(tracks[k] || k)}</option>`).join('');
        domainSel.innerHTML = domainKeys.map(k => `<option value="${k}">${this.esc(domains[k] || k)}</option>`).join('');

        if (goalsGrid) {
            const goals = this.meta?.learning_goals || {};
            const keys = isSkill ? ['skill_hobby', 'skill_pro', 'certification'] : ['konkur_exam', 'supplementary', 'tizhooshan', 'school_exam'];
            goalsGrid.innerHTML = keys.map(k => goals[k] ? `
                <label class="edu-check"><input type="checkbox" name="goals" value="${k}"> ${this.esc(goals[k])}</label>` : '').join('');
        }
    }

    _resetFlow() {
        this.flowStep = 'form';
        this.flowRequestId = null;
        this.flowTest = null;
        this.flowPhaseIdx = 0;
        this.flowAnswers = {};
        this.flowResults = null;
        this.flowRequest = null;
        this._hydrateTab();
    }

    async _submitRequest() {
        const form = this.root.querySelector('#edu-request-form');
        if (!form) return;
        const payload = R.parseRequestForm(form);
        if (!payload.goals?.length) {
            alert('حداقل یک هدف یادگیری انتخاب کنید.');
            return;
        }
        const btn = this.root.querySelector('#edu-submit-request');
        if (btn) { btn.disabled = true; btn.textContent = 'در حال ثبت…'; }
        try {
            const r = await this.api('/education/requests', { method: 'POST', body: JSON.stringify(payload) });
            this.flowRequestId = r.request_id;
            this.flowRefCode = r.ref_code;
            this.flowSessionType = payload.session_type;
            await this._loadTest(r.request_id);
        } catch (e) {
            alert(e.message);
        } finally {
            if (btn) { btn.disabled = false; btn.textContent = 'ثبت درخواست و ورود به آزمون ←'; }
        }
    }

    async _resumeTest(id) {
        this.flowRequestId = id;
        await this._loadTest(id);
    }

    async _loadTest(id) {
        const test = await this.api(`/education/requests/${id}/test`);
        if (!test.success) {
            alert(test.message || 'خطا');
            return;
        }
        this.flowTest = test;
        this.flowPhaseIdx = 0;
        this.flowAnswers = {};
        this.flowStep = 'test';
        this.flowSessionType = test.session_type;
        this._renderFlowBody();
    }

    _renderFlowBody() {
        const mount = this.root.querySelector('#edu-flow-body');
        if (!mount) return;
        mount.innerHTML = this.flowStep === 'test'
            ? R.renderOnlineTest({ test: this.flowTest, phaseIdx: this.flowPhaseIdx, session_type: this.flowSessionType })
            : R.renderTestResult({
                results: this.flowResults,
                request: this.flowRequest,
                ref_code: this.flowRefCode,
            });
        this.root.querySelector('#edu-test-next')?.addEventListener('click', () => this._nextTestPhase());
        this.root.querySelector('#edu-test-prev')?.addEventListener('click', () => this._prevTestPhase());
        this.root.querySelector('#edu-submit-test')?.addEventListener('click', () => this._submitTest());
        this.root.querySelector('#edu-goto-book')?.addEventListener('click', () => { this.tab = 'book'; this._paint(); });
        this.root.querySelector('#edu-goto-brain')?.addEventListener('click', () => { this.tab = 'brain'; this._paint(); });
        this.root.querySelector('#edu-new-request')?.addEventListener('click', () => this._resetFlow());
    }

    _mergePhaseAnswers() {
        Object.assign(this.flowAnswers, R.collectTestAnswers(this.root));
    }

    _nextTestPhase() {
        this._mergePhaseAnswers();
        const total = this.flowTest?.phases?.length || 1;
        if (this.flowPhaseIdx < total - 1) {
            this.flowPhaseIdx++;
            this._renderFlowBody();
        }
    }

    _prevTestPhase() {
        this._mergePhaseAnswers();
        if (this.flowPhaseIdx > 0) {
            this.flowPhaseIdx--;
            this._renderFlowBody();
        }
    }

    async _submitTest() {
        this._mergePhaseAnswers();
        const btn = this.root.querySelector('#edu-submit-test');
        if (btn) { btn.disabled = true; btn.textContent = 'در حال تصحیح…'; }
        try {
            const r = await this.api(`/education/requests/${this.flowRequestId}/submit`, {
                method: 'POST',
                body: JSON.stringify({ answers: this.flowAnswers }),
            });
            if (!r.success) throw new Error(r.message || 'خطا');
            this.flowResults = r.results;
            this.flowRequest = { ref_code: this.flowRefCode };
            this.flowStep = 'result';
            await this._loadApp();
            this._renderFlowBody();
            const stepper = this.root.querySelectorAll('.edu-stepper__item');
            stepper.forEach(el => el.classList.add('edu-stepper__item--done'));
        } catch (e) {
            alert(e.message);
        } finally {
            if (btn) { btn.disabled = false; btn.textContent = 'ارسال پاسخ‌ها و مشاهده نتیجه'; }
        }
    }

    async _demoLogin(role, username, tab, rowEl) {
        const badge = rowEl.querySelector('.edu-demo-row__badge');
        rowEl.classList.add('edu-demo-row--loading');
        if (badge) badge.textContent = '⏳…';
        try {
            const base = window.ACC_EDU_CFG?.api || '/acc-engine/api.php/acc/v1';
            const r = await fetch(`${base}/public/auth/login`, {
                method: 'POST', headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ username, password: DEMO_PASS }),
            });
            const j = await r.json();
            if (!r.ok || !j.token) throw new Error(j.message || 'خطا');
            this.token = j.token;
            sessionStorage.setItem(TOKEN_KEY, this.token);
            this.role = role;
            sessionStorage.setItem(ROLE_KEY, role);
            await this._loadApp();
            this.screen = 'app';
            this.tab = tab || ({ learner: 'companion', parent: 'family' }[role] || 'dashboard');
            this._paint();
        } catch (e) {
            rowEl.classList.remove('edu-demo-row--loading');
            if (badge) badge.textContent = '❌ ' + e.message;
        }
    }

    async _login() {
        this.err = '';
        const user = this.root.querySelector('#edu-login-user')?.value?.trim();
        const pass = this.root.querySelector('#edu-login-pass')?.value || '';
        const base = window.ACC_EDU_CFG?.api || '/acc-engine/api.php/acc/v1';
        try {
            const r = await fetch(`${base}/public/auth/login`, {
                method: 'POST', headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ username: user, password: pass }),
            });
            const j = await r.json();
            if (!r.ok || !j.token) throw new Error(j.message || 'خطا');
            this.token = j.token;
            sessionStorage.setItem(TOKEN_KEY, this.token);
            await this._loadApp();
            this.screen = 'app';
            this.tab = this.pendingLoginTab
                || ({ learner: 'companion', parent: 'family', accountant: 'cost' }[this.role] || 'dashboard');
            this._paint();
        } catch (e) {
            this.err = e.message;
            this.screen = 'login';
            this._paint();
        }
    }

    _bookPayload() {
        return {
            session_type: this.root.querySelector('#edu-b-stype')?.value,
            domain: this.root.querySelector('#edu-b-domain')?.value,
            delivery_mode: this.root.querySelector('#edu-b-delivery')?.value,
            venue_type: this.root.querySelector('#edu-b-venue')?.value,
            org_id: +(this.root.querySelector('#edu-b-org')?.value || 0) || undefined,
            duration_min: +(this.root.querySelector('#edu-b-dur')?.value || 90),
            distance_km: +(this.root.querySelector('#edu-b-km')?.value || 0),
        };
    }

    async _calcQuote() {
        const q = await this.api('/education/sessions/quote', { method: 'POST', body: JSON.stringify(this._bookPayload()) });
        const box = this.root.querySelector('#edu-quote-box');
        if (box && q.lines) {
            box.innerHTML = `<div class="edu-quote-lines">${q.lines.map(l =>
                `<div><span>${this.esc(l.label)}</span><span>${this.fmt(l.amount)}</span></div>`).join('')}
                <div class="total"><span>جمع</span><span>${this.fmt(q.total)} ریال</span></div></div>`;
        }
    }

    async _submitSession() {
        await this._calcQuote();
        const r = await this.api('/education/sessions', { method: 'POST', body: JSON.stringify(this._bookPayload()) });
        alert(r.success ? `ثبت #${r.session_id}` : (r.message || 'خطا'));
        await this._loadApp();
        this.tab = 'sessions';
        this._paint();
    }

    async _runPlacement() {
        const answers = {};
        this.root.querySelectorAll('.edu-plc-input').forEach(el => { answers[el.dataset.domain] = +el.value; });
        const track = this.root.querySelector('#edu-plc-track')?.value;
        if (track) await this.api('/education/learner/profile', { method: 'PUT', body: JSON.stringify({ track }) });
        const r = await this.api('/education/placement', { method: 'POST', body: JSON.stringify({ answers }) });
        const out = this.root.querySelector('#edu-placement-result');
        if (out) {
            out.innerHTML = `<div class="edu-success" style="margin-top:12px">
                ✅ Placement انجام شد — ${(r.weaknesses||[]).length} ضعف · ${(r.plan?.weeks||[]).length} هفته برنامه
            </div>`;
        }
        await this._loadApp();
        setTimeout(() => { this.tab = 'brain'; this._paint(); }, 800);
    }

    async _addLog() {
        await this.api('/education/learner/log', {
            method: 'POST',
            body: JSON.stringify({
                log_type: this.root.querySelector('#edu-log-type')?.value,
                category: 'general',
                title: this.root.querySelector('#edu-log-title')?.value,
            }),
        });
        this._hydrateTab();
    }

    async _addSlot() {
        const orgId = this.schedOrgId || this.root.querySelector('#edu-sched-org')?.value;
        await this.api(`/education/orgs/${orgId}/schedule`, {
            method: 'POST',
            body: JSON.stringify({
                slot_date: this.root.querySelector('#edu-slot-date')?.value,
                start_time: this.root.querySelector('#edu-slot-start')?.value,
                end_time: this.root.querySelector('#edu-slot-end')?.value,
            }),
        });
        this._hydrateTab();
    }

    async _sendAi() {
        const inp = this.root.querySelector('#edu-ai-input');
        const box = this.root.querySelector('#edu-ai-messages');
        const msg = inp?.value?.trim();
        if (!msg || !box) return;
        box.innerHTML += `<div class="edu-ai-msg edu-ai-msg--user">${this.esc(msg)}</div>`;
        inp.value = '';
        const r = await this.api('/education/ai/chat', {
            method: 'POST',
            body: JSON.stringify({ message: msg, history: this.aiHistory }),
        });
        this.aiHistory.push({ role: 'user', content: msg }, { role: 'assistant', content: r.reply });
        box.innerHTML += `<div class="edu-ai-msg edu-ai-msg--bot">${this.esc(r.reply)} <span class="edu-muted">[${this.esc(r.engine||'ai')}]</span></div>`;
        box.scrollTop = box.scrollHeight;
    }

    async _viewSession(id) {
        const r = await this.api(`/education/sessions/${id}`);
        const mount = this.root.querySelector('#edu-session-detail-mount');
        if (mount) mount.innerHTML = P.renderSessionDetail(r.session);
    }

    async _viewOrg(id) {
        const r = await this.api(`/education/orgs/${id}`);
        const mount = this.root.querySelector('#edu-org-detail-box');
        if (mount) mount.innerHTML = P.renderOrgDetail(r.org);
    }

    async _viewSplits(id) {
        const r = await this.api(`/education/accounting/splits/${id}`);
        const mount = this.root.querySelector('#edu-splits-mount');
        if (mount) mount.innerHTML = P.renderSplits(r.splits);
    }

    async _assign(id) { await this.api(`/education/sessions/${id}/assign`, { method: 'POST', body: '{}' }); await this._loadApp(); this._paint(); }
    async _complete(id) { await this.api(`/education/sessions/${id}/complete`, { method: 'POST', body: JSON.stringify({ summary: 'تکمیل' }) }); await this._loadApp(); this._paint(); }
    async _postSession(id) { await this.api(`/education/accounting/post/${id}`, { method: 'POST', body: '{}' }); await this._loadApp(); this._paint(); }
    async _saveEducator() {
        await this.api('/education/educator/profile', {
            method: 'PUT',
            body: JSON.stringify({
                educator_type: this.root.querySelector('#edu-e-type')?.value,
                hourly_rate: +(this.root.querySelector('#edu-e-rate')?.value || 0),
            }),
        });
        alert('ذخیره شد');
    }

    async _loadCostAuto() {
        const r = await this.api('/education/accounting/cost-report');
        const out = this.root.querySelector('#edu-cost-out');
        if (out) out.innerHTML = `<div class="edu-stat-row">
            <div class="edu-stat"><strong>${this.fmt(r.revenue)}</strong><span>درآمد</span></div>
            <div class="edu-stat"><strong>${this.fmt(r.mentor)}</strong><span>مربی</span></div>
            <div class="edu-stat"><strong>${this.fmt(r.transport)}</strong><span>ایاب‌ذهاب</span></div>
            <div class="edu-stat"><strong>${this.fmt(r.materials)}</strong><span>مواد</span></div>
            <div class="edu-stat"><strong>${this.fmt(r.overhead)}</strong><span>سربار</span></div>
            <div class="edu-stat"><strong>${r.sessions||0}</strong><span>جلسات</span></div></div>`;
    }

    async _loadCost() { await this._loadCostAuto(); }
}
