/**
 * AclUserProfileSection.js — پروفایل دسترسی یکپارچه هر کاربر
 * جریان: انتخاب کاربر → منوها → نقش‌ها → scope → ذخیره
 */
import SectionBase from "../../accounting/SectionBase.js";

export default class AclUserProfileSection extends SectionBase {

    constructor(p) {
        super(p);
        this._users      = [];
        this._selectedId = null;
        this._profile    = null;
        this._menus      = [];
        this._roles      = [];
        this._registry   = {};
        this._profiles   = [];
        this._scopeCache = {};
        this._state      = { menu_keys: [], role_ids: [], scopes: {} };
    }

    async template() {
        return `
        <div class="acc-section-wrap acl-user-profile">
            <div class="acc-toolbar" style="flex-wrap:wrap;gap:10px;">
                <h2 class="acc-section-title">👤 پروفایل دسترسی کاربر</h2>
                <div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-right:auto;">
                    <select data-ref="userSelect" class="acc-input" style="min-width:240px;">
                        <option value="">— انتخاب کاربر —</option>
                    </select>
                    <select data-ref="profileSelect" class="acc-input" style="min-width:200px;">
                        <option value="">📋 پروفایل آماده...</option>
                    </select>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>

            <div data-ref="empty" class="acc-empty" style="padding:40px;">
                یک کاربر را انتخاب کنید تا منو، نقش و محدوده دسترسی را تنظیم کنید.
            </div>

            <div data-ref="editor" style="display:none;">
                <div data-ref="warnings" style="display:none;margin-bottom:12px;"></div>

                <div class="acl-profile-card">
                    <h3>۱. منوهای قابل مشاهده</h3>
                    <p class="acl-profile-hint">کاربر فقط این منوها را در sidebar می‌بیند.</p>
                    <div data-ref="menuGrid" class="acl-check-grid"></div>
                </div>

                <div class="acl-profile-card">
                    <h3>۲. نقش‌ها (عملیات مجاز)</h3>
                    <p class="acl-profile-hint">نقش تعیین می‌کند کاربر چه کارهایی انجام دهد (ثبت، ویرایش، حذف).</p>
                    <div data-ref="roleGrid" class="acl-check-grid"></div>
                    <div data-ref="roleSuggest" class="acl-profile-suggest"></div>
                </div>

                <div class="acl-profile-card">
                    <h3>۳. محدوده دسترسی (Scope)</h3>
                    <p class="acl-profile-hint">برای ماژول‌های انتخاب‌شده، مشخص کنید روی کدام انبار/پروژه/منطقه کار کند. خالی = سراسری.</p>
                    <div data-ref="scopeArea"></div>
                </div>

                <div style="display:flex;gap:10px;justify-content:flex-end;margin-top:16px;">
                    <button class="acc-btn acc-btn--primary" data-ref="saveBtn">💾 ذخیره دسترسی‌ها</button>
                </div>
            </div>
        </div>
        <style>
            .acl-user-profile .acl-profile-card {
                background:#fff;border:1px solid #e2e8f0;border-radius:12px;
                padding:16px 18px;margin-bottom:14px;
            }
            .acl-user-profile .acl-profile-card h3 { margin:0 0 6px;font-size:15px; }
            .acl-user-profile .acl-profile-hint { margin:0 0 12px;color:#64748b;font-size:12px; }
            .acl-user-profile .acl-check-grid {
                display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:8px;
            }
            .acl-user-profile .acl-check-item {
                display:flex;align-items:center;gap:8px;padding:8px 10px;
                border:1px solid #e2e8f0;border-radius:8px;cursor:pointer;font-size:13px;
            }
            .acl-user-profile .acl-check-item:hover { background:#f8fafc; }
            .acl-user-profile .acl-check-item input { accent-color:#4f46e5; }
            .acl-user-profile .acl-scope-block {
                border:1px dashed #cbd5e1;border-radius:10px;padding:12px;margin-bottom:10px;
            }
            .acl-user-profile .acl-scope-block h4 { margin:0 0 8px;font-size:13px; }
            .acl-user-profile .acl-warn-box {
                background:#fef9c3;border:1px solid #fde047;color:#854d0e;
                padding:10px 14px;border-radius:8px;font-size:13px;
            }
            .acl-user-profile .acl-profile-suggest {
                margin-top:8px;font-size:12px;color:#6366f1;
            }
        </style>`;
    }

