var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { Component } from '@angular/core';
import { BaseResourceComponent } from '@memberjunction/ng-shared';
import { RegisterClass } from '@memberjunction/global';
import { DevToolsPrefs } from './dev-tools-prefs';
import { buildAppStateInspectorAgentContext } from './dev-tools-agent-context';
import { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';
import * as i0 from "@angular/core";
import * as i1 from "@memberjunction/ng-base-application";
import * as i2 from "@memberjunction/ng-shared";
import * as i3 from "@angular/forms";
import * as i4 from "@memberjunction/ng-ui-components";
import * as i5 from "@memberjunction/ng-code-editor";
/**
 * App State Inspector — read-only structured view of the Explorer's runtime
 * state. Replaces the legacy "Inspect App State" user-menu item which only
 * dumped to console. Lives in the Admin app's dev tools area.
 */
let AppStateInspectorComponent = class AppStateInspectorComponent extends BaseResourceComponent {
    cdr;
    workspace;
    devMode;
    Sections = [
        { id: 'user', label: 'Current User', icon: 'fa-solid fa-user', enabled: true, description: 'Identity, roles, email' },
        { id: 'provider', label: 'Provider', icon: 'fa-solid fa-plug', enabled: true, description: 'API URL, entities loaded' },
        { id: 'workspace', label: 'Workspace', icon: 'fa-solid fa-table-columns', enabled: true, description: 'Tabs, layout, active state' },
        { id: 'app', label: 'Active Application', icon: 'fa-solid fa-th-large', enabled: true, description: 'Current app + nav items' },
        { id: 'dev', label: 'Developer Mode', icon: 'fa-solid fa-code', enabled: true, description: 'Dev mode flag, eligibility' },
        { id: 'browser', label: 'Browser & Session', icon: 'fa-solid fa-window-maximize', enabled: true, description: 'User agent, viewport, URL' }
    ];
    ActiveSection = 'user';
    StateJson = '{}';
    SearchQuery = '';
    CopyConfirmed = false;
    LastRefreshed = new Date();
    constructor(cdr, workspace, devMode) {
        super();
        this.cdr = cdr;
        this.workspace = workspace;
        this.devMode = devMode;
    }
    ngOnInit() {
        const p = DevToolsPrefs.Get('appStateInspector');
        if (p?.activeSection && this.Sections.some(s => s.id === p.activeSection)) {
            this.ActiveSection = p.activeSection;
        }
        this.refresh();
        this.NotifyLoadComplete();
    }
    ngAfterViewInit() {
        // Publish initial agent context. Re-emit happens in refresh() (section change).
        // 🔒 METADATA-ONLY surface — NO client tools are registered (see SAFETY note below).
        this.publishAgentContext();
    }
    ngOnDestroy() {
        DevToolsPrefs.Save('appStateInspector', { activeSection: this.ActiveSection });
        super.ngOnDestroy();
    }
    async GetResourceDisplayName() { return 'App State Inspector'; }
    async GetResourceIconClass() { return 'fa-solid fa-magnifying-glass-chart'; }
    /** Sections rendered as horizontal tabs in the chrome's [toolbar] slot. */
    get tabsConfig() {
        return this.Sections.map(s => ({
            key: s.id,
            label: s.label,
            icon: s.icon
        }));
    }
    /** Adapter for `<mj-tab-nav>`'s string-typed `(TabChange)` output. */
    onTabChange(key) {
        const section = this.Sections.find(s => s.id === key);
        if (section) {
            this.OnSectionClick(section);
        }
    }
    OnSectionClick(section) {
        if (this.ActiveSection === section.id)
            return;
        this.ActiveSection = section.id;
        DevToolsPrefs.Save('appStateInspector', { activeSection: this.ActiveSection });
        this.refresh();
    }
    refresh() {
        this.StateJson = JSON.stringify(this.computeSectionData(this.ActiveSection), this.jsonReplacer, 2);
        this.LastRefreshed = new Date();
        this.cdr.markForCheck();
        this.publishAgentContext();
    }
    async OnCopy() {
        try {
            await navigator.clipboard.writeText(this.StateJson);
            this.CopyConfirmed = true;
            this.cdr.markForCheck();
            setTimeout(() => {
                this.CopyConfirmed = false;
                this.cdr.markForCheck();
            }, 1800);
        }
        catch {
            // clipboard unavailable
        }
    }
    OnDownload() {
        const blob = new Blob([this.StateJson], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `mj-app-state-${this.ActiveSection}-${this.timestampSlug()}.json`;
        a.click();
        URL.revokeObjectURL(url);
    }
    get LastRefreshedLabel() {
        return this.LastRefreshed.toLocaleTimeString();
    }
    get SectionLabel() {
        return this.Sections.find(s => s.id === this.ActiveSection)?.label ?? '';
    }
    // ---------- private ----------
    computeSectionData(section) {
        switch (section) {
            case 'user': return this.userData();
            case 'provider': return this.providerData();
            case 'workspace': return this.workspaceData();
            case 'app': return this.appData();
            case 'dev': return this.devData();
            case 'browser': return this.browserData();
            default: return {};
        }
    }
    userData() {
        const user = this.ProviderToUse?.CurrentUser;
        if (!user)
            return { error: 'No current user' };
        return {
            ID: user.ID,
            Name: user.Name,
            FirstName: user.FirstName,
            LastName: user.LastName,
            Email: user.Email,
            Type: user.Type,
            IsActive: user.IsActive,
            LinkedRecordType: user.LinkedRecordType,
            CreatedAt: user.__mj_CreatedAt,
            Roles: (user.UserRoles ?? []).map(r => ({ Role: r.Role, RoleID: r.RoleID }))
        };
    }
    providerData() {
        const provider = this.ProviderToUse;
        if (!provider)
            return { error: 'No provider' };
        const data = {
            type: provider.constructor.name,
            EntitiesCount: provider.Entities?.length ?? 0,
            ApplicationsCount: provider.Applications?.length ?? 0,
            QueriesCount: provider.Queries?.length ?? 0,
            RolesCount: provider.Roles?.length ?? 0
        };
        if (provider instanceof GraphQLDataProvider) {
            data.URL = provider.ConfigData?.URL;
            data.WSURL = provider.ConfigData?.WSURL;
        }
        return data;
    }
    workspaceData() {
        const config = this.workspace.GetConfiguration();
        return config;
    }
    appData() {
        const config = this.workspace.GetConfiguration();
        if (!config)
            return { error: 'No workspace configuration' };
        const activeTab = config.tabs?.find(t => t.id === config.activeTabId);
        return {
            ActiveTabId: config.activeTabId,
            ActiveTab: activeTab,
            TabCount: config.tabs?.length ?? 0
        };
    }
    devData() {
        return {
            IsEnabled: this.devMode.IsEnabled,
            IsDeveloper: this.devMode.IsDeveloper,
            EligibleRoles: ['Developer', 'Admin', 'System Administrator', 'Integration']
        };
    }
    browserData() {
        return {
            UserAgent: navigator.userAgent,
            Language: navigator.language,
            Languages: navigator.languages,
            Platform: navigator.platform,
            Online: navigator.onLine,
            Viewport: { width: window.innerWidth, height: window.innerHeight, devicePixelRatio: window.devicePixelRatio },
            URL: window.location.href,
            Origin: window.location.origin,
            Path: window.location.pathname + window.location.search,
            Memory: this.readMemory()
        };
    }
    jsonReplacer(_key, value) {
        if (value instanceof Date)
            return value.toISOString();
        if (value instanceof Map)
            return Object.fromEntries(value.entries());
        if (value instanceof Set)
            return Array.from(value);
        if (typeof value === 'function')
            return `[Function ${value.name || 'anonymous'}]`;
        return value;
    }
    readMemory() {
        const memory = performance.memory;
        if (!memory)
            return undefined;
        return { usedJSHeapSize: memory.usedJSHeapSize, totalJSHeapSize: memory.totalJSHeapSize };
    }
    timestampSlug() {
        const d = new Date();
        const pad = (n) => n.toString().padStart(2, '0');
        return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
    }
    // ========================================
    // AI AGENT CONTEXT (METADATA-ONLY)
    //
    // 🔒 SAFETY BOUNDARY — CLASSIFICATION: METADATA-ONLY.
    // The App State Inspector renders the Explorer's runtime state — which can
    // include auth/session details, provider URLs, and user PII. We therefore
    // expose to the AI agent ONLY metadata ABOUT the state (its serialized size,
    // the number of top-level keys in the active section, and the section label)
    // — NEVER the state VALUES themselves. For the same reason, NO client tools
    // are registered here: there is no value-returning operation the agent may
    // invoke against this surface.
    // ========================================
    /**
     * Publish METADATA-ONLY context for the App State Inspector. Reports the
     * size of the active section's serialized JSON, its top-level key count, the
     * section label/ids, and the top-level KEY NAMES (structural identifiers like
     * "Email"/"Roles" — never their values). See SAFETY BOUNDARY above.
     */
    publishAgentContext() {
        const context = buildAppStateInspectorAgentContext({
            StateSize: this.StateJson.length,
            KeyCount: this.activeSectionKeys().length,
            ActiveSection: this.ActiveSection,
            ActiveSectionLabel: this.SectionLabel,
            SectionIds: this.Sections.map(s => s.id),
            // 🔒 KEY NAMES only — never values.
            TopLevelKeys: this.activeSectionKeys(),
        });
        this.navigationService.SetAgentContext(this, context);
    }
    /**
     * Top-level KEY NAMES of the active section's data — METADATA ONLY, never
     * any value. For an array, returns the numeric indices as strings.
     */
    activeSectionKeys() {
        const data = this.computeSectionData(this.ActiveSection);
        if (data && typeof data === 'object') {
            return Array.isArray(data)
                ? data.map((_, i) => String(i))
                : Object.keys(data);
        }
        return [];
    }
    static ɵfac = function AppStateInspectorComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || AppStateInspectorComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.WorkspaceStateManager), i0.ɵɵdirectiveInject(i2.DeveloperModeService)); };
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AppStateInspectorComponent, selectors: [["mj-app-state-inspector"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 20, vars: 16, consts: [[1, "mj-inspector", "mj-inspector--solo"], ["Role", "region", "AriaLabel", "App State inspector", "Title", "App State Inspector", "Subtitle", "Read-only snapshot of Explorer runtime state"], ["actions", ""], [3, "Clicked", "Loading"], ["mjButton", "", "size", "sm", 3, "click", "variant", "title"], ["aria-hidden", "true", 1, "fa-solid"], [1, "mj-action-label"], ["mjButton", "", "variant", "secondary", "size", "sm", "title", "Download as JSON", "aria-label", "Download as JSON", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-download"], ["toolbar", ""], [3, "TabChange", "Tabs", "ActiveKey"], [1, "mj-inspector__content"], [1, "mj-inspector__content-head"], [1, "mj-inspector__content-title"], [1, "mj-inspector__content-meta"], [1, "mj-inspector__editor"], [3, "ngModelChange", "ngModel", "language", "readonly", "lineWrapping"]], template: function AppStateInspectorComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵelementStart(0, "div", 0)(1, "mj-page-header-interior", 1)(2, "div", 2)(3, "mj-refresh-button", 3);
            i0.ɵɵlistener("Clicked", function AppStateInspectorComponent_Template_mj_refresh_button_Clicked_3_listener() { return ctx.refresh(); });
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(4, "button", 4);
            i0.ɵɵlistener("click", function AppStateInspectorComponent_Template_button_click_4_listener() { return ctx.OnCopy(); });
            i0.ɵɵelement(5, "i", 5);
            i0.ɵɵelementStart(6, "span", 6);
            i0.ɵɵtext(7);
            i0.ɵɵelementEnd()();
            i0.ɵɵelementStart(8, "button", 7);
            i0.ɵɵlistener("click", function AppStateInspectorComponent_Template_button_click_8_listener() { return ctx.OnDownload(); });
            i0.ɵɵelement(9, "i", 8);
            i0.ɵɵelementEnd()();
            i0.ɵɵelementStart(10, "div", 9)(11, "mj-tab-nav", 10);
            i0.ɵɵlistener("TabChange", function AppStateInspectorComponent_Template_mj_tab_nav_TabChange_11_listener($event) { return ctx.onTabChange($event); });
            i0.ɵɵelementEnd()()();
            i0.ɵɵelementStart(12, "div", 11)(13, "div", 12)(14, "h4", 13);
            i0.ɵɵtext(15);
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(16, "span", 14);
            i0.ɵɵtext(17);
            i0.ɵɵelementEnd()();
            i0.ɵɵelementStart(18, "div", 15)(19, "mj-code-editor", 16);
            i0.ɵɵtwoWayListener("ngModelChange", function AppStateInspectorComponent_Template_mj_code_editor_ngModelChange_19_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.StateJson, $event) || (ctx.StateJson = $event); return $event; });
            i0.ɵɵelementEnd()()()();
        } if (rf & 2) {
            i0.ɵɵadvance(3);
            i0.ɵɵproperty("Loading", false);
            i0.ɵɵadvance();
            i0.ɵɵproperty("variant", ctx.CopyConfirmed ? "success" : "secondary")("title", ctx.CopyConfirmed ? "Copied" : "Copy JSON");
            i0.ɵɵadvance();
            i0.ɵɵclassProp("fa-clipboard", !ctx.CopyConfirmed)("fa-check", ctx.CopyConfirmed);
            i0.ɵɵadvance(2);
            i0.ɵɵtextInterpolate(ctx.CopyConfirmed ? "Copied" : "Copy");
            i0.ɵɵadvance(4);
            i0.ɵɵproperty("Tabs", ctx.tabsConfig)("ActiveKey", ctx.ActiveSection);
            i0.ɵɵadvance(4);
            i0.ɵɵtextInterpolate(ctx.SectionLabel);
            i0.ɵɵadvance(2);
            i0.ɵɵtextInterpolate1("Refreshed ", ctx.LastRefreshedLabel);
            i0.ɵɵadvance(2);
            i0.ɵɵtwoWayProperty("ngModel", ctx.StateJson);
            i0.ɵɵproperty("language", "json")("readonly", true)("lineWrapping", true);
        } }, dependencies: [i3.NgControlStatus, i3.NgModel, i4.MJButtonDirective, i4.MJPageHeaderInteriorComponent, i4.MJRefreshButtonComponent, i4.MJTabNavComponent, i5.CodeEditorComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.mj-inspector[_ngcontent-%COMP%] {\n    display: flex;\n    flex-direction: column;\n    height: 100%;\n    min-height: 0;\n    background: var(--mj-bg-page);\n    color: var(--mj-text-primary);\n    font-family: inherit;\n}\n\n\n\n.mj-inspector__content[_ngcontent-%COMP%] {\n    flex: 1;\n    min-width: 0;\n    display: flex;\n    flex-direction: column;\n    background: var(--mj-bg-page);\n}\n.mj-inspector__content-head[_ngcontent-%COMP%] {\n    padding: 12px 20px;\n    border-bottom: 1px solid var(--mj-border-subtle);\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    background: var(--mj-bg-surface-card);\n}\n.mj-inspector__content-title[_ngcontent-%COMP%] {\n    margin: 0;\n    font-size: 13px;\n    font-weight: 600;\n    color: var(--mj-text-primary);\n}\n.mj-inspector__content-meta[_ngcontent-%COMP%] {\n    font-size: 11px;\n    color: var(--mj-text-muted);\n}\n.mj-inspector__editor[_ngcontent-%COMP%] {\n    flex: 1;\n    min-height: 0;\n    display: flex;\n    flex-direction: column;\n    overflow: hidden;\n}\n.mj-inspector__editor[_ngcontent-%COMP%]   mj-code-editor[_ngcontent-%COMP%] {\n    flex: 1;\n    min-height: 0;\n    display: block;\n}\n\n\n\n.mj-inspector__empty[_ngcontent-%COMP%] {\n    flex: 1;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    color: var(--mj-text-muted);\n    font-size: 13px;\n}"] });
};
AppStateInspectorComponent = __decorate([
    RegisterClass(BaseResourceComponent, 'AppStateInspector')
], AppStateInspectorComponent);
export { AppStateInspectorComponent };
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AppStateInspectorComponent, [{
        type: Component,
        args: [{ standalone: false, selector: 'mj-app-state-inspector', template: "<div class=\"mj-inspector mj-inspector--solo\">\n    <mj-page-header-interior\n        Role=\"region\"\n        AriaLabel=\"App State inspector\"\n        Title=\"App State Inspector\"\n        Subtitle=\"Read-only snapshot of Explorer runtime state\">\n        <div actions>\n            <mj-refresh-button [Loading]=\"false\" (Clicked)=\"refresh()\"></mj-refresh-button>\n            <button mjButton\n                    [variant]=\"CopyConfirmed ? 'success' : 'secondary'\"\n                    size=\"sm\"\n                    (click)=\"OnCopy()\"\n                    [title]=\"CopyConfirmed ? 'Copied' : 'Copy JSON'\">\n                <i class=\"fa-solid\" [class.fa-clipboard]=\"!CopyConfirmed\" [class.fa-check]=\"CopyConfirmed\" aria-hidden=\"true\"></i>\n                <span class=\"mj-action-label\">{{ CopyConfirmed ? 'Copied' : 'Copy' }}</span>\n            </button>\n            <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"OnDownload()\" title=\"Download as JSON\" aria-label=\"Download as JSON\">\n                <i class=\"fa-solid fa-download\" aria-hidden=\"true\"></i>\n            </button>\n        </div>\n        <div toolbar>\n            <mj-tab-nav\n                [Tabs]=\"tabsConfig\"\n                [ActiveKey]=\"ActiveSection\"\n                (TabChange)=\"onTabChange($event)\">\n            </mj-tab-nav>\n        </div>\n    </mj-page-header-interior>\n\n    <div class=\"mj-inspector__content\">\n        <div class=\"mj-inspector__content-head\">\n            <h4 class=\"mj-inspector__content-title\">{{ SectionLabel }}</h4>\n            <span class=\"mj-inspector__content-meta\">Refreshed {{ LastRefreshedLabel }}</span>\n        </div>\n        <div class=\"mj-inspector__editor\">\n            <mj-code-editor\n                [(ngModel)]=\"StateJson\"\n                [language]=\"'json'\"\n                [readonly]=\"true\"\n                [lineWrapping]=\"true\">\n            </mj-code-editor>\n        </div>\n    </div>\n</div>\n", styles: [":host { display: block; height: 100%; }\n\n/*\n  Inspector shell \u2014 each Dev Tools sub-page wraps its body in .mj-inspector. The\n  chrome (title icon, title, subtitle, action buttons) was previously rendered\n  via .mj-inspector__header*, but that's been replaced by <mj-page-header-interior>\n  in every inspector template. Action buttons now use the mjButton directive\n  (variant=\"secondary\" / \"success\") so they inherit global button styling. App\n  State + Layout inspectors used to carry an inner left rail (.mj-inspector__body\n  + __sidebar + __nav-item) for L2 sections; that rail was retired 2026-05-19 in\n  favor of <mj-tab-nav> projected into the chrome's [toolbar] slot, matching\n  SystemDiagnostics and the API Keys tab strip. All inspectors are now \"solo\"\n  mode (no sidebar).\n*/\n.mj-inspector {\n    display: flex;\n    flex-direction: column;\n    height: 100%;\n    min-height: 0;\n    background: var(--mj-bg-page);\n    color: var(--mj-text-primary);\n    font-family: inherit;\n}\n\n/* Content area */\n.mj-inspector__content {\n    flex: 1;\n    min-width: 0;\n    display: flex;\n    flex-direction: column;\n    background: var(--mj-bg-page);\n}\n.mj-inspector__content-head {\n    padding: 12px 20px;\n    border-bottom: 1px solid var(--mj-border-subtle);\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    background: var(--mj-bg-surface-card);\n}\n.mj-inspector__content-title {\n    margin: 0;\n    font-size: 13px;\n    font-weight: 600;\n    color: var(--mj-text-primary);\n}\n.mj-inspector__content-meta {\n    font-size: 11px;\n    color: var(--mj-text-muted);\n}\n.mj-inspector__editor {\n    flex: 1;\n    min-height: 0;\n    display: flex;\n    flex-direction: column;\n    overflow: hidden;\n}\n.mj-inspector__editor mj-code-editor {\n    flex: 1;\n    min-height: 0;\n    display: block;\n}\n\n/* Empty state */\n.mj-inspector__empty {\n    flex: 1;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    color: var(--mj-text-muted);\n    font-size: 13px;\n}\n\n"] }]
    }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.WorkspaceStateManager }, { type: i2.DeveloperModeService }], null); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AppStateInspectorComponent, { className: "AppStateInspectorComponent", filePath: "src/DevTools/app-state-inspector.component.ts", lineNumber: 31 }); })();
//# sourceMappingURL=app-state-inspector.component.js.map