/**
 * @fileoverview Error Analysis -- Basic.
 *
 * Displays error summary cards, and errors grouped by source (Prompt+Model combination).
 * Each group can be expanded to show individual error details.
 * Data loaded from MJ: AI Prompt Runs where Success=false.
 */
import { Component, Input, ChangeDetectorRef, inject } from '@angular/core';
import { Subject } from 'rxjs';
import { RunView } from '@memberjunction/core';
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
import * as i0 from "@angular/core";
import * as i1 from "@memberjunction/ng-shared-generic";
import * as i2 from "@memberjunction/ng-ui-components";
import * as i3 from "@angular/common";
const _forTrack0 = ($index, $item) => $item.Source;
const _forTrack1 = ($index, $item) => $item.ID;
function AnalyticsErrorAnalysisComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 0);
    i0.ɵɵelement(1, "mj-loading", 1);
    i0.ɵɵelementEnd();
} }
function AnalyticsErrorAnalysisComponent_Conditional_1_Conditional_27_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "mj-empty-state", 15);
} }
function AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_1_Conditional_16_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 30)(1, "span", 31);
    i0.ɵɵtext(2, "Last error:");
    i0.ɵɵelementEnd();
    i0.ɵɵtext(3);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const group_r2 = i0.ɵɵnextContext(2).$implicit;
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate1(" ", group_r2.LastErrorMessage, " ");
} }
function AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_1_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 20)(1, "div", 21)(2, "div", 22);
    i0.ɵɵtext(3);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "div", 23)(5, "span", 24);
    i0.ɵɵtext(6);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(7, "span", 25);
    i0.ɵɵtext(8, "+");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(9, "span", 26);
    i0.ɵɵtext(10);
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(11, "div", 27)(12, "span", 28);
    i0.ɵɵtext(13);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(14, "div", 29);
    i0.ɵɵtext(15);
    i0.ɵɵelementEnd()()();
    i0.ɵɵconditionalCreate(16, AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_1_Conditional_16_Template, 4, 1, "div", 30);
} if (rf & 2) {
    const group_r2 = i0.ɵɵnextContext().$implicit;
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(group_r2.Source);
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(group_r2.PromptName);
    i0.ɵɵadvance(4);
    i0.ɵɵtextInterpolate(group_r2.ModelName);
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(group_r2.Count);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(group_r2.LastErrorTime);
    i0.ɵɵadvance();
    i0.ɵɵconditional(!group_r2.IsExpanded ? 16 : -1);
} }
function AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_2_For_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "span", 36);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const err_r4 = i0.ɵɵnextContext().$implicit;
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(err_r4.Duration);
} }
function AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_2_For_2_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 33)(1, "div", 34)(2, "span", 35);
    i0.ɵɵtext(3);
    i0.ɵɵelementEnd();
    i0.ɵɵconditionalCreate(4, AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_2_For_2_Conditional_4_Template, 2, 1, "span", 36);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "div", 37);
    i0.ɵɵtext(6);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const err_r4 = ctx.$implicit;
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(err_r4.Time);
    i0.ɵɵadvance();
    i0.ɵɵconditional(err_r4.Duration ? 4 : -1);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(err_r4.ErrorMessage);
} }
function AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_2_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 32);
    i0.ɵɵrepeaterCreate(1, AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_2_For_2_Template, 7, 3, "div", 33, _forTrack1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const group_r2 = i0.ɵɵnextContext().$implicit;
    i0.ɵɵadvance();
    i0.ɵɵrepeater(group_r2.Errors);
} }
function AnalyticsErrorAnalysisComponent_Conditional_1_For_29_Template(rf, ctx) { if (rf & 1) {
    const _r1 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "mj-accordion-panel", 17);
    i0.ɵɵlistener("ExpandedChange", function AnalyticsErrorAnalysisComponent_Conditional_1_For_29_Template_mj_accordion_panel_ExpandedChange_0_listener($event) { const group_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onGroupExpandedChange(group_r2, $event)); });
    i0.ɵɵtemplate(1, AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_1_Template, 17, 6, "ng-template", 18)(2, AnalyticsErrorAnalysisComponent_Conditional_1_For_29_ng_template_2_Template, 3, 0, "ng-template", 19);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const group_r2 = ctx.$implicit;
    i0.ɵɵproperty("FlushBody", true)("Expanded", group_r2.IsExpanded);
} }
function AnalyticsErrorAnalysisComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 2)(1, "div", 3)(2, "div", 4);
    i0.ɵɵelement(3, "i", 5);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "div", 6)(5, "div", 7);
    i0.ɵɵtext(6, "Total Errors");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(7, "div", 8);
    i0.ɵɵtext(8);
    i0.ɵɵpipe(9, "number");
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(10, "div", 9)(11, "div", 10);
    i0.ɵɵelement(12, "i", 11);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(13, "div", 6)(14, "div", 7);
    i0.ɵɵtext(15, "Error Rate");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(16, "div", 8);
    i0.ɵɵtext(17);
    i0.ɵɵpipe(18, "number");
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(19, "div", 9)(20, "div", 12);
    i0.ɵɵelement(21, "i", 13);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(22, "div", 6)(23, "div", 7);
    i0.ɵɵtext(24, "Most Common");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(25, "div", 14);
    i0.ɵɵtext(26);
    i0.ɵɵelementEnd()()()();
    i0.ɵɵconditionalCreate(27, AnalyticsErrorAnalysisComponent_Conditional_1_Conditional_27_Template, 1, 0, "mj-empty-state", 15);
    i0.ɵɵrepeaterCreate(28, AnalyticsErrorAnalysisComponent_Conditional_1_For_29_Template, 3, 2, "mj-accordion-panel", 16, _forTrack0);
} if (rf & 2) {
    const ctx_r2 = i0.ɵɵnextContext();
    i0.ɵɵadvance(8);
    i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(9, 5, ctx_r2.Summary.TotalErrors));
    i0.ɵɵadvance(9);
    i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(18, 7, ctx_r2.Summary.ErrorRate, "1.1-1"), "%");
    i0.ɵɵadvance(8);
    i0.ɵɵproperty("title", ctx_r2.Summary.MostCommonError);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1(" ", ctx_r2.Summary.MostCommonError || "N/A", " ");
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r2.ErrorGroups.length === 0 ? 27 : -1);
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r2.ErrorGroups);
} }
const FIELDS = [
    'ID', 'RunAt', 'ErrorMessage', 'Model', 'Prompt',
    'Vendor', 'ExecutionTimeMS', 'Status'
];
export class AnalyticsErrorAnalysisComponent extends BaseAngularComponent {
    _timeRange = '7d';
    set TimeRange(value) {
        const prev = this._timeRange;
        this._timeRange = value;
        if (prev !== value && this.initialized)
            this.LoadData();
    }
    get TimeRange() { return this._timeRange; }
    _filters = { Models: [], Agents: [], Prompts: [], Statuses: [] };
    set Filters(value) {
        const next = value ?? { Models: [], Agents: [], Prompts: [], Statuses: [] };
        const changed = !this.shallowFiltersEqual(this._filters, next);
        this._filters = next;
        if (changed && this.initialized)
            this.LoadData();
    }
    get Filters() { return this._filters; }
    shallowFiltersEqual(a, b) {
        const sameArr = (x, y) => x.length === y.length && x.every((v, i) => v === y[i]);
        return sameArr(a.Models, b.Models) && sameArr(a.Agents, b.Agents) && sameArr(a.Prompts, b.Prompts) && sameArr(a.Statuses, b.Statuses);
    }
    cdr = inject(ChangeDetectorRef);
    destroy$ = new Subject();
    initialized = false;
    IsLoading = false;
    Summary = {
        TotalErrors: 0,
        ErrorRate: 0,
        MostCommonError: ''
    };
    ErrorGroups = [];
    failedRuns = [];
    totalRunCount = 0;
    ngOnInit() {
        this.initialized = true;
        this.LoadData();
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
    }
    // ── Public Handlers ──
    OnTimeRangeChange(range) {
        this.TimeRange = range;
        this.LoadData();
    }
    OnFiltersChange(filters) {
        this.Filters = filters;
        this.LoadData();
    }
    /** Accordion-driven handler — SETS the emitted expanded value (vs. a flip),
     *  preserving the detectChanges() side-effect and keeping IsExpanded in sync
     *  so the collapsed-only "last error" preview shows/hides correctly. */
    onGroupExpandedChange(group, expanded) {
        group.IsExpanded = expanded;
        this.cdr.detectChanges();
    }
    // ── Data Loading ──
    async LoadData() {
        this.IsLoading = true;
        this.cdr.detectChanges();
        try {
            const rv = RunView.FromMetadataProvider(this.ProviderToUse);
            const dateFilter = this.buildDateFilter();
            const extraFilters = this.buildExtraFilters();
            const baseFilter = [dateFilter, ...extraFilters].filter(Boolean).join(' AND ');
            const errorFilter = baseFilter + ' AND Success = 0';
            const [errorResult, totalResult] = await rv.RunViews([
                {
                    EntityName: 'MJ: AI Prompt Runs',
                    ExtraFilter: errorFilter,
                    Fields: FIELDS,
                    OrderBy: 'RunAt DESC',
                    ResultType: 'simple'
                },
                {
                    EntityName: 'MJ: AI Prompt Runs',
                    ExtraFilter: baseFilter,
                    Fields: ['ID'],
                    ResultType: 'simple'
                }
            ]);
            this.failedRuns = (errorResult?.Results ?? []);
            this.totalRunCount = totalResult?.Results?.length ?? 0;
            this.computeSummary();
            this.buildErrorGroups();
        }
        catch (e) {
            console.error('Error Analysis load error:', e);
        }
        finally {
            this.IsLoading = false;
            this.cdr.detectChanges();
        }
    }
    // ── Computations ──
    computeSummary() {
        const errorCount = this.failedRuns.length;
        const errorRate = this.totalRunCount > 0 ? (errorCount / this.totalRunCount) * 100 : 0;
        // Find most common error by grouping error messages
        const messageCounts = new Map();
        for (const run of this.failedRuns) {
            const msg = this.normalizeErrorMessage(run.ErrorMessage ?? 'Unknown error');
            messageCounts.set(msg, (messageCounts.get(msg) ?? 0) + 1);
        }
        let mostCommon = '';
        let maxCount = 0;
        for (const [msg, count] of messageCounts) {
            if (count > maxCount) {
                maxCount = count;
                mostCommon = msg;
            }
        }
        this.Summary = {
            TotalErrors: errorCount,
            ErrorRate: errorRate,
            MostCommonError: mostCommon
        };
    }
    buildErrorGroups() {
        const groups = new Map();
        for (const run of this.failedRuns) {
            const prompt = run.Prompt ?? 'Unknown Prompt';
            const model = run.Model ?? 'Unknown Model';
            const key = prompt + ' + ' + model;
            if (!groups.has(key))
                groups.set(key, []);
            groups.get(key).push(run);
        }
        this.ErrorGroups = Array.from(groups.entries())
            .map(([source, runs]) => {
            const sortedRuns = runs.sort((a, b) => new Date(b.RunAt).getTime() - new Date(a.RunAt).getTime());
            return {
                Source: source,
                PromptName: sortedRuns[0].Prompt ?? 'Unknown',
                ModelName: sortedRuns[0].Model ?? 'Unknown',
                Count: sortedRuns.length,
                LastErrorMessage: this.truncateMessage(sortedRuns[0].ErrorMessage ?? 'No message'),
                LastErrorTime: this.formatRelativeTime(sortedRuns[0].RunAt),
                IsExpanded: false,
                Errors: sortedRuns.slice(0, 20).map(r => ({
                    ID: r.ID,
                    Time: this.formatDateTime(r.RunAt),
                    ErrorMessage: r.ErrorMessage ?? 'No error message',
                    Duration: r.ExecutionTimeMS != null ? r.ExecutionTimeMS + 'ms' : ''
                }))
            };
        })
            .sort((a, b) => b.Count - a.Count);
    }
    // ── Helpers ──
    buildDateFilter() {
        const now = new Date();
        const msMap = {
            '1h': 3600000, '6h': 21600000, '24h': 86400000,
            '7d': 604800000, '30d': 2592000000
        };
        const ms = msMap[this.TimeRange] ?? 604800000;
        const start = new Date(now.getTime() - ms);
        return `RunAt >= '${start.toISOString()}'`;
    }
    buildExtraFilters() {
        const filters = [];
        if (this.Filters.Models.length > 0) {
            filters.push(`ModelID IN (${this.Filters.Models.map(id => `'${id}'`).join(',')})`);
        }
        if (this.Filters.Prompts.length > 0) {
            filters.push(`PromptID IN (${this.Filters.Prompts.map(id => `'${id}'`).join(',')})`);
        }
        return filters;
    }
    normalizeErrorMessage(msg) {
        // Truncate and normalize for grouping
        return msg.slice(0, 100).trim().toLowerCase();
    }
    truncateMessage(msg) {
        if (msg.length <= 120)
            return msg;
        return msg.slice(0, 120) + '...';
    }
    formatRelativeTime(dateStr) {
        const now = Date.now();
        const then = new Date(dateStr).getTime();
        const diffMin = Math.floor((now - then) / 60000);
        if (diffMin < 1)
            return 'just now';
        if (diffMin < 60)
            return diffMin + 'm ago';
        const diffHr = Math.floor(diffMin / 60);
        if (diffHr < 24)
            return diffHr + 'h ago';
        const diffDay = Math.floor(diffHr / 24);
        return diffDay + 'd ago';
    }
    formatDateTime(dateStr) {
        const d = new Date(dateStr);
        const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
        const hh = d.getHours().toString().padStart(2, '0');
        const mm = d.getMinutes().toString().padStart(2, '0');
        return `${months[d.getMonth()]} ${d.getDate()} ${hh}:${mm}`;
    }
    static ɵfac = /*@__PURE__*/ (() => { let ɵAnalyticsErrorAnalysisComponent_BaseFactory; return function AnalyticsErrorAnalysisComponent_Factory(__ngFactoryType__) { return (ɵAnalyticsErrorAnalysisComponent_BaseFactory || (ɵAnalyticsErrorAnalysisComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AnalyticsErrorAnalysisComponent)))(__ngFactoryType__ || AnalyticsErrorAnalysisComponent); }; })();
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AnalyticsErrorAnalysisComponent, selectors: [["app-analytics-error-analysis"]], inputs: { TimeRange: "TimeRange", Filters: "Filters" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "loading-container"], ["text", "Loading error data..."], [1, "summary-row"], [1, "summary-card", "summary-card--error"], [1, "summary-icon"], [1, "fa-solid", "fa-circle-exclamation"], [1, "summary-content"], [1, "summary-label"], [1, "summary-value"], [1, "summary-card"], [1, "summary-icon", "summary-icon--warning"], [1, "fa-solid", "fa-percentage"], [1, "summary-icon", "summary-icon--info"], [1, "fa-solid", "fa-bug"], [1, "summary-value", "summary-value--text", 3, "title"], ["Variant", "success", "Title", "No Errors Found", "Message", "No errors detected in the selected time range."], ["Size", "sm", 3, "FlushBody", "Expanded"], ["Size", "sm", 3, "ExpandedChange", "FlushBody", "Expanded"], ["mjAccordionTitle", ""], ["mjAccordionBody", ""], [1, "error-group__title-row"], [1, "error-group__source"], [1, "source-name"], [1, "source-details"], [1, "source-prompt"], [1, "source-separator"], [1, "source-model"], [1, "error-group__right"], [1, "mj-accordion-badge", "mj-accordion-badge--error"], [1, "last-error-time"], [1, "error-group__preview"], [1, "preview-label"], [1, "error-group__body"], [1, "error-detail"], [1, "error-detail__header"], [1, "error-detail__time"], [1, "error-detail__duration"], [1, "error-detail__message"]], template: function AnalyticsErrorAnalysisComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵconditionalCreate(0, AnalyticsErrorAnalysisComponent_Conditional_0_Template, 2, 0, "div", 0)(1, AnalyticsErrorAnalysisComponent_Conditional_1_Template, 30, 10);
        } if (rf & 2) {
            i0.ɵɵconditional(ctx.IsLoading ? 0 : 1);
        } }, dependencies: [i1.LoadingComponent, i2.MJEmptyStateComponent, i2.MJAccordionPanelComponent, i2.MJAccordionTitleDirective, i2.MJAccordionBodyDirective, i3.DecimalPipe], styles: ["[_nghost-%COMP%] { display: block; }\n\n        .loading-container[_ngcontent-%COMP%] {\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            min-height: 300px;\n        }\n\n        \n\n        .summary-row[_ngcontent-%COMP%] {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n            gap: 12px;\n            margin: 16px 0;\n        }\n\n        .summary-card[_ngcontent-%COMP%] {\n            background: var(--mj-bg-surface);\n            border: 1px solid var(--mj-border-default);\n            border-radius: 10px;\n            padding: 16px;\n            display: flex;\n            align-items: center;\n            gap: 14px;\n        }\n\n        .summary-card--error[_ngcontent-%COMP%] {\n            border-left: 4px solid var(--mj-status-error);\n        }\n\n        .summary-icon[_ngcontent-%COMP%] {\n            width: 40px;\n            height: 40px;\n            border-radius: 10px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n            color: var(--mj-status-error);\n            font-size: 16px;\n            flex-shrink: 0;\n        }\n\n        .summary-icon--warning[_ngcontent-%COMP%] {\n            background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n            color: var(--mj-status-warning);\n        }\n\n        .summary-icon--info[_ngcontent-%COMP%] {\n            background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n            color: var(--mj-brand-primary);\n        }\n\n        .summary-label[_ngcontent-%COMP%] {\n            font-size: 11px;\n            font-weight: 600;\n            color: var(--mj-text-muted);\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n        }\n\n        .summary-value[_ngcontent-%COMP%] {\n            font-size: 22px;\n            font-weight: 700;\n            color: var(--mj-text-primary);\n            letter-spacing: -0.02em;\n        }\n\n        .summary-value--text[_ngcontent-%COMP%] {\n            font-size: 13px;\n            font-weight: 500;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            max-width: 220px;\n        }\n\n        \n\n        \n\n\n\n\n\n\n        mj-accordion-panel[_ngcontent-%COMP%] {\n            display: block;\n            margin-bottom: 8px;\n        }\n\n        \n\n        .error-group__title-row[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            gap: 12px;\n            width: 100%;\n        }\n\n        .error-group__source[_ngcontent-%COMP%] {\n            flex: 1;\n            min-width: 0;\n        }\n\n        .source-name[_ngcontent-%COMP%] {\n            font-size: 14px;\n            font-weight: 600;\n            color: var(--mj-text-primary);\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n        }\n\n        .source-details[_ngcontent-%COMP%] {\n            font-size: 12px;\n            color: var(--mj-text-muted);\n            display: flex;\n            align-items: center;\n            gap: 4px;\n            margin-top: 2px;\n        }\n\n        .source-separator[_ngcontent-%COMP%] {\n            color: var(--mj-text-disabled);\n        }\n\n        .error-group__right[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: center;\n            gap: 12px;\n            flex-shrink: 0;\n        }\n\n        \n\n\n\n        .last-error-time[_ngcontent-%COMP%] {\n            font-size: 12px;\n            color: var(--mj-text-disabled);\n            white-space: nowrap;\n        }\n\n        \n\n\n        .error-group__preview[_ngcontent-%COMP%] {\n            margin-top: 6px;\n            font-size: 12px;\n            color: var(--mj-text-muted);\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n        }\n\n        .preview-label[_ngcontent-%COMP%] {\n            color: var(--mj-text-disabled);\n            margin-right: 4px;\n        }\n\n        \n\n\n        .error-group__body[_ngcontent-%COMP%] {\n            max-height: 400px;\n            overflow-y: auto;\n        }\n\n        .error-detail[_ngcontent-%COMP%] {\n            padding: 12px 16px;\n            border-bottom: 1px solid var(--mj-border-subtle);\n        }\n\n        .error-detail[_ngcontent-%COMP%]:last-child {\n            border-bottom: none;\n        }\n\n        .error-detail__header[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: center;\n            gap: 10px;\n            margin-bottom: 4px;\n        }\n\n        .error-detail__time[_ngcontent-%COMP%] {\n            font-size: 11px;\n            font-weight: 600;\n            color: var(--mj-text-muted);\n        }\n\n        .error-detail__duration[_ngcontent-%COMP%] {\n            font-size: 11px;\n            color: var(--mj-text-disabled);\n            font-variant-numeric: tabular-nums;\n        }\n\n        .error-detail__message[_ngcontent-%COMP%] {\n            font-size: 13px;\n            color: var(--mj-status-error-text, var(--mj-status-error));\n            line-height: 1.5;\n            word-break: break-word;\n            font-family: monospace;\n            background: color-mix(in srgb, var(--mj-status-error) 5%, var(--mj-bg-surface));\n            padding: 8px 10px;\n            border-radius: 6px;\n            border: 1px solid color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n        }\n\n        \n\n        @media (max-width: 768px) {\n            .summary-row[_ngcontent-%COMP%] {\n                grid-template-columns: 1fr;\n            }\n\n            .summary-value[_ngcontent-%COMP%] {\n                font-size: 18px;\n            }\n        }"] });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AnalyticsErrorAnalysisComponent, [{
        type: Component,
        args: [{ standalone: false, selector: 'app-analytics-error-analysis', template: `

        @if (IsLoading) {
            <div class="loading-container">
                <mj-loading text="Loading error data..."></mj-loading>
            </div>
        } @else {
            <!-- Summary Cards -->
            <div class="summary-row">
                <div class="summary-card summary-card--error">
                    <div class="summary-icon">
                        <i class="fa-solid fa-circle-exclamation"></i>
                    </div>
                    <div class="summary-content">
                        <div class="summary-label">Total Errors</div>
                        <div class="summary-value">{{ Summary.TotalErrors | number }}</div>
                    </div>
                </div>
                <div class="summary-card">
                    <div class="summary-icon summary-icon--warning">
                        <i class="fa-solid fa-percentage"></i>
                    </div>
                    <div class="summary-content">
                        <div class="summary-label">Error Rate</div>
                        <div class="summary-value">{{ Summary.ErrorRate | number:'1.1-1' }}%</div>
                    </div>
                </div>
                <div class="summary-card">
                    <div class="summary-icon summary-icon--info">
                        <i class="fa-solid fa-bug"></i>
                    </div>
                    <div class="summary-content">
                        <div class="summary-label">Most Common</div>
                        <div class="summary-value summary-value--text" [title]="Summary.MostCommonError">
                            {{ Summary.MostCommonError || 'N/A' }}
                        </div>
                    </div>
                </div>
            </div>

            <!-- Error Groups -->
            @if (ErrorGroups.length === 0) {
                <mj-empty-state Variant="success"
                    Title="No Errors Found"
                    Message="No errors detected in the selected time range." />
            }

            @for (group of ErrorGroups; track group.Source) {
                <mj-accordion-panel Size="sm" [FlushBody]="true"
                    [Expanded]="group.IsExpanded"
                    (ExpandedChange)="onGroupExpandedChange(group, $event)">
                    <ng-template mjAccordionTitle>
                        <div class="error-group__title-row">
                            <div class="error-group__source">
                                <div class="source-name">{{ group.Source }}</div>
                                <div class="source-details">
                                    <span class="source-prompt">{{ group.PromptName }}</span>
                                    <span class="source-separator">+</span>
                                    <span class="source-model">{{ group.ModelName }}</span>
                                </div>
                            </div>
                            <div class="error-group__right">
                                <span class="mj-accordion-badge mj-accordion-badge--error">{{ group.Count }}</span>
                                <div class="last-error-time">{{ group.LastErrorTime }}</div>
                            </div>
                        </div>
                        <!-- Collapsed-preview wrinkle: the "last error" preview lives in the
                             title slot (gated on !IsExpanded) so it shows while collapsed,
                             and the full error list lives in the body. -->
                        @if (!group.IsExpanded) {
                            <div class="error-group__preview">
                                <span class="preview-label">Last error:</span>
                                {{ group.LastErrorMessage }}
                            </div>
                        }
                    </ng-template>
                    <ng-template mjAccordionBody>
                        <div class="error-group__body">
                            @for (err of group.Errors; track err.ID) {
                                <div class="error-detail">
                                    <div class="error-detail__header">
                                        <span class="error-detail__time">{{ err.Time }}</span>
                                        @if (err.Duration) {
                                            <span class="error-detail__duration">{{ err.Duration }}</span>
                                        }
                                    </div>
                                    <div class="error-detail__message">{{ err.ErrorMessage }}</div>
                                </div>
                            }
                        </div>
                    </ng-template>
                </mj-accordion-panel>
            }
        }
    `, styles: ["\n        :host { display: block; }\n\n        .loading-container {\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            min-height: 300px;\n        }\n\n        /* \u2500\u2500 Summary Row \u2500\u2500 */\n        .summary-row {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n            gap: 12px;\n            margin: 16px 0;\n        }\n\n        .summary-card {\n            background: var(--mj-bg-surface);\n            border: 1px solid var(--mj-border-default);\n            border-radius: 10px;\n            padding: 16px;\n            display: flex;\n            align-items: center;\n            gap: 14px;\n        }\n\n        .summary-card--error {\n            border-left: 4px solid var(--mj-status-error);\n        }\n\n        .summary-icon {\n            width: 40px;\n            height: 40px;\n            border-radius: 10px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n            color: var(--mj-status-error);\n            font-size: 16px;\n            flex-shrink: 0;\n        }\n\n        .summary-icon--warning {\n            background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n            color: var(--mj-status-warning);\n        }\n\n        .summary-icon--info {\n            background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n            color: var(--mj-brand-primary);\n        }\n\n        .summary-label {\n            font-size: 11px;\n            font-weight: 600;\n            color: var(--mj-text-muted);\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n        }\n\n        .summary-value {\n            font-size: 22px;\n            font-weight: 700;\n            color: var(--mj-text-primary);\n            letter-spacing: -0.02em;\n        }\n\n        .summary-value--text {\n            font-size: 13px;\n            font-weight: 500;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            max-width: 220px;\n        }\n\n        /* \u2500\u2500 Error Groups \u2500\u2500 */\n        /* Each group is now an <mj-accordion-panel>; it owns the card chrome,\n           header row, hover, chevron, and expanded state. We only space the\n           panels apart here. The removed bespoke blocks (.error-group wrapper\n           chrome, .error-group--expanded border, .error-group__header + :hover,\n           .error-group__left, .expand-icon chevron) are gone \u2014 the accordion\n           provides all of that. */\n        mj-accordion-panel {\n            display: block;\n            margin-bottom: 8px;\n        }\n\n        /* Title-slot layout: source info on the left, badge + time on the right. */\n        .error-group__title-row {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            gap: 12px;\n            width: 100%;\n        }\n\n        .error-group__source {\n            flex: 1;\n            min-width: 0;\n        }\n\n        .source-name {\n            font-size: 14px;\n            font-weight: 600;\n            color: var(--mj-text-primary);\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n        }\n\n        .source-details {\n            font-size: 12px;\n            color: var(--mj-text-muted);\n            display: flex;\n            align-items: center;\n            gap: 4px;\n            margin-top: 2px;\n        }\n\n        .source-separator {\n            color: var(--mj-text-disabled);\n        }\n\n        .error-group__right {\n            display: flex;\n            align-items: center;\n            gap: 12px;\n            flex-shrink: 0;\n        }\n\n        /* Count pill now uses the canonical .mj-accordion-badge--error (token-driven,\n           dark-mode-safe) \u2014 the bespoke .error-count-badge rule was deleted. */\n\n        .last-error-time {\n            font-size: 12px;\n            color: var(--mj-text-disabled);\n            white-space: nowrap;\n        }\n\n        /* Preview now renders inside the accordion title slot (already indented),\n           so it only needs a little top separation from the title row. */\n        .error-group__preview {\n            margin-top: 6px;\n            font-size: 12px;\n            color: var(--mj-text-muted);\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n        }\n\n        .preview-label {\n            color: var(--mj-text-disabled);\n            margin-right: 4px;\n        }\n\n        /* Body is rendered flush ([FlushBody]); it manages its own scroll/padding.\n           No body-hiding/collapse rule needed \u2014 the accordion owns expand/collapse. */\n        .error-group__body {\n            max-height: 400px;\n            overflow-y: auto;\n        }\n\n        .error-detail {\n            padding: 12px 16px;\n            border-bottom: 1px solid var(--mj-border-subtle);\n        }\n\n        .error-detail:last-child {\n            border-bottom: none;\n        }\n\n        .error-detail__header {\n            display: flex;\n            align-items: center;\n            gap: 10px;\n            margin-bottom: 4px;\n        }\n\n        .error-detail__time {\n            font-size: 11px;\n            font-weight: 600;\n            color: var(--mj-text-muted);\n        }\n\n        .error-detail__duration {\n            font-size: 11px;\n            color: var(--mj-text-disabled);\n            font-variant-numeric: tabular-nums;\n        }\n\n        .error-detail__message {\n            font-size: 13px;\n            color: var(--mj-status-error-text, var(--mj-status-error));\n            line-height: 1.5;\n            word-break: break-word;\n            font-family: monospace;\n            background: color-mix(in srgb, var(--mj-status-error) 5%, var(--mj-bg-surface));\n            padding: 8px 10px;\n            border-radius: 6px;\n            border: 1px solid color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n        }\n\n        /* \u2500\u2500 Responsive \u2500\u2500 */\n        @media (max-width: 768px) {\n            .summary-row {\n                grid-template-columns: 1fr;\n            }\n\n            .summary-value {\n                font-size: 18px;\n            }\n        }\n    "] }]
    }], null, { TimeRange: [{
            type: Input
        }], Filters: [{
            type: Input
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AnalyticsErrorAnalysisComponent, { className: "AnalyticsErrorAnalysisComponent", filePath: "src/AI/components/analytics/error-analysis/error-analysis.component.ts", lineNumber: 376 }); })();
export function LoadAnalyticsErrorAnalysis() { }
//# sourceMappingURL=error-analysis.component.js.map