    async afterRender() {
        await this._loadUsers();
        await this._loadRegistry();
        this.on(this.ref("refreshBtn"), "click", () => this._reload());
        this.on(this.ref("userSelect"), "change", () => this._onUserChange());
        this.on(this.ref("profileSelect"), "change", () => this._applyProfile());
        this.on(this.ref("saveBtn"), "click", () => this._save());
    }

    async _loadUsers() {
        try {
            const res = await this.api.get("/acl/users");
            this._users = res?.data ?? [];
            const sel = this.ref("userSelect");
            sel.innerHTML = `<option value="">— انتخاب کاربر —</option>` +
                this._users.map(u =>
                    `<option value="${u.user_id}">${this.escape(u.display_name || u.user_login)} (${this.escape(u.user_login)})</option>`
                ).join("");
        } catch {
            this.ref("userSelect").innerHTML = `<option value="">خطا در بارگذاری کاربران</option>`;
        }
    }

    async _loadRegistry() {
        try {
            const res = await this.api.get("/acl/module-registry");
            this._registry = res?.data ?? {};
            this._profiles = res?.profiles ?? [];
            const ps = this.ref("profileSelect");
            ps.innerHTML = `<option value="">📋 پروفایل آماده...</option>` +
                this._profiles.map(p =>
                    `<option value="${p.key}">${this.escape(p.label)}</option>`
                ).join("");
        } catch {}
    }

    async _onUserChange() {
        const id = parseInt(this.ref("userSelect").value, 10);
        this._selectedId = id || null;
        if (!this._selectedId) {
            this.ref("empty").style.display = "";
            this.ref("editor").style.display = "none";
            return;
        }
        await this._loadProfile();
    }

    async _reload() {
        await this._loadUsers();
        if (this._selectedId) await this._loadProfile();
    }

    async _loadProfile() {
        this.ref("empty").style.display = "none";
        this.ref("editor").style.display = "";
        this.ref("editor").querySelector(".acc-loading")?.remove();

        try {
            const res = await this.api.get(`/acl/users/${this._selectedId}/profile`);
            this._profile = res?.profile ?? null;
            this._menus    = res?.menus ?? [];
            this._roles    = res?.roles ?? [];
            this._state = {
                menu_keys: [...(this._profile?.menu_keys ?? [])],
                role_ids:  [...(this._profile?.role_ids ?? [])],
                scopes:    { ...(this._profile?.scopes ?? {}) },
            };
            this._renderAll(res?.suggested_roles ?? []);
        } catch (e) {
            this.ref("editor").innerHTML = `<div class="acc-error">❌ ${this.escape(e?.message ?? "خطا")}</div>`;
        }
    }

    _renderAll(suggestedRoles = []) {
        this._renderMenus();
        this._renderRoles(suggestedRoles);
        this._renderScopes();
        this._validateUi();
    }

    _renderMenus() {
        const grid = this.ref("menuGrid");
        const adminMenus = ["access", "users"];
        grid.innerHTML = this._menus
            .filter(m => !adminMenus.includes(m.menu_key))
            .map(m => {
                const checked = this._state.menu_keys.includes(m.menu_key) ? "checked" : "";
                return `<label class="acl-check-item">
                    <input type="checkbox" data-menu="${m.menu_key}" ${checked}>
                    <span>${this.escape(m.icon || "")} ${this.escape(m.title)}</span>
                </label>`;
            }).join("");

        grid.querySelectorAll("input[data-menu]").forEach(inp => {
            inp.addEventListener("change", async () => {
                const key = inp.dataset.menu;
                if (inp.checked) {
                    if (!this._state.menu_keys.includes(key)) this._state.menu_keys.push(key);
                } else {
                    this._state.menu_keys = this._state.menu_keys.filter(k => k !== key);
                }
                await this._refreshScopeAndSuggest();
                this._validateUi();
            });
        });
    }

