/**
 * @fileoverview Model Performance Leaderboard.
 *
 * Ranks AI models by configurable metrics (Cost Efficiency, Speed, Reliability, Usage Volume).
 * Data is loaded from MJ: AI Prompt Runs and augmented with model metadata from AIEngineBase.
 */
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 { UUIDsEqual } from '@memberjunction/global';
import { AIEngineBase } from '@memberjunction/ai-engine-base';
import * as i0 from "@angular/core";
import * as i1 from "@memberjunction/ng-shared-generic";
import * as i2 from "@angular/common";
const _forTrack0 = ($index, $item) => $item.ModelName;
function AnalyticsModelPerformanceComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 0);
    i0.ɵɵelement(1, "mj-loading", 2);
    i0.ɵɵelementEnd();
} }
function AnalyticsModelPerformanceComponent_Conditional_1_Conditional_26_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "tr")(1, "td", 11);
    i0.ɵɵtext(2, "No model data for selected period");
    i0.ɵɵelementEnd()();
} }
function AnalyticsModelPerformanceComponent_Conditional_1_For_28_Conditional_7_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 15);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const row_r1 = i0.ɵɵnextContext().$implicit;
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(row_r1.ApiId);
} }
function AnalyticsModelPerformanceComponent_Conditional_1_For_28_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "tr")(1, "td")(2, "span", 12);
    i0.ɵɵtext(3);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(4, "td", 13)(5, "div", 14);
    i0.ɵɵtext(6);
    i0.ɵɵelementEnd();
    i0.ɵɵconditionalCreate(7, AnalyticsModelPerformanceComponent_Conditional_1_For_28_Conditional_7_Template, 2, 1, "div", 15);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(8, "td", 16);
    i0.ɵɵtext(9);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(10, "td", 17);
    i0.ɵɵtext(11);
    i0.ɵɵpipe(12, "number");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(13, "td", 17)(14, "span");
    i0.ɵɵtext(15);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(16, "td", 17);
    i0.ɵɵtext(17);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(18, "td", 17)(19, "div", 18)(20, "span", 19);
    i0.ɵɵtext(21);
    i0.ɵɵpipe(22, "number");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(23, "div", 20);
    i0.ɵɵelement(24, "div", 21);
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(25, "td", 17);
    i0.ɵɵtext(26);
    i0.ɵɵpipe(27, "number");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(28, "td", 17);
    i0.ɵɵtext(29);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(30, "td", 22);
    i0.ɵɵtext(31);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const row_r1 = ctx.$implicit;
    const ctx_r1 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(2);
    i0.ɵɵclassMap(row_r1.RankClass);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1(" ", row_r1.Rank, " ");
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(row_r1.ModelName);
    i0.ɵɵadvance();
    i0.ɵɵconditional(row_r1.ApiId && row_r1.ApiId !== row_r1.ModelName ? 7 : -1);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(row_r1.Vendor);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(12, 17, row_r1.Runs));
    i0.ɵɵadvance(3);
    i0.ɵɵstyleProp("color", row_r1.AvgLatencyColor);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1(" ", ctx_r1.FormatLatency(row_r1.AvgLatencyMs), " ");
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r1.FormatLatency(row_r1.P95LatencyMs));
    i0.ɵɵadvance(4);
    i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(22, 19, row_r1.SuccessRate, "1.1-1"), "%");
    i0.ɵɵadvance(3);
    i0.ɵɵstyleProp("width", row_r1.SuccessRate, "%");
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(row_r1.CacheHitRate > 0 ? i0.ɵɵpipeBind2(27, 22, row_r1.CacheHitRate * 100, "1.0-0") + "%" : "\u2014");
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(ctx_r1.FormatCurrency(row_r1.CostPer1KTokens, 4));
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r1.FormatCurrency(row_r1.TotalCost));
} }
function AnalyticsModelPerformanceComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 1)(1, "div", 3)(2, "table", 4)(3, "thead")(4, "tr")(5, "th", 5);
    i0.ɵɵtext(6, "Rank");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(7, "th", 6);
    i0.ɵɵtext(8, "Model");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(9, "th", 7);
    i0.ɵɵtext(10, "Vendor");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(11, "th", 8);
    i0.ɵɵtext(12, "Runs");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(13, "th", 8);
    i0.ɵɵtext(14, "Avg Latency");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(15, "th", 8);
    i0.ɵɵtext(16, "P95 Latency");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(17, "th", 8);
    i0.ɵɵtext(18, "Success Rate");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(19, "th", 9);
    i0.ɵɵtext(20, "Cache Hit");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(21, "th", 10);
    i0.ɵɵtext(22, "$/1K Tokens");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(23, "th", 8);
    i0.ɵɵtext(24, "Total Cost");
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(25, "tbody");
    i0.ɵɵconditionalCreate(26, AnalyticsModelPerformanceComponent_Conditional_1_Conditional_26_Template, 3, 0, "tr");
    i0.ɵɵrepeaterCreate(27, AnalyticsModelPerformanceComponent_Conditional_1_For_28_Template, 32, 25, "tr", null, _forTrack0);
    i0.ɵɵelementEnd()()()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵadvance(26);
    i0.ɵɵconditional(ctx_r1.Rows.length === 0 ? 26 : -1);
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r1.Rows);
} }
const FIELDS = [
    'ID', 'RunAt', 'CompletedAt', 'ExecutionTimeMS', 'Success',
    'Cost', 'TotalCost', 'TokensUsed', 'TokensPrompt', 'TokensCompletion',
    'TokensCacheRead', 'TokensCacheWrite', 'ModelID', 'Model', 'VendorID', 'Vendor'
];
export class AnalyticsModelPerformanceComponent 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; }
    _sortBy = 'cost-efficiency';
    set SortBy(value) {
        const prev = this._sortBy;
        this._sortBy = (value || 'cost-efficiency');
        if (prev !== this._sortBy && this.initialized) {
            this.buildRows();
            this.cdr.markForCheck();
        }
    }
    get SortBy() { return this._sortBy; }
    _selectedVendor = '';
    set SelectedVendor(value) {
        const prev = this._selectedVendor;
        this._selectedVendor = value ?? '';
        if (prev !== this._selectedVendor && this.initialized) {
            this.buildRows();
            this.cdr.markForCheck();
        }
    }
    get SelectedVendor() { return this._selectedVendor; }
    cdr = inject(ChangeDetectorRef);
    destroy$ = new Subject();
    initialized = false;
    IsLoading = false;
    Rows = [];
    allRuns = [];
    async ngOnInit() {
        // AIEngineBase is deferred at startup — make sure it's loaded before
        // we read .Vendors / .Models from it.
        await AIEngineBase.Instance.EnsureLoaded();
        this.initialized = true;
        this.LoadData();
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
    }
    FormatLatency(ms) {
        if (ms < 1000)
            return Math.round(ms) + 'ms';
        return (ms / 1000).toFixed(2) + 's';
    }
    FormatCurrency(value, decimals = 2) {
        if (value === 0)
            return '$0.00';
        if (value < 0.01 && decimals < 4)
            decimals = 4;
        return '$' + value.toFixed(decimals);
    }
    // ── Data Loading ──
    async LoadData() {
        this.IsLoading = true;
        this.cdr.detectChanges();
        try {
            const rv = RunView.FromMetadataProvider(this.ProviderToUse);
            const dateFilter = this.buildDateFilter();
            const result = await rv.RunView({
                EntityName: 'MJ: AI Prompt Runs',
                ExtraFilter: dateFilter,
                Fields: FIELDS,
                OrderBy: 'RunAt DESC',
                ResultType: 'simple'
            });
            this.allRuns = (result?.Results ?? []);
            this.buildRows();
        }
        catch (e) {
            console.error('Model Performance load error:', e);
        }
        finally {
            this.IsLoading = false;
            this.cdr.detectChanges();
        }
    }
    // ── Row Building ──
    buildRows() {
        // Filter by vendor if needed
        let runs = this.allRuns;
        if (this.SelectedVendor) {
            runs = runs.filter(r => r.VendorID === this.SelectedVendor);
        }
        // Group by model
        const groups = new Map();
        for (const run of runs) {
            const key = run.ModelID ?? 'unknown';
            if (!groups.has(key))
                groups.set(key, []);
            groups.get(key).push(run);
        }
        // Compute metrics per model
        const modelRows = [];
        for (const [modelId, modelRuns] of groups) {
            const row = this.computeModelMetrics(modelId, modelRuns);
            modelRows.push(row);
        }
        // Sort by chosen metric
        this.sortRows(modelRows);
        // Assign ranks
        modelRows.forEach((row, i) => {
            row.Rank = i + 1;
            row.RankClass = this.getRankClass(i + 1);
        });
        this.Rows = modelRows;
    }
    computeModelMetrics(modelId, runs) {
        const totalRuns = runs.length;
        const successCount = runs.filter(r => r.Success).length;
        const successRate = totalRuns > 0 ? (successCount / totalRuns) * 100 : 0;
        const latencies = runs
            .filter(r => r.ExecutionTimeMS != null && r.ExecutionTimeMS > 0)
            .map(r => r.ExecutionTimeMS);
        const avgLatency = latencies.length > 0
            ? latencies.reduce((s, l) => s + l, 0) / latencies.length
            : 0;
        const p95Latency = this.computePercentile(latencies, 0.95);
        // Effective rate uses TOTAL tokens the model processed, including cache reads/writes — so a
        // model that caches heavily shows its true (lower) cost per token rather than dividing the
        // discounted cost by only the uncached tokens.
        const cacheRead = runs.reduce((s, r) => s + (r.TokensCacheRead ?? 0), 0);
        const cacheWrite = runs.reduce((s, r) => s + (r.TokensCacheWrite ?? 0), 0);
        const totalTokens = runs.reduce((s, r) => s + (r.TokensUsed ?? 0), 0) + cacheRead + cacheWrite;
        const totalCost = runs.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);
        const costPer1K = totalTokens > 0 ? (totalCost / totalTokens) * 1000 : 0;
        const inputForHit = runs.reduce((s, r) => s + (r.TokensPrompt ?? 0), 0) + cacheRead + cacheWrite;
        const cacheHitRate = inputForHit > 0 ? cacheRead / inputForHit : 0;
        const firstName = runs.find(r => r.Model != null);
        const firstVendor = runs.find(r => r.Vendor != null);
        // Look up model API name from engine
        let apiId = '';
        try {
            const model = AIEngineBase.Instance.Models.find(m => UUIDsEqual(m.ID, modelId));
            apiId = model?.APIName ?? '';
        }
        catch {
            // engine might not be ready
        }
        return {
            Rank: 0,
            RankClass: 'rank-neutral',
            ModelName: firstName?.Model ?? 'Unknown',
            ApiId: apiId,
            Vendor: firstVendor?.Vendor ?? 'Unknown',
            VendorID: firstVendor?.VendorID ?? '',
            Runs: totalRuns,
            AvgLatencyMs: avgLatency,
            AvgLatencyColor: this.getLatencyColor(avgLatency),
            P95LatencyMs: p95Latency,
            SuccessRate: successRate,
            CostPer1KTokens: costPer1K,
            CacheHitRate: cacheHitRate,
            TotalCost: totalCost
        };
    }
    sortRows(rows) {
        switch (this.SortBy) {
            case 'cost-efficiency':
                rows.sort((a, b) => a.CostPer1KTokens - b.CostPer1KTokens);
                break;
            case 'speed':
                rows.sort((a, b) => a.AvgLatencyMs - b.AvgLatencyMs);
                break;
            case 'reliability':
                rows.sort((a, b) => b.SuccessRate - a.SuccessRate);
                break;
            case 'usage-volume':
                rows.sort((a, b) => b.Runs - a.Runs);
                break;
        }
    }
    // ── Helpers ──
    computePercentile(sortedValues, percentile) {
        if (sortedValues.length === 0)
            return 0;
        const sorted = [...sortedValues].sort((a, b) => a - b);
        const idx = Math.ceil(sorted.length * percentile) - 1;
        return sorted[Math.max(0, idx)];
    }
    getRankClass(rank) {
        if (rank === 1)
            return 'rank-badge rank-gold';
        if (rank === 2)
            return 'rank-badge rank-silver';
        if (rank === 3)
            return 'rank-badge rank-bronze';
        return 'rank-badge rank-neutral';
    }
    getLatencyColor(ms) {
        if (ms < 1000)
            return 'var(--mj-status-success)';
        if (ms < 3000)
            return 'var(--mj-status-warning)';
        return 'var(--mj-status-error)';
    }
    buildDateFilter() {
        const now = new Date();
        const msMap = {
            '24h': 86400000,
            '7d': 604800000,
            '30d': 2592000000
        };
        const ms = msMap[this.TimeRange] ?? 604800000;
        const start = new Date(now.getTime() - ms);
        return `RunAt >= '${start.toISOString()}'`;
    }
    static ɵfac = /*@__PURE__*/ (() => { let ɵAnalyticsModelPerformanceComponent_BaseFactory; return function AnalyticsModelPerformanceComponent_Factory(__ngFactoryType__) { return (ɵAnalyticsModelPerformanceComponent_BaseFactory || (ɵAnalyticsModelPerformanceComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AnalyticsModelPerformanceComponent)))(__ngFactoryType__ || AnalyticsModelPerformanceComponent); }; })();
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AnalyticsModelPerformanceComponent, selectors: [["app-analytics-model-performance"]], inputs: { TimeRange: "TimeRange", SortBy: "SortBy", SelectedVendor: "SelectedVendor" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "loading-container"], [1, "leaderboard-panel"], ["text", "Loading model performance..."], [1, "table-wrapper"], [1, "leaderboard-table"], [1, "col-rank"], [1, "col-model"], [1, "col-vendor"], [1, "col-numeric"], ["title", "Share of input tokens served from the provider's prompt cache", 1, "col-numeric"], ["title", "Cost per 1K tokens processed, including cached tokens (effective rate)", 1, "col-numeric"], ["colspan", "10", 1, "empty-row"], [1, "rank-badge"], [1, "cell-model"], [1, "model-name"], [1, "model-api-id"], [1, "cell-vendor"], [1, "cell-numeric"], [1, "success-rate-cell"], [1, "success-rate-value"], [1, "success-bar-bg"], [1, "success-bar-fill"], [1, "cell-numeric", "cell-cost"]], template: function AnalyticsModelPerformanceComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵconditionalCreate(0, AnalyticsModelPerformanceComponent_Conditional_0_Template, 2, 0, "div", 0)(1, AnalyticsModelPerformanceComponent_Conditional_1_Template, 29, 1, "div", 1);
        } if (rf & 2) {
            i0.ɵɵconditional(ctx.IsLoading ? 0 : 1);
        } }, dependencies: [i1.LoadingComponent, i2.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        .leaderboard-panel[_ngcontent-%COMP%] {\n            background: var(--mj-bg-surface);\n            border: 1px solid var(--mj-border-default);\n            border-radius: 12px;\n            overflow: hidden;\n        }\n\n        .table-wrapper[_ngcontent-%COMP%] {\n            overflow-x: auto;\n        }\n\n        .leaderboard-table[_ngcontent-%COMP%] {\n            width: 100%;\n            border-collapse: collapse;\n            font-size: 13px;\n        }\n\n        .leaderboard-table[_ngcontent-%COMP%]   th[_ngcontent-%COMP%], \n   .leaderboard-table[_ngcontent-%COMP%]   td[_ngcontent-%COMP%] {\n            padding: 12px 14px;\n            text-align: left;\n            border-bottom: 1px solid var(--mj-border-subtle);\n        }\n\n        .leaderboard-table[_ngcontent-%COMP%]   th[_ngcontent-%COMP%] {\n            font-size: 11px;\n            font-weight: 600;\n            color: var(--mj-text-muted);\n            text-transform: uppercase;\n            letter-spacing: 0.4px;\n            background: var(--mj-bg-surface-card);\n            position: sticky;\n            top: 0;\n            white-space: nowrap;\n        }\n\n        .col-rank[_ngcontent-%COMP%] { width: 60px; text-align: center; }\n        .col-model[_ngcontent-%COMP%] { min-width: 180px; }\n        .col-vendor[_ngcontent-%COMP%] { min-width: 100px; }\n        .col-numeric[_ngcontent-%COMP%] { text-align: right; white-space: nowrap; }\n\n        .leaderboard-table[_ngcontent-%COMP%]   tbody[_ngcontent-%COMP%]   tr[_ngcontent-%COMP%] {\n            transition: background 0.15s;\n        }\n\n        .leaderboard-table[_ngcontent-%COMP%]   tbody[_ngcontent-%COMP%]   tr[_ngcontent-%COMP%]:hover {\n            background: var(--mj-bg-surface-hover);\n        }\n\n        .empty-row[_ngcontent-%COMP%] {\n            text-align: center;\n            color: var(--mj-text-disabled);\n            padding: 32px;\n        }\n\n        \n\n        .rank-badge[_ngcontent-%COMP%] {\n            display: inline-flex;\n            align-items: center;\n            justify-content: center;\n            width: 28px;\n            height: 28px;\n            border-radius: 50%;\n            font-size: 12px;\n            font-weight: 700;\n        }\n\n        .rank-gold[_ngcontent-%COMP%] {\n            background: linear-gradient(135deg, color-mix(in srgb, var(--mj-status-warning) 35%, var(--mj-bg-surface)), color-mix(in srgb, var(--mj-status-warning) 20%, var(--mj-bg-surface)));\n            color: var(--mj-status-warning-text, var(--mj-status-warning));\n            box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n        }\n\n        .rank-silver[_ngcontent-%COMP%] {\n            background: color-mix(in srgb, var(--mj-text-muted) 18%, var(--mj-bg-surface));\n            color: var(--mj-text-secondary);\n            box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-text-muted) 20%, transparent);\n        }\n\n        .rank-bronze[_ngcontent-%COMP%] {\n            background: color-mix(in srgb, var(--mj-status-warning) 18%, var(--mj-bg-surface));\n            color: var(--mj-text-secondary);\n        }\n\n        .rank-neutral[_ngcontent-%COMP%] {\n            background: var(--mj-bg-surface-sunken);\n            color: var(--mj-text-muted);\n        }\n\n        \n\n        .cell-model[_ngcontent-%COMP%] {\n            font-weight: 500;\n            color: var(--mj-text-primary);\n        }\n\n        .model-name[_ngcontent-%COMP%] {\n            font-weight: 600;\n        }\n\n        .model-api-id[_ngcontent-%COMP%] {\n            font-size: 11px;\n            color: var(--mj-text-muted);\n            margin-top: 2px;\n            font-family: monospace;\n        }\n\n        .cell-vendor[_ngcontent-%COMP%] {\n            color: var(--mj-text-secondary);\n        }\n\n        .cell-numeric[_ngcontent-%COMP%] {\n            text-align: right;\n            font-variant-numeric: tabular-nums;\n            color: var(--mj-text-secondary);\n        }\n\n        .cell-cost[_ngcontent-%COMP%] {\n            font-weight: 600;\n            color: var(--mj-text-primary);\n        }\n\n        \n\n        .success-rate-cell[_ngcontent-%COMP%] {\n            display: flex;\n            flex-direction: column;\n            align-items: flex-end;\n            gap: 3px;\n        }\n\n        .success-rate-value[_ngcontent-%COMP%] {\n            font-weight: 600;\n        }\n\n        .success-bar-bg[_ngcontent-%COMP%] {\n            width: 60px;\n            height: 4px;\n            background: var(--mj-bg-surface-sunken);\n            border-radius: 2px;\n            overflow: hidden;\n        }\n\n        .success-bar-fill[_ngcontent-%COMP%] {\n            height: 100%;\n            background: var(--mj-status-success);\n            border-radius: 2px;\n            transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n        }\n\n        \n\n        @media (max-width: 1200px) {\n            .leaderboard-table[_ngcontent-%COMP%]   th[_ngcontent-%COMP%], \n   .leaderboard-table[_ngcontent-%COMP%]   td[_ngcontent-%COMP%] {\n                padding: 10px 10px;\n            }\n        }"] });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AnalyticsModelPerformanceComponent, [{
        type: Component,
        args: [{ standalone: false, selector: 'app-analytics-model-performance', template: `
        @if (IsLoading) {
            <div class="loading-container">
                <mj-loading text="Loading model performance..."></mj-loading>
            </div>
        } @else {
            <!-- Leaderboard Table -->
            <div class="leaderboard-panel">
                <div class="table-wrapper">
                    <table class="leaderboard-table">
                        <thead>
                            <tr>
                                <th class="col-rank">Rank</th>
                                <th class="col-model">Model</th>
                                <th class="col-vendor">Vendor</th>
                                <th class="col-numeric">Runs</th>
                                <th class="col-numeric">Avg Latency</th>
                                <th class="col-numeric">P95 Latency</th>
                                <th class="col-numeric">Success Rate</th>
                                <th class="col-numeric" title="Share of input tokens served from the provider's prompt cache">Cache Hit</th>
                                <th class="col-numeric" title="Cost per 1K tokens processed, including cached tokens (effective rate)">$/1K Tokens</th>
                                <th class="col-numeric">Total Cost</th>
                            </tr>
                        </thead>
                        <tbody>
                            @if (Rows.length === 0) {
                                <tr><td colspan="10" class="empty-row">No model data for selected period</td></tr>
                            }
                            @for (row of Rows; track row.ModelName) {
                                <tr>
                                    <td>
                                        <span class="rank-badge" [class]="row.RankClass">
                                            {{ row.Rank }}
                                        </span>
                                    </td>
                                    <td class="cell-model">
                                        <div class="model-name">{{ row.ModelName }}</div>
                                        @if (row.ApiId && row.ApiId !== row.ModelName) {
                                            <div class="model-api-id">{{ row.ApiId }}</div>
                                        }
                                    </td>
                                    <td class="cell-vendor">{{ row.Vendor }}</td>
                                    <td class="cell-numeric">{{ row.Runs | number }}</td>
                                    <td class="cell-numeric">
                                        <span [style.color]="row.AvgLatencyColor">
                                            {{ FormatLatency(row.AvgLatencyMs) }}
                                        </span>
                                    </td>
                                    <td class="cell-numeric">{{ FormatLatency(row.P95LatencyMs) }}</td>
                                    <td class="cell-numeric">
                                        <div class="success-rate-cell">
                                            <span class="success-rate-value">{{ row.SuccessRate | number:'1.1-1' }}%</span>
                                            <div class="success-bar-bg">
                                                <div class="success-bar-fill" [style.width.%]="row.SuccessRate"></div>
                                            </div>
                                        </div>
                                    </td>
                                    <td class="cell-numeric">{{ row.CacheHitRate > 0 ? ((row.CacheHitRate * 100 | number:'1.0-0') + '%') : '—' }}</td>
                                    <td class="cell-numeric">{{ FormatCurrency(row.CostPer1KTokens, 4) }}</td>
                                    <td class="cell-numeric cell-cost">{{ FormatCurrency(row.TotalCost) }}</td>
                                </tr>
                            }
                        </tbody>
                    </table>
                </div>
            </div>
        }
    `, 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 Leaderboard \u2500\u2500 */\n        .leaderboard-panel {\n            background: var(--mj-bg-surface);\n            border: 1px solid var(--mj-border-default);\n            border-radius: 12px;\n            overflow: hidden;\n        }\n\n        .table-wrapper {\n            overflow-x: auto;\n        }\n\n        .leaderboard-table {\n            width: 100%;\n            border-collapse: collapse;\n            font-size: 13px;\n        }\n\n        .leaderboard-table th,\n        .leaderboard-table td {\n            padding: 12px 14px;\n            text-align: left;\n            border-bottom: 1px solid var(--mj-border-subtle);\n        }\n\n        .leaderboard-table th {\n            font-size: 11px;\n            font-weight: 600;\n            color: var(--mj-text-muted);\n            text-transform: uppercase;\n            letter-spacing: 0.4px;\n            background: var(--mj-bg-surface-card);\n            position: sticky;\n            top: 0;\n            white-space: nowrap;\n        }\n\n        .col-rank { width: 60px; text-align: center; }\n        .col-model { min-width: 180px; }\n        .col-vendor { min-width: 100px; }\n        .col-numeric { text-align: right; white-space: nowrap; }\n\n        .leaderboard-table tbody tr {\n            transition: background 0.15s;\n        }\n\n        .leaderboard-table tbody tr:hover {\n            background: var(--mj-bg-surface-hover);\n        }\n\n        .empty-row {\n            text-align: center;\n            color: var(--mj-text-disabled);\n            padding: 32px;\n        }\n\n        /* \u2500\u2500 Rank Badge \u2500\u2500 */\n        .rank-badge {\n            display: inline-flex;\n            align-items: center;\n            justify-content: center;\n            width: 28px;\n            height: 28px;\n            border-radius: 50%;\n            font-size: 12px;\n            font-weight: 700;\n        }\n\n        .rank-gold {\n            background: linear-gradient(135deg, color-mix(in srgb, var(--mj-status-warning) 35%, var(--mj-bg-surface)), color-mix(in srgb, var(--mj-status-warning) 20%, var(--mj-bg-surface)));\n            color: var(--mj-status-warning-text, var(--mj-status-warning));\n            box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n        }\n\n        .rank-silver {\n            background: color-mix(in srgb, var(--mj-text-muted) 18%, var(--mj-bg-surface));\n            color: var(--mj-text-secondary);\n            box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-text-muted) 20%, transparent);\n        }\n\n        .rank-bronze {\n            background: color-mix(in srgb, var(--mj-status-warning) 18%, var(--mj-bg-surface));\n            color: var(--mj-text-secondary);\n        }\n\n        .rank-neutral {\n            background: var(--mj-bg-surface-sunken);\n            color: var(--mj-text-muted);\n        }\n\n        /* \u2500\u2500 Model Cell \u2500\u2500 */\n        .cell-model {\n            font-weight: 500;\n            color: var(--mj-text-primary);\n        }\n\n        .model-name {\n            font-weight: 600;\n        }\n\n        .model-api-id {\n            font-size: 11px;\n            color: var(--mj-text-muted);\n            margin-top: 2px;\n            font-family: monospace;\n        }\n\n        .cell-vendor {\n            color: var(--mj-text-secondary);\n        }\n\n        .cell-numeric {\n            text-align: right;\n            font-variant-numeric: tabular-nums;\n            color: var(--mj-text-secondary);\n        }\n\n        .cell-cost {\n            font-weight: 600;\n            color: var(--mj-text-primary);\n        }\n\n        /* \u2500\u2500 Success Rate Mini Bar \u2500\u2500 */\n        .success-rate-cell {\n            display: flex;\n            flex-direction: column;\n            align-items: flex-end;\n            gap: 3px;\n        }\n\n        .success-rate-value {\n            font-weight: 600;\n        }\n\n        .success-bar-bg {\n            width: 60px;\n            height: 4px;\n            background: var(--mj-bg-surface-sunken);\n            border-radius: 2px;\n            overflow: hidden;\n        }\n\n        .success-bar-fill {\n            height: 100%;\n            background: var(--mj-status-success);\n            border-radius: 2px;\n            transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n        }\n\n        /* \u2500\u2500 Responsive \u2500\u2500 */\n        @media (max-width: 1200px) {\n            .leaderboard-table th,\n            .leaderboard-table td {\n                padding: 10px 10px;\n            }\n        }\n\n    "] }]
    }], null, { TimeRange: [{
            type: Input
        }], SortBy: [{
            type: Input
        }], SelectedVendor: [{
            type: Input
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AnalyticsModelPerformanceComponent, { className: "AnalyticsModelPerformanceComponent", filePath: "src/AI/components/analytics/model-performance/model-performance.component.ts", lineNumber: 305 }); })();
export function LoadAnalyticsModelPerformance() { }
//# sourceMappingURL=model-performance.component.js.map