    _renderRoles(suggestedRoles = []) {
        const grid = this.ref("roleGrid");
        const canAssignSuper = typeof window !== "undefined" && window.acl?.isSuperAdmin?.();
        const roles = this._roles.filter(r => r.slug !== "super_admin" || canAssignSuper);

        grid.innerHTML = roles.map(r => {
            const checked = this._state.role_ids.includes(+r.id) ? "checked" : "";
            const isSuper = r.slug === "super_admin";
            return `<label class="acl-check-item" ${isSuper ? 'style="border-color:#f59e0b;background:#fffbeb;"' : ""}>
                <input type="checkbox" data-role="${r.id}" ${checked}>
                <span><b>${this.escape(r.name)}</b><br><small style="color:#94a3b8;">${this.escape(r.slug)}</small></span>
            </label>`;
        }).join("");

        grid.querySelectorAll("input[data-role]").forEach(inp => {
            inp.addEventListener("change", () => {
                const id = +inp.dataset.role;
                if (inp.checked) {
                    if (!this._state.role_ids.includes(id)) this._state.role_ids.push(id);
                } else {
                    this._state.role_ids = this._state.role_ids.filter(x => x !== id);
                }
                this._validateUi();
            });
        });

        const sug = this.ref("roleSuggest");
        if (suggestedRoles.length) {
            const names = suggestedRoles.map(r => r.name).join("، ");
            sug.innerHTML = `💡 پیشنهاد برای منوهای انتخاب‌شده: <b>${this.escape(names)}</b>
                <button type="button" class="acc-btn acc-btn--xs acc-btn--secondary" data-ref="applySuggest" style="margin-right:8px;">اعمال پیشنهاد</button>`;
            sug.querySelector("[data-ref=applySuggest]")?.addEventListener("click", () => {
                suggestedRoles.forEach(r => {
                    const id = +r.id;
                    if (!this._state.role_ids.includes(id)) this._state.role_ids.push(id);
                });
                this._renderRoles(suggestedRoles);
                this._validateUi();
            });
        } else {
            sug.innerHTML = "";
        }
    }

    async _refreshScopeAndSuggest() {
        try {
            const res = await this.api.get(`/acl/users/${this._selectedId}/profile`);
            this._renderRoles(res?.suggested_roles ?? []);
        } catch {}
        await this._renderScopes();
    }

    async _renderScopes() {
        const area = this.ref("scopeArea");
        const types = this._getScopeTypesForMenus();
        if (!types.length) {
            area.innerHTML = `<div style="color:#94a3b8;font-size:13px;">برای منوهای انتخاب‌شده محدوده‌ای تعریف نشده (سراسری).</div>`;
            return;
        }

        area.innerHTML = `<div class="acc-loading">⏳ بارگذاری محدوده‌ها...</div>`;

        const blocks = [];
        for (const st of types) {
            const opts = await this._loadScopeOptions(st.scope_type);
            const selected = new Set(this._state.scopes[st.scope_type] ?? []);
            blocks.push(`
                <div class="acl-scope-block" data-scope-type="${st.scope_type}">
                    <h4>${this.escape(st.scope_label || st.scope_type)}</h4>
                    <div class="acl-check-grid">
                        ${opts.length ? opts.map(o => `
                            <label class="acl-check-item">
                                <input type="checkbox" data-scope-type="${st.scope_type}" data-scope-id="${o.id}"
                                    ${selected.has(+o.id) ? "checked" : ""}>
                                <span>${this.escape(o.label || o.name || o.title || ("#" + o.id))}</span>
                            </label>
                        `).join("") : `<div style="color:#94a3b8;font-size:12px;">موردی یافت نشد — خالی = سراسری</div>`}
                    </div>
                </div>
            `);
        }
        area.innerHTML = blocks.join("");

        area.querySelectorAll("input[data-scope-type]").forEach(inp => {
            inp.addEventListener("change", () => {
                const st = inp.dataset.scopeType;
                const id = +inp.dataset.scopeId;
                if (!this._state.scopes[st]) this._state.scopes[st] = [];
                if (inp.checked) {
                    if (!this._state.scopes[st].includes(id)) this._state.scopes[st].push(id);
                } else {
                    this._state.scopes[st] = this._state.scopes[st].filter(x => x !== id);
                }
            });
        });
    }

    _getScopeTypesForMenus() {
        const seen = new Set();
        const out  = [];
        for (const mk of this._state.menu_keys) {
            for (const mod of Object.values(this._registry)) {
                if (mod.menu_key === mk && mod.scope_type && !seen.has(mod.scope_type)) {
                    seen.add(mod.scope_type);
                    out.push({
                        scope_type:  mod.scope_type,
                        scope_label: mod.scope_label,
                        scope_api:   mod.scope_api,
                    });
                }
            }
        }
        return out;
    }

    async _loadScopeOptions(scopeType) {
        if (this._scopeCache[scopeType]) return this._scopeCache[scopeType];
        try {
            const res = await this.api.get(`/acl/scope-options/${scopeType}`);
            this._scopeCache[scopeType] = res?.data ?? [];
        } catch {
            this._scopeCache[scopeType] = [];
        }
        return this._scopeCache[scopeType];
    }

    _validateUi() {
        const box = this.ref("warnings");
        const warnings = [];

        if (!this._state.menu_keys.length) {
            warnings.push("حداقل یک منو انتخاب کنید.");
        }
        if (!this._state.role_ids.length) {
            warnings.push("حداقل یک نقش انتخاب کنید.");
        }

        for (const mk of this._state.menu_keys) {
            for (const mod of Object.values(this._registry)) {
                if (mod.menu_key !== mk || !mod.view_perm) continue;
                const rolePerms = this._getSelectedRolePerms();
                if (!rolePerms.has(mod.view_perm)) {
                    warnings.push(`منوی «${mod.label}» نیاز به مجوز ${mod.view_perm} دارد که در نقش‌های انتخاب‌شده نیست.`);
                }
            }
        }

        const superRole = this._roles.find(r => r.slug === "super_admin");
        if (superRole && this._state.role_ids.includes(+superRole.id)) {
            warnings.push("نقش «مدیر کل سیستم» دسترسی سراسری دارد — محدوده انبار/پروژه روی این نقش اعمال نمی‌شود. برای محدودیت واقعی، super_admin را بردارید و نقش‌های عملیاتی (مثل انباردار/فروش) بدهید.");
        }

        if (warnings.length) {
            box.style.display = "";
            box.className = "acl-warn-box";
            box.innerHTML = "⚠️ " + warnings.map(w => `<div>${this.escape(w)}</div>`).join("");
        } else {
            box.style.display = "none";
            box.innerHTML = "";
        }
    }

    _getSelectedRolePerms() {
        const perms = new Set();
        for (const r of this._roles) {
            if (this._state.role_ids.includes(+r.id) && r.permissions) {
                r.permissions.forEach(p => perms.add(p));
            }
        }
        return perms;
    }

    async _applyProfile() {
        const key = this.ref("profileSelect").value;
        if (!key) return;
        const profile = this._profiles.find(p => p.key === key);
        if (!profile) return;

        this._state.menu_keys = [...(profile.menu_keys ?? [])];
        this._state.scopes    = JSON.parse(JSON.stringify(profile.scopes ?? {}));

        const slugs = profile.role_slugs ?? [];
        this._state.role_ids = this._roles
            .filter(r => slugs.includes(r.slug))
            .map(r => +r.id);

        this._renderAll();
        this.ref("profileSelect").value = "";
    }

    async _save() {
        if (!this._selectedId) return;

        const btn = this.ref("saveBtn");
        btn.disabled = true;
        btn.textContent = "⏳ در حال ذخیره...";

        try {
            const res = await this.api.put(`/acl/users/${this._selectedId}/profile`, {
                menu_keys: this._state.menu_keys,
                role_ids:  this._state.role_ids,
                scopes:    this._state.scopes,
            });

            btn.disabled = false;
            btn.textContent = "💾 ذخیره دسترسی‌ها";

            const notes = [...(res?.warnings ?? [])];
            if (res?.menus_saved === false) {
                notes.push("جدول منوها در دیتابیس نیست — run-acl-migrate.php را اجرا کنید.");
            }
            if (notes.length) {
                const box = this.ref("warnings");
                box.style.display = "";
                box.className = "acl-warn-box";
                box.innerHTML = "⚠️ ذخیره شد با هشدار:<br>" + notes.map(w => `<div>${this.escape(w)}</div>`).join("");
            } else {
                const box = this.ref("warnings");
                box.style.display = "";
                box.className = "acl-warn-box";
                box.style.background = "#dcfce7";
                box.style.borderColor = "#86efac";
                box.style.color = "#166534";
                box.innerHTML = "✅ دسترسی‌ها با موفقیت ذخیره شد";
                setTimeout(() => { box.style.display = "none"; }, 4000);
            }
            await this._loadProfile();
        } catch (e) {
            btn.disabled = false;
            btn.textContent = "💾 ذخیره دسترسی‌ها";
            const msg = e?.message ?? "خطا در ذخیره";
            if (msg.includes("هم‌خوان") || msg.includes("منو")) {
                if (confirm(msg + "\n\nبا وجود هشدار ذخیره شود؟")) {
                    try {
                        await this.api.put(`/acl/users/${this._selectedId}/profile`, {
                            menu_keys: this._state.menu_keys,
                            role_ids:  this._state.role_ids,
                            scopes:    this._state.scopes,
                            force: true,
                        });
                        await this._loadProfile();
                    } catch (e2) {
                        alert("❌ " + (e2?.message ?? ""));
                    }
                }
            } else {
                alert("❌ " + msg);
            }
        }
    }

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