/**
 * @fileoverview Prompt Run Analysis — Charts-first analytics with a detail table.
 *
 * Displays stats summary, runs-over-time chart, model/prompt/status breakdowns,
 * and a sortable, paginated detail table. All data is loaded via RunView from
 * the "MJ: AI Prompt Runs" entity.
 */
import { Component, Input, Output, EventEmitter, ChangeDetectorRef, inject } from '@angular/core';
import { Subject } from 'rxjs';
import { RunView } from '@memberjunction/core';
import { cacheHitRate } from '../../../services/cache-metrics';
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 "@angular/common";
const _forTrack0 = ($index, $item) => $item.key;
const _forTrack1 = ($index, $item) => $item.id;
const _forTrack2 = ($index, $item) => $item.name;
const _forTrack3 = ($index, $item) => $item.field;
const _forTrack4 = ($index, $item) => $item.ID;
const _forTrack5 = ($index, $item) => $item.label;
function AnalyticsPromptRunsComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 0);
    i0.ɵɵelement(1, "mj-loading", 1);
    i0.ɵɵelementEnd();
} }
function AnalyticsPromptRunsComponent_Conditional_1_For_53_Template(rf, ctx) { if (rf & 1) {
    const _r1 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "button", 32);
    i0.ɵɵlistener("click", function AnalyticsPromptRunsComponent_Conditional_1_For_53_Template_button_click_0_listener() { const metric_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnChartMetricChange(metric_r2.key)); });
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const metric_r2 = ctx.$implicit;
    const ctx_r2 = i0.ɵɵnextContext(2);
    i0.ɵɵclassProp("active", ctx_r2.ActiveChartMetric === metric_r2.key);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1(" ", metric_r2.label, " ");
} }
function AnalyticsPromptRunsComponent_Conditional_1_Conditional_55_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 16);
    i0.ɵɵtext(1, "No data for selected time range");
    i0.ɵɵelementEnd();
} }
function AnalyticsPromptRunsComponent_Conditional_1_Conditional_56_For_2_Template(rf, ctx) { if (rf & 1) {
    const _r4 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 34);
    i0.ɵɵlistener("click", function AnalyticsPromptRunsComponent_Conditional_1_Conditional_56_For_2_Template_div_click_0_listener() { const bucket_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.OnChartBucketClick(bucket_r5)); });
    i0.ɵɵelementStart(1, "div", 35);
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelement(3, "div", 36);
    i0.ɵɵelementStart(4, "div", 37);
    i0.ɵɵtext(5);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const bucket_r5 = ctx.$implicit;
    const ctx_r2 = i0.ɵɵnextContext(3);
    i0.ɵɵproperty("title", bucket_r5.label + ": " + bucket_r5.value);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r2.FormatChartValue(bucket_r5.value));
    i0.ɵɵadvance();
    i0.ɵɵstyleProp("height", bucket_r5.heightPercent, "%");
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(bucket_r5.label);
} }
function AnalyticsPromptRunsComponent_Conditional_1_Conditional_56_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 17);
    i0.ɵɵrepeaterCreate(1, AnalyticsPromptRunsComponent_Conditional_1_Conditional_56_For_2_Template, 6, 5, "div", 33, _forTrack5);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r2 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r2.ChartBuckets);
} }
function AnalyticsPromptRunsComponent_Conditional_1_For_62_Template(rf, ctx) { if (rf & 1) {
    const _r6 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 38);
    i0.ɵɵlistener("click", function AnalyticsPromptRunsComponent_Conditional_1_For_62_Template_div_click_0_listener() { const item_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.ApplyModelFilter(item_r7.id)); });
    i0.ɵɵelementStart(1, "span", 39);
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "span", 40);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "div", 41);
    i0.ɵɵelement(6, "div", 42);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const item_r7 = ctx.$implicit;
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(item_r7.name);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(item_r7.count);
    i0.ɵɵadvance(2);
    i0.ɵɵstyleProp("width", item_r7.percentage, "%");
} }
function AnalyticsPromptRunsComponent_Conditional_1_Conditional_63_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 22);
    i0.ɵɵtext(1, "No data");
    i0.ɵɵelementEnd();
} }
function AnalyticsPromptRunsComponent_Conditional_1_For_68_Template(rf, ctx) { if (rf & 1) {
    const _r8 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 38);
    i0.ɵɵlistener("click", function AnalyticsPromptRunsComponent_Conditional_1_For_68_Template_div_click_0_listener() { const item_r9 = i0.ɵɵrestoreView(_r8).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.ApplyPromptFilter(item_r9.id)); });
    i0.ɵɵelementStart(1, "span", 39);
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "span", 40);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "div", 41);
    i0.ɵɵelement(6, "div", 42);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const item_r9 = ctx.$implicit;
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(item_r9.name);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(item_r9.count);
    i0.ɵɵadvance(2);
    i0.ɵɵstyleProp("width", item_r9.percentage, "%");
} }
function AnalyticsPromptRunsComponent_Conditional_1_Conditional_69_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 22);
    i0.ɵɵtext(1, "No data");
    i0.ɵɵelementEnd();
} }
function AnalyticsPromptRunsComponent_Conditional_1_For_74_Template(rf, ctx) { if (rf & 1) {
    const _r10 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 38);
    i0.ɵɵlistener("click", function AnalyticsPromptRunsComponent_Conditional_1_For_74_Template_div_click_0_listener() { const item_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.ApplyStatusFilter(item_r11.name)); });
    i0.ɵɵelement(1, "span", 43);
    i0.ɵɵelementStart(2, "span", 39);
    i0.ɵɵtext(3);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "span", 40);
    i0.ɵɵtext(5);
    i0.ɵɵpipe(6, "number");
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const item_r11 = ctx.$implicit;
    i0.ɵɵadvance();
    i0.ɵɵclassMap(item_r11.cssClass);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(item_r11.name);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate2("", item_r11.count, " (", i0.ɵɵpipeBind2(6, 5, item_r11.percentage, "1.1-1"), "%)");
} }
function AnalyticsPromptRunsComponent_Conditional_1_Conditional_75_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 22);
    i0.ɵɵtext(1, "No data");
    i0.ɵɵelementEnd();
} }
function AnalyticsPromptRunsComponent_Conditional_1_For_88_Conditional_2_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "i");
} if (rf & 2) {
    const ctx_r2 = i0.ɵɵnextContext(3);
    i0.ɵɵclassMap(ctx_r2.SortDirection === "asc" ? "fa-solid fa-caret-up" : "fa-solid fa-caret-down");
} }
function AnalyticsPromptRunsComponent_Conditional_1_For_88_Template(rf, ctx) { if (rf & 1) {
    const _r12 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "th", 44);
    i0.ɵɵlistener("click", function AnalyticsPromptRunsComponent_Conditional_1_For_88_Template_th_click_0_listener() { const col_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(col_r13.sortable ? ctx_r2.OnSortChange(col_r13.field) : null); });
    i0.ɵɵtext(1);
    i0.ɵɵconditionalCreate(2, AnalyticsPromptRunsComponent_Conditional_1_For_88_Conditional_2_Template, 1, 2, "i", 45);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const col_r13 = ctx.$implicit;
    const ctx_r2 = i0.ɵɵnextContext(2);
    i0.ɵɵclassProp("sortable", col_r13.sortable)("sorted", ctx_r2.SortField === col_r13.field);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate1(" ", col_r13.label, " ");
    i0.ɵɵadvance();
    i0.ɵɵconditional(col_r13.sortable && ctx_r2.SortField === col_r13.field ? 2 : -1);
} }
function AnalyticsPromptRunsComponent_Conditional_1_For_91_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "tr")(1, "td", 46);
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "td", 47);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "td")(6, "span", 48);
    i0.ɵɵtext(7);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(8, "td")(9, "span", 49);
    i0.ɵɵtext(10);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(11, "td", 50);
    i0.ɵɵtext(12);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(13, "td", 51);
    i0.ɵɵtext(14);
    i0.ɵɵpipe(15, "number");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(16, "td", 50);
    i0.ɵɵtext(17);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const run_r14 = ctx.$implicit;
    const ɵ$index_207_r15 = ctx.$index;
    const ctx_r2 = i0.ɵɵnextContext(2);
    i0.ɵɵclassProp("row-even", ɵ$index_207_r15 % 2 === 0);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r2.FormatTimestamp(run_r14.RunAt));
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(run_r14.Prompt ?? "(unnamed)");
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(run_r14.Model ?? "N/A");
    i0.ɵɵadvance(2);
    i0.ɵɵclassMap(ctx_r2.GetStatusClass(run_r14.Status));
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(run_r14.Status);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r2.FormatDuration(run_r14.ExecutionTimeMS));
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(run_r14.TokensUsed != null ? i0.ɵɵpipeBind1(15, 11, ctx_r2.TrueTotalTokens(run_r14)) : "-");
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(ctx_r2.FormatCurrency(run_r14.Cost, 4));
} }
function AnalyticsPromptRunsComponent_Conditional_1_Conditional_92_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "tr")(1, "td", 52);
    i0.ɵɵtext(2, "No prompt runs found for the selected filters.");
    i0.ɵɵelementEnd()();
} }
function AnalyticsPromptRunsComponent_Conditional_1_Conditional_93_Template(rf, ctx) { if (rf & 1) {
    const _r16 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 31)(1, "button", 53);
    i0.ɵɵlistener("click", function AnalyticsPromptRunsComponent_Conditional_1_Conditional_93_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r16); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnPageChange(ctx_r2.CurrentPage - 1)); });
    i0.ɵɵelement(2, "i", 54);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "span", 55);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "button", 53);
    i0.ɵɵlistener("click", function AnalyticsPromptRunsComponent_Conditional_1_Conditional_93_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r16); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnPageChange(ctx_r2.CurrentPage + 1)); });
    i0.ɵɵelement(6, "i", 56);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r2 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance();
    i0.ɵɵproperty("disabled", ctx_r2.CurrentPage === 1);
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate2("Page ", ctx_r2.CurrentPage, " of ", ctx_r2.TotalPages);
    i0.ɵɵadvance();
    i0.ɵɵproperty("disabled", ctx_r2.CurrentPage === ctx_r2.TotalPages);
} }
function AnalyticsPromptRunsComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 2)(1, "div", 3)(2, "div", 4);
    i0.ɵɵtext(3, "Total Runs");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "div", 5);
    i0.ɵɵtext(5);
    i0.ɵɵpipe(6, "number");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(7, "div", 6)(8, "div", 4);
    i0.ɵɵtext(9, "Avg Cost");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(10, "div", 5);
    i0.ɵɵtext(11);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(12, "div", 6)(13, "div", 4);
    i0.ɵɵtext(14, "Avg Tokens");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(15, "div", 5);
    i0.ɵɵtext(16);
    i0.ɵɵpipe(17, "number");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(18, "div", 6)(19, "div", 4);
    i0.ɵɵtext(20, "Avg Latency");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(21, "div", 5);
    i0.ɵɵtext(22);
    i0.ɵɵpipe(23, "number");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(24, "div", 7)(25, "div", 4);
    i0.ɵɵtext(26, "Success Rate");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(27, "div", 5);
    i0.ɵɵtext(28);
    i0.ɵɵpipe(29, "number");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(30, "div", 8)(31, "div", 4);
    i0.ɵɵtext(32, "P95 Latency");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(33, "div", 5);
    i0.ɵɵtext(34);
    i0.ɵɵpipe(35, "number");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(36, "div", 6)(37, "div", 4);
    i0.ɵɵtext(38, "Total Cost");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(39, "div", 5);
    i0.ɵɵtext(40);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(41, "div", 9)(42, "div", 4);
    i0.ɵɵtext(43, "Cache Hit Rate");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(44, "div", 5);
    i0.ɵɵtext(45);
    i0.ɵɵpipe(46, "number");
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(47, "div", 10)(48, "div", 11)(49, "h3", 12);
    i0.ɵɵtext(50, "Runs Over Time");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(51, "div", 13);
    i0.ɵɵrepeaterCreate(52, AnalyticsPromptRunsComponent_Conditional_1_For_53_Template, 2, 3, "button", 14, _forTrack0);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(54, "div", 15);
    i0.ɵɵconditionalCreate(55, AnalyticsPromptRunsComponent_Conditional_1_Conditional_55_Template, 2, 0, "div", 16)(56, AnalyticsPromptRunsComponent_Conditional_1_Conditional_56_Template, 3, 0, "div", 17);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(57, "div", 18)(58, "div", 19)(59, "h4", 20);
    i0.ɵɵtext(60, "By Model");
    i0.ɵɵelementEnd();
    i0.ɵɵrepeaterCreate(61, AnalyticsPromptRunsComponent_Conditional_1_For_62_Template, 7, 4, "div", 21, _forTrack1);
    i0.ɵɵconditionalCreate(63, AnalyticsPromptRunsComponent_Conditional_1_Conditional_63_Template, 2, 0, "div", 22);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(64, "div", 19)(65, "h4", 20);
    i0.ɵɵtext(66, "By Prompt");
    i0.ɵɵelementEnd();
    i0.ɵɵrepeaterCreate(67, AnalyticsPromptRunsComponent_Conditional_1_For_68_Template, 7, 4, "div", 21, _forTrack1);
    i0.ɵɵconditionalCreate(69, AnalyticsPromptRunsComponent_Conditional_1_Conditional_69_Template, 2, 0, "div", 22);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(70, "div", 19)(71, "h4", 20);
    i0.ɵɵtext(72, "By Status");
    i0.ɵɵelementEnd();
    i0.ɵɵrepeaterCreate(73, AnalyticsPromptRunsComponent_Conditional_1_For_74_Template, 7, 8, "div", 21, _forTrack2);
    i0.ɵɵconditionalCreate(75, AnalyticsPromptRunsComponent_Conditional_1_Conditional_75_Template, 2, 0, "div", 22);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(76, "div", 23)(77, "div", 24)(78, "h3", 25);
    i0.ɵɵtext(79, "Run Details");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(80, "span", 26);
    i0.ɵɵtext(81);
    i0.ɵɵpipe(82, "number");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(83, "div", 27)(84, "table", 28)(85, "thead")(86, "tr");
    i0.ɵɵrepeaterCreate(87, AnalyticsPromptRunsComponent_Conditional_1_For_88_Template, 3, 6, "th", 29, _forTrack3);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(89, "tbody");
    i0.ɵɵrepeaterCreate(90, AnalyticsPromptRunsComponent_Conditional_1_For_91_Template, 18, 13, "tr", 30, _forTrack4);
    i0.ɵɵconditionalCreate(92, AnalyticsPromptRunsComponent_Conditional_1_Conditional_92_Template, 3, 0, "tr");
    i0.ɵɵelementEnd()()();
    i0.ɵɵconditionalCreate(93, AnalyticsPromptRunsComponent_Conditional_1_Conditional_93_Template, 7, 4, "div", 31);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r2 = i0.ɵɵnextContext();
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(6, 15, ctx_r2.Stats.TotalRuns));
    i0.ɵɵadvance(6);
    i0.ɵɵtextInterpolate(ctx_r2.FormatCurrency(ctx_r2.Stats.AvgCost, 4));
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(17, 17, ctx_r2.Stats.AvgTokens, "1.0-0"));
    i0.ɵɵadvance(6);
    i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(23, 20, ctx_r2.Stats.AvgLatencySeconds, "1.2-2"), "s");
    i0.ɵɵadvance(6);
    i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(29, 23, ctx_r2.Stats.SuccessRate, "1.1-1"), "%");
    i0.ɵɵadvance(6);
    i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(35, 26, ctx_r2.Stats.P95LatencySeconds, "1.2-2"), "s");
    i0.ɵɵadvance(6);
    i0.ɵɵtextInterpolate(ctx_r2.FormatCurrency(ctx_r2.Stats.TotalCost, 2));
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(46, 29, ctx_r2.Stats.CacheHitRate * 100, "1.1-1"), "%");
    i0.ɵɵadvance(7);
    i0.ɵɵrepeater(ctx_r2.ChartMetricOptions);
    i0.ɵɵadvance(3);
    i0.ɵɵconditional(ctx_r2.ChartBuckets.length === 0 ? 55 : 56);
    i0.ɵɵadvance(6);
    i0.ɵɵrepeater(ctx_r2.ModelBreakdown);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(ctx_r2.ModelBreakdown.length === 0 ? 63 : -1);
    i0.ɵɵadvance(4);
    i0.ɵɵrepeater(ctx_r2.PromptBreakdown);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(ctx_r2.PromptBreakdown.length === 0 ? 69 : -1);
    i0.ɵɵadvance(4);
    i0.ɵɵrepeater(ctx_r2.StatusBreakdown);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(ctx_r2.StatusBreakdown.length === 0 ? 75 : -1);
    i0.ɵɵadvance(6);
    i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(82, 32, ctx_r2.FilteredRuns.length), " runs");
    i0.ɵɵadvance(6);
    i0.ɵɵrepeater(ctx_r2.TableColumns);
    i0.ɵɵadvance(3);
    i0.ɵɵrepeater(ctx_r2.PagedRuns);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(ctx_r2.PagedRuns.length === 0 ? 92 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r2.TotalPages > 1 ? 93 : -1);
} }
const FIELDS = [
    'ID', 'RunAt', 'CompletedAt', 'Status', 'Success', 'Cost', 'TotalCost',
    'TokensUsed', 'TokensPrompt', 'TokensCompletion', 'TokensCacheRead', 'TokensCacheWrite', 'ExecutionTimeMS',
    'ModelID', 'Model', 'AgentID', 'Agent', 'PromptID', 'Prompt', 'ErrorMessage'
];
const PAGE_SIZE = 25;
export class AnalyticsPromptRunsComponent extends BaseAngularComponent {
    cdr = inject(ChangeDetectorRef);
    destroy$ = new Subject();
    isInitialized = false;
    // ── Inputs with setter pattern ──
    _timeRange = '24h';
    set TimeRange(value) {
        if (value !== this._timeRange) {
            this._timeRange = value;
            if (this.isInitialized) {
                this.LoadData();
            }
        }
    }
    get TimeRange() {
        return this._timeRange;
    }
    _filters = { Models: [], Agents: [], Prompts: [], Statuses: [] };
    set Filters(value) {
        this._filters = value;
        if (this.isInitialized) {
            this.resetPagination();
            this.cdr.detectChanges();
        }
    }
    get Filters() {
        return this._filters;
    }
    TimeRangeChange = new EventEmitter();
    FiltersChange = new EventEmitter();
    // ── State ──
    IsLoading = false;
    ActiveChartMetric = 'volume';
    SortField = 'RunAt';
    SortDirection = 'desc';
    CurrentPage = 1;
    allRuns = [];
    ChartMetricOptions = [
        { key: 'volume', label: 'By Volume' },
        { key: 'cost', label: 'By Cost' },
        { key: 'tokens', label: 'By Tokens' },
        { key: 'cacheHit', label: 'By Cache Hit %' },
    ];
    TableColumns = [
        { field: 'RunAt', label: 'Timestamp', sortable: true },
        { field: 'Prompt', label: 'Prompt', sortable: true },
        { field: 'Model', label: 'Model', sortable: true },
        { field: 'Status', label: 'Status', sortable: true },
        { field: 'ExecutionTimeMS', label: 'Duration', sortable: true },
        { field: 'TokensUsed', label: 'Tokens', sortable: true },
        { field: 'Cost', label: 'Cost', sortable: true },
    ];
    // ── Lifecycle ──
    async ngOnInit() {
        this.isInitialized = true;
        await this.LoadData();
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
    }
    // ── Computed Properties ──
    get FilteredRuns() {
        return this.applyFilters(this.allRuns);
    }
    get Stats() {
        return this.computeStats(this.FilteredRuns);
    }
    get ChartBuckets() {
        return this.computeChartBuckets(this.FilteredRuns);
    }
    get ModelBreakdown() {
        return this.computeBreakdown(this.FilteredRuns, 'Model', 'ModelID');
    }
    get PromptBreakdown() {
        return this.computeBreakdown(this.FilteredRuns, 'Prompt', 'PromptID');
    }
    get StatusBreakdown() {
        return this.computeStatusBreakdown(this.FilteredRuns);
    }
    get PagedRuns() {
        const sorted = this.sortRuns(this.FilteredRuns);
        const start = (this.CurrentPage - 1) * PAGE_SIZE;
        return sorted.slice(start, start + PAGE_SIZE);
    }
    get TotalPages() {
        return Math.max(1, Math.ceil(this.FilteredRuns.length / PAGE_SIZE));
    }
    // ── Event Handlers ──
    OnTimeRangeChange(range) {
        this.TimeRange = range;
        this.TimeRangeChange.emit(range);
    }
    OnFiltersChange(filters) {
        this.Filters = filters;
        this.FiltersChange.emit(filters);
    }
    OnChartMetricChange(metric) {
        this.ActiveChartMetric = metric;
        this.cdr.detectChanges();
    }
    OnChartBucketClick(_bucket) {
        // Future: drill into time range
    }
    OnSortChange(field) {
        if (this.SortField === field) {
            this.SortDirection = this.SortDirection === 'asc' ? 'desc' : 'asc';
        }
        else {
            this.SortField = field;
            this.SortDirection = 'desc';
        }
        this.resetPagination();
        this.cdr.detectChanges();
    }
    OnPageChange(page) {
        if (page >= 1 && page <= this.TotalPages) {
            this.CurrentPage = page;
            this.cdr.detectChanges();
        }
    }
    ApplyModelFilter(modelId) {
        this.Filters = { ...this.Filters, Models: [modelId] };
        this.FiltersChange.emit(this.Filters);
    }
    ApplyPromptFilter(promptId) {
        this.Filters = { ...this.Filters, Prompts: [promptId] };
        this.FiltersChange.emit(this.Filters);
    }
    ApplyStatusFilter(status) {
        this.Filters = { ...this.Filters, Statuses: [status] };
        this.FiltersChange.emit(this.Filters);
    }
    ExportCSV() {
        const headers = ['Timestamp', 'Prompt', 'Model', 'Status', 'Duration(ms)', 'Tokens', 'Cost'];
        const rows = this.FilteredRuns.map(r => [
            r.RunAt,
            r.Prompt ?? '',
            r.Model ?? '',
            r.Status,
            r.ExecutionTimeMS?.toString() ?? '',
            this.TrueTotalTokens(r).toString(),
            r.Cost?.toString() ?? ''
        ]);
        const csv = [headers, ...rows].map(r => r.join(',')).join('\n');
        const blob = new Blob([csv], { type: 'text/csv' });
        const url = URL.createObjectURL(blob);
        const anchor = document.createElement('a');
        anchor.href = url;
        anchor.download = `prompt-runs-${new Date().toISOString().slice(0, 10)}.csv`;
        anchor.click();
        URL.revokeObjectURL(url);
    }
    // ── Formatting Helpers ──
    FormatCurrency(value, decimals) {
        if (value == null || isNaN(value))
            return '$0.00';
        return '$' + value.toFixed(decimals);
    }
    FormatTimestamp(dateStr) {
        const d = new Date(dateStr);
        return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) +
            ' ' + d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
    }
    FormatDuration(ms) {
        if (ms == null)
            return '-';
        if (ms < 1000)
            return ms + 'ms';
        return (ms / 1000).toFixed(2) + 's';
    }
    FormatChartValue(value) {
        if (this.ActiveChartMetric === 'cost') {
            return '$' + value.toFixed(2);
        }
        if (this.ActiveChartMetric === 'cacheHit') {
            return value.toFixed(0) + '%';
        }
        if (value >= 1000) {
            return (value / 1000).toFixed(1) + 'k';
        }
        return value.toFixed(0);
    }
    GetStatusClass(status) {
        const key = status.toLowerCase();
        return 'pill-' + key;
    }
    // ── Data Loading ──
    async LoadData() {
        this.IsLoading = true;
        this.cdr.detectChanges();
        try {
            const rv = RunView.FromMetadataProvider(this.ProviderToUse);
            const cutoff = this.getTimeRangeCutoff(this._timeRange);
            const filter = cutoff ? `RunAt >= '${cutoff.toISOString()}'` : '';
            const result = await rv.RunView({
                EntityName: 'MJ: AI Prompt Runs',
                ExtraFilter: filter,
                OrderBy: 'RunAt DESC',
                Fields: FIELDS,
                ResultType: 'simple'
            });
            if (result.Success) {
                this.allRuns = result.Results;
            }
            else {
                this.allRuns = [];
            }
        }
        catch {
            this.allRuns = [];
        }
        this.resetPagination();
        this.IsLoading = false;
        this.cdr.detectChanges();
    }
    // ── Private Helpers ──
    applyFilters(runs) {
        let filtered = runs;
        if (this._filters.Models.length > 0) {
            filtered = filtered.filter(r => r.ModelID != null && this._filters.Models.includes(r.ModelID));
        }
        if (this._filters.Agents.length > 0) {
            filtered = filtered.filter(r => r.AgentID != null && this._filters.Agents.includes(r.AgentID));
        }
        if (this._filters.Prompts.length > 0) {
            filtered = filtered.filter(r => r.PromptID != null && this._filters.Prompts.includes(r.PromptID));
        }
        if (this._filters.Statuses.length > 0) {
            filtered = filtered.filter(r => this._filters.Statuses.includes(r.Status));
        }
        return filtered;
    }
    /**
     * Total tokens the model processed for a run, INCLUDING cached input. TokensUsed excludes the
     * cache buckets by design, so a heavily-cached run looks tiny; this is the true throughput.
     */
    TrueTotalTokens(run) {
        return (run.TokensUsed ?? 0) + (run.TokensCacheRead ?? 0) + (run.TokensCacheWrite ?? 0);
    }
    computeStats(runs) {
        const total = runs.length;
        if (total === 0) {
            return { TotalRuns: 0, AvgCost: 0, AvgTokens: 0, AvgLatencySeconds: 0, SuccessRate: 0, P95LatencySeconds: 0, TotalCost: 0, CacheHitRate: 0 };
        }
        const totalCost = this.sumNullable(runs, r => r.Cost);
        const totalTokens = runs.reduce((sum, r) => sum + this.TrueTotalTokens(r), 0);
        const latencies = this.collectNonNull(runs, r => r.ExecutionTimeMS);
        const avgLatencyMs = latencies.length > 0 ? latencies.reduce((a, b) => a + b, 0) / latencies.length : 0;
        const successCount = runs.filter(r => r.Status === 'Completed').length;
        const p95 = this.percentile(latencies, 95);
        const cacheHit = cacheHitRate({
            uncachedInputTokens: this.sumNullable(runs, r => r.TokensPrompt),
            cacheReadTokens: this.sumNullable(runs, r => r.TokensCacheRead),
            cacheWriteTokens: this.sumNullable(runs, r => r.TokensCacheWrite)
        });
        return {
            TotalRuns: total,
            AvgCost: totalCost / total,
            AvgTokens: totalTokens / total,
            AvgLatencySeconds: avgLatencyMs / 1000,
            SuccessRate: (successCount / total) * 100,
            P95LatencySeconds: p95 / 1000,
            TotalCost: totalCost,
            CacheHitRate: cacheHit,
        };
    }
    computeChartBuckets(runs) {
        if (runs.length === 0)
            return [];
        const bucketCount = this.getBucketCount();
        const cutoff = this.getTimeRangeCutoff(this._timeRange) ?? new Date(runs[runs.length - 1].RunAt);
        const now = new Date();
        const rangeMs = now.getTime() - cutoff.getTime();
        const bucketMs = rangeMs / bucketCount;
        const buckets = [];
        for (let i = 0; i < bucketCount; i++) {
            const start = new Date(cutoff.getTime() + i * bucketMs);
            const end = new Date(cutoff.getTime() + (i + 1) * bucketMs);
            buckets.push({
                label: this.formatBucketLabel(start),
                total: 0,
                cacheRead: 0,
                inputForHit: 0,
                start,
                end,
            });
        }
        for (const run of runs) {
            const runTime = new Date(run.RunAt).getTime();
            const idx = Math.min(Math.floor((runTime - cutoff.getTime()) / bucketMs), bucketCount - 1);
            if (idx >= 0 && idx < bucketCount) {
                buckets[idx].total += this.getChartMetricValue(run);
                // Cache hit-rate is a ratio, not a sum — accumulate the components and divide below.
                buckets[idx].cacheRead += run.TokensCacheRead ?? 0;
                buckets[idx].inputForHit += (run.TokensPrompt ?? 0) + (run.TokensCacheRead ?? 0) + (run.TokensCacheWrite ?? 0);
            }
        }
        if (this.ActiveChartMetric === 'cacheHit') {
            for (const b of buckets) {
                b.total = b.inputForHit > 0 ? (b.cacheRead / b.inputForHit) * 100 : 0;
            }
        }
        const max = Math.max(...buckets.map(b => b.total), 1);
        return buckets.map(b => ({
            label: b.label,
            value: Math.round(b.total * 100) / 100,
            heightPercent: Math.max((b.total / max) * 100, 1),
            startTime: b.start,
            endTime: b.end,
        }));
    }
    getChartMetricValue(run) {
        switch (this.ActiveChartMetric) {
            case 'cost': return run.Cost ?? 0;
            case 'tokens': return this.TrueTotalTokens(run);
            default: return 1; // volume = count
        }
    }
    computeBreakdown(runs, nameKey, idKey) {
        const counts = new Map();
        for (const run of runs) {
            const id = run[idKey];
            const name = run[nameKey];
            if (id != null && name != null) {
                const existing = counts.get(id);
                if (existing) {
                    existing.count++;
                }
                else {
                    counts.set(id, { name, count: 1 });
                }
            }
        }
        const sorted = Array.from(counts.entries())
            .sort((a, b) => b[1].count - a[1].count)
            .slice(0, 4);
        const maxCount = sorted.length > 0 ? sorted[0][1].count : 1;
        return sorted.map(([id, data]) => ({
            id,
            name: data.name,
            count: data.count,
            percentage: (data.count / maxCount) * 100,
        }));
    }
    computeStatusBreakdown(runs) {
        const total = runs.length;
        if (total === 0)
            return [];
        const counts = new Map();
        for (const run of runs) {
            counts.set(run.Status, (counts.get(run.Status) ?? 0) + 1);
        }
        return Array.from(counts.entries())
            .sort((a, b) => b[1] - a[1])
            .map(([status, count]) => ({
            id: status,
            name: status,
            count,
            percentage: (count / total) * 100,
            cssClass: 'dot-' + status.toLowerCase(),
        }));
    }
    sortRuns(runs) {
        const dir = this.SortDirection === 'asc' ? 1 : -1;
        return [...runs].sort((a, b) => {
            const aVal = a[this.SortField];
            const bVal = b[this.SortField];
            if (aVal == null && bVal == null)
                return 0;
            if (aVal == null)
                return 1;
            if (bVal == null)
                return -1;
            if (typeof aVal === 'string' && typeof bVal === 'string') {
                return aVal.localeCompare(bVal) * dir;
            }
            if (typeof aVal === 'number' && typeof bVal === 'number') {
                return (aVal - bVal) * dir;
            }
            return String(aVal).localeCompare(String(bVal)) * dir;
        });
    }
    getTimeRangeCutoff(range) {
        const now = new Date();
        switch (range) {
            case '1h': return new Date(now.getTime() - 60 * 60 * 1000);
            case '6h': return new Date(now.getTime() - 6 * 60 * 60 * 1000);
            case '24h': return new Date(now.getTime() - 24 * 60 * 60 * 1000);
            case '7d': return new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
            case '30d': return new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
            default: return null;
        }
    }
    getBucketCount() {
        switch (this._timeRange) {
            case '1h': return 12; // 5-min buckets
            case '6h': return 12; // 30-min buckets
            case '24h': return 24; // 1-hour buckets
            case '7d': return 14; // 12-hour buckets
            case '30d': return 30; // 1-day buckets
            default: return 24;
        }
    }
    formatBucketLabel(date) {
        switch (this._timeRange) {
            case '1h':
            case '6h':
                return date.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
            case '24h':
                return date.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
            case '7d':
            case '30d':
                return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
            default:
                return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
        }
    }
    sumNullable(runs, getter) {
        return runs.reduce((sum, r) => sum + (getter(r) ?? 0), 0);
    }
    collectNonNull(runs, getter) {
        const result = [];
        for (const r of runs) {
            const val = getter(r);
            if (val != null) {
                result.push(val);
            }
        }
        return result;
    }
    percentile(values, pct) {
        if (values.length === 0)
            return 0;
        const sorted = [...values].sort((a, b) => a - b);
        const index = Math.ceil((pct / 100) * sorted.length) - 1;
        return sorted[Math.max(0, index)];
    }
    resetPagination() {
        this.CurrentPage = 1;
    }
    static ɵfac = /*@__PURE__*/ (() => { let ɵAnalyticsPromptRunsComponent_BaseFactory; return function AnalyticsPromptRunsComponent_Factory(__ngFactoryType__) { return (ɵAnalyticsPromptRunsComponent_BaseFactory || (ɵAnalyticsPromptRunsComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AnalyticsPromptRunsComponent)))(__ngFactoryType__ || AnalyticsPromptRunsComponent); }; })();
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AnalyticsPromptRunsComponent, selectors: [["app-analytics-prompt-runs"]], inputs: { TimeRange: "TimeRange", Filters: "Filters" }, outputs: { TimeRangeChange: "TimeRangeChange", FiltersChange: "FiltersChange" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "loading-container"], ["text", "Loading prompt runs..."], [1, "stats-grid"], [1, "stat-card", "accent-brand"], [1, "stat-label"], [1, "stat-value"], [1, "stat-card"], [1, "stat-card", "accent-success"], [1, "stat-card", "accent-warning"], ["title", "Share of input tokens served from the provider's prompt cache", 1, "stat-card"], [1, "chart-panel"], [1, "chart-header"], [1, "chart-title"], [1, "chart-toggles"], [1, "toggle-chip", 3, "active"], [1, "chart-area"], [1, "chart-empty"], [1, "chart-bars"], [1, "breakdown-grid"], [1, "breakdown-card"], [1, "breakdown-title"], [1, "breakdown-row"], [1, "breakdown-empty"], [1, "table-panel"], [1, "table-header"], [1, "table-title"], [1, "table-count"], [1, "table-scroll"], [1, "runs-table"], [3, "sortable", "sorted"], [3, "row-even"], [1, "pagination"], [1, "toggle-chip", 3, "click"], [1, "chart-bar-wrapper", 3, "title"], [1, "chart-bar-wrapper", 3, "click", "title"], [1, "chart-bar-value"], [1, "chart-bar"], [1, "chart-bar-label"], [1, "breakdown-row", 3, "click"], [1, "breakdown-name"], [1, "breakdown-count"], [1, "breakdown-bar-track"], [1, "breakdown-bar-fill"], [1, "status-dot"], [3, "click"], [3, "class"], [1, "cell-timestamp"], [1, "cell-prompt"], [1, "model-tag"], [1, "status-pill"], [1, "cell-number"], ["title", "Total tokens processed, including cached input", 1, "cell-number"], ["colspan", "7", 1, "empty-row"], [1, "page-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-left"], [1, "page-info"], [1, "fa-solid", "fa-chevron-right"]], template: function AnalyticsPromptRunsComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵconditionalCreate(0, AnalyticsPromptRunsComponent_Conditional_0_Template, 2, 0, "div", 0)(1, AnalyticsPromptRunsComponent_Conditional_1_Template, 94, 34);
        } if (rf & 2) {
            i0.ɵɵconditional(ctx.IsLoading ? 0 : 1);
        } }, dependencies: [i1.LoadingComponent, i2.DecimalPipe], styles: ["[_nghost-%COMP%] {\n            display: block;\n        }\n\n        .loading-container[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            padding: 80px 0;\n        }\n\n        \n\n\n        .stats-grid[_ngcontent-%COMP%] {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n            gap: 12px;\n            margin-top: 16px;\n        }\n\n        .stat-card[_ngcontent-%COMP%] {\n            background: var(--mj-bg-surface);\n            border: 1px solid var(--mj-border-default);\n            border-radius: 10px;\n            padding: 14px 16px;\n            display: flex;\n            flex-direction: column;\n            gap: 4px;\n        }\n\n        .stat-card.accent-brand[_ngcontent-%COMP%] {\n            border-left: 3px solid var(--mj-brand-primary);\n        }\n\n        .stat-card.accent-success[_ngcontent-%COMP%] {\n            border-left: 3px solid var(--mj-status-success);\n        }\n\n        .stat-card.accent-warning[_ngcontent-%COMP%] {\n            border-left: 3px solid var(--mj-status-warning);\n        }\n\n        .stat-label[_ngcontent-%COMP%] {\n            font-size: 12px;\n            font-weight: 500;\n            color: var(--mj-text-muted);\n            text-transform: uppercase;\n            letter-spacing: 0.4px;\n        }\n\n        .stat-value[_ngcontent-%COMP%] {\n            font-size: 20px;\n            font-weight: 700;\n            color: var(--mj-text-primary);\n        }\n\n        \n\n\n        .chart-panel[_ngcontent-%COMP%] {\n            margin-top: 16px;\n            background: var(--mj-bg-surface);\n            border: 1px solid var(--mj-border-default);\n            border-radius: 12px;\n            padding: 20px;\n        }\n\n        .chart-header[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            margin-bottom: 16px;\n        }\n\n        .chart-title[_ngcontent-%COMP%] {\n            font-size: 15px;\n            font-weight: 600;\n            color: var(--mj-text-primary);\n            margin: 0;\n        }\n\n        .chart-toggles[_ngcontent-%COMP%] {\n            display: flex;\n            gap: 4px;\n        }\n\n        .toggle-chip[_ngcontent-%COMP%] {\n            padding: 4px 12px;\n            border: 1px solid var(--mj-border-default);\n            border-radius: 16px;\n            background: var(--mj-bg-surface);\n            color: var(--mj-text-secondary);\n            font-size: 12px;\n            font-weight: 500;\n            cursor: pointer;\n            transition: background 0.15s, color 0.15s, border-color 0.15s;\n        }\n\n        .toggle-chip[_ngcontent-%COMP%]:hover {\n            background: var(--mj-bg-surface-hover);\n            color: var(--mj-text-primary);\n        }\n\n        .toggle-chip.active[_ngcontent-%COMP%] {\n            background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n            color: var(--mj-brand-primary);\n            border-color: var(--mj-brand-primary);\n            font-weight: 600;\n        }\n\n        .chart-area[_ngcontent-%COMP%] {\n            height: 220px;\n            display: flex;\n            align-items: flex-end;\n        }\n\n        .chart-empty[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            width: 100%;\n            height: 100%;\n            color: var(--mj-text-muted);\n            font-size: 13px;\n        }\n\n        .chart-bars[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: flex-end;\n            gap: 4px;\n            width: 100%;\n            height: 100%;\n            padding-bottom: 24px;\n        }\n\n        .chart-bar-wrapper[_ngcontent-%COMP%] {\n            flex: 1;\n            min-width: 0;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            cursor: pointer;\n            position: relative;\n            height: 100%;\n            justify-content: flex-end;\n        }\n\n        .chart-bar-value[_ngcontent-%COMP%] {\n            font-size: 10px;\n            color: var(--mj-text-muted);\n            margin-bottom: 4px;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            max-width: 100%;\n        }\n\n        .chart-bar[_ngcontent-%COMP%] {\n            width: 80%;\n            min-height: 2px;\n            background: color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n            border-radius: 4px 4px 0 0;\n            transition: background 0.15s, height 0.3s;\n        }\n\n        .chart-bar-wrapper[_ngcontent-%COMP%]:hover   .chart-bar[_ngcontent-%COMP%] {\n            background: color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-bg-surface));\n        }\n\n        .chart-bar-label[_ngcontent-%COMP%] {\n            font-size: 10px;\n            color: var(--mj-text-muted);\n            margin-top: 6px;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            max-width: 100%;\n            text-align: center;\n            position: absolute;\n            bottom: 0;\n        }\n\n        \n\n\n        .breakdown-grid[_ngcontent-%COMP%] {\n            display: grid;\n            grid-template-columns: repeat(3, 1fr);\n            gap: 12px;\n            margin-top: 16px;\n        }\n\n        .breakdown-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        }\n\n        .breakdown-title[_ngcontent-%COMP%] {\n            font-size: 13px;\n            font-weight: 600;\n            color: var(--mj-text-primary);\n            margin: 0 0 12px;\n        }\n\n        .breakdown-row[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            padding: 6px 0;\n            cursor: pointer;\n            border-radius: 4px;\n            transition: background 0.1s;\n        }\n\n        .breakdown-row[_ngcontent-%COMP%]:hover {\n            background: var(--mj-bg-surface-hover);\n        }\n\n        .breakdown-name[_ngcontent-%COMP%] {\n            flex: 1;\n            font-size: 13px;\n            color: var(--mj-text-primary);\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            min-width: 0;\n        }\n\n        .breakdown-count[_ngcontent-%COMP%] {\n            font-size: 12px;\n            color: var(--mj-text-secondary);\n            font-weight: 600;\n            white-space: nowrap;\n        }\n\n        .breakdown-bar-track[_ngcontent-%COMP%] {\n            width: 60px;\n            height: 6px;\n            background: var(--mj-bg-surface-sunken);\n            border-radius: 3px;\n            overflow: hidden;\n            flex-shrink: 0;\n        }\n\n        .breakdown-bar-fill[_ngcontent-%COMP%] {\n            height: 100%;\n            background: var(--mj-brand-primary);\n            border-radius: 3px;\n            transition: width 0.3s;\n        }\n\n        .breakdown-empty[_ngcontent-%COMP%] {\n            font-size: 13px;\n            color: var(--mj-text-muted);\n            padding: 8px 0;\n        }\n\n        .status-dot[_ngcontent-%COMP%] {\n            width: 8px;\n            height: 8px;\n            border-radius: 50%;\n            flex-shrink: 0;\n        }\n\n        .status-dot.dot-completed[_ngcontent-%COMP%] { background: var(--mj-status-success); }\n        .status-dot.dot-failed[_ngcontent-%COMP%] { background: var(--mj-status-error); }\n        .status-dot.dot-running[_ngcontent-%COMP%] { background: var(--mj-brand-primary); }\n        .status-dot.dot-pending[_ngcontent-%COMP%] { background: var(--mj-status-warning); }\n        .status-dot.dot-cancelled[_ngcontent-%COMP%] { background: var(--mj-text-muted); }\n\n        \n\n\n        .table-panel[_ngcontent-%COMP%] {\n            margin-top: 16px;\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-header[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            padding: 16px 20px;\n            border-bottom: 1px solid var(--mj-border-subtle);\n        }\n\n        .table-title[_ngcontent-%COMP%] {\n            font-size: 15px;\n            font-weight: 600;\n            color: var(--mj-text-primary);\n            margin: 0;\n        }\n\n        .table-count[_ngcontent-%COMP%] {\n            font-size: 12px;\n            color: var(--mj-text-muted);\n            font-weight: 500;\n        }\n\n        .table-scroll[_ngcontent-%COMP%] {\n            overflow-x: auto;\n        }\n\n        .runs-table[_ngcontent-%COMP%] {\n            width: 100%;\n            border-collapse: collapse;\n            font-size: 13px;\n        }\n\n        .runs-table[_ngcontent-%COMP%]   th[_ngcontent-%COMP%] {\n            padding: 10px 14px;\n            text-align: left;\n            font-weight: 600;\n            font-size: 12px;\n            color: var(--mj-text-secondary);\n            text-transform: uppercase;\n            letter-spacing: 0.4px;\n            border-bottom: 1px solid var(--mj-border-default);\n            background: var(--mj-bg-surface-card);\n            white-space: nowrap;\n            user-select: none;\n        }\n\n        .runs-table[_ngcontent-%COMP%]   th.sortable[_ngcontent-%COMP%] {\n            cursor: pointer;\n        }\n\n        .runs-table[_ngcontent-%COMP%]   th.sortable[_ngcontent-%COMP%]:hover {\n            color: var(--mj-text-primary);\n        }\n\n        .runs-table[_ngcontent-%COMP%]   th.sorted[_ngcontent-%COMP%] {\n            color: var(--mj-brand-primary);\n        }\n\n        .runs-table[_ngcontent-%COMP%]   th[_ngcontent-%COMP%]   i[_ngcontent-%COMP%] {\n            margin-left: 4px;\n            font-size: 10px;\n        }\n\n        .runs-table[_ngcontent-%COMP%]   td[_ngcontent-%COMP%] {\n            padding: 10px 14px;\n            color: var(--mj-text-primary);\n            border-bottom: 1px solid var(--mj-border-subtle);\n        }\n\n        .runs-table[_ngcontent-%COMP%]   tr.row-even[_ngcontent-%COMP%] {\n            background: var(--mj-bg-surface-card);\n        }\n\n        .runs-table[_ngcontent-%COMP%]   tbody[_ngcontent-%COMP%]   tr[_ngcontent-%COMP%]:hover {\n            background: var(--mj-bg-surface-hover);\n        }\n\n        .cell-timestamp[_ngcontent-%COMP%] {\n            white-space: nowrap;\n            color: var(--mj-text-secondary);\n            font-size: 12px;\n        }\n\n        .cell-prompt[_ngcontent-%COMP%] {\n            font-weight: 600;\n            max-width: 220px;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            white-space: nowrap;\n        }\n\n        .cell-number[_ngcontent-%COMP%] {\n            text-align: right;\n            font-variant-numeric: tabular-nums;\n            white-space: nowrap;\n        }\n\n        .model-tag[_ngcontent-%COMP%] {\n            display: inline-flex;\n            padding: 2px 8px;\n            background: var(--mj-bg-surface-sunken);\n            border-radius: 4px;\n            font-size: 12px;\n            color: var(--mj-text-secondary);\n            white-space: nowrap;\n        }\n\n        .status-pill[_ngcontent-%COMP%] {\n            display: inline-block;\n            padding: 2px 10px;\n            border-radius: 10px;\n            font-size: 12px;\n            font-weight: 600;\n            white-space: nowrap;\n        }\n\n        .pill-completed[_ngcontent-%COMP%] {\n            background: var(--mj-status-success-bg);\n            color: var(--mj-status-success-text);\n        }\n\n        .pill-failed[_ngcontent-%COMP%] {\n            background: var(--mj-status-error-bg);\n            color: var(--mj-status-error-text);\n        }\n\n        .pill-running[_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        .pill-pending[_ngcontent-%COMP%] {\n            background: var(--mj-status-warning-bg);\n            color: var(--mj-status-warning-text);\n        }\n\n        .pill-cancelled[_ngcontent-%COMP%] {\n            background: var(--mj-bg-surface-sunken);\n            color: var(--mj-text-muted);\n        }\n\n        .empty-row[_ngcontent-%COMP%] {\n            text-align: center;\n            color: var(--mj-text-muted);\n            padding: 24px 14px;\n        }\n\n        \n\n\n        .pagination[_ngcontent-%COMP%] {\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            gap: 12px;\n            padding: 12px 20px;\n            border-top: 1px solid var(--mj-border-subtle);\n        }\n\n        .page-btn[_ngcontent-%COMP%] {\n            padding: 6px 12px;\n            border: 1px solid var(--mj-border-default);\n            border-radius: 6px;\n            background: var(--mj-bg-surface);\n            color: var(--mj-text-secondary);\n            cursor: pointer;\n            font-size: 13px;\n            transition: background 0.15s, color 0.15s;\n        }\n\n        .page-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n            background: var(--mj-bg-surface-hover);\n            color: var(--mj-text-primary);\n        }\n\n        .page-btn[_ngcontent-%COMP%]:disabled {\n            opacity: 0.4;\n            cursor: default;\n        }\n\n        .page-info[_ngcontent-%COMP%] {\n            font-size: 13px;\n            color: var(--mj-text-secondary);\n        }\n\n        \n\n\n        @media (max-width: 1200px) {\n            .breakdown-grid[_ngcontent-%COMP%] {\n                grid-template-columns: repeat(2, 1fr);\n            }\n        }\n\n        @media (max-width: 768px) {\n            .stats-grid[_ngcontent-%COMP%] {\n                grid-template-columns: repeat(2, 1fr);\n            }\n\n            .breakdown-grid[_ngcontent-%COMP%] {\n                grid-template-columns: 1fr;\n            }\n\n            .chart-header[_ngcontent-%COMP%] {\n                flex-direction: column;\n                align-items: flex-start;\n                gap: 8px;\n            }\n        }"] });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AnalyticsPromptRunsComponent, [{
        type: Component,
        args: [{ standalone: false, selector: 'app-analytics-prompt-runs', template: `

        @if (IsLoading) {
            <div class="loading-container">
                <mj-loading text="Loading prompt runs..."></mj-loading>
            </div>
        } @else {
            <!-- Stats Summary Bar -->
            <div class="stats-grid">
                <div class="stat-card accent-brand">
                    <div class="stat-label">Total Runs</div>
                    <div class="stat-value">{{ Stats.TotalRuns | number }}</div>
                </div>
                <div class="stat-card">
                    <div class="stat-label">Avg Cost</div>
                    <div class="stat-value">{{ FormatCurrency(Stats.AvgCost, 4) }}</div>
                </div>
                <div class="stat-card">
                    <div class="stat-label">Avg Tokens</div>
                    <div class="stat-value">{{ Stats.AvgTokens | number:'1.0-0' }}</div>
                </div>
                <div class="stat-card">
                    <div class="stat-label">Avg Latency</div>
                    <div class="stat-value">{{ Stats.AvgLatencySeconds | number:'1.2-2' }}s</div>
                </div>
                <div class="stat-card accent-success">
                    <div class="stat-label">Success Rate</div>
                    <div class="stat-value">{{ Stats.SuccessRate | number:'1.1-1' }}%</div>
                </div>
                <div class="stat-card accent-warning">
                    <div class="stat-label">P95 Latency</div>
                    <div class="stat-value">{{ Stats.P95LatencySeconds | number:'1.2-2' }}s</div>
                </div>
                <div class="stat-card">
                    <div class="stat-label">Total Cost</div>
                    <div class="stat-value">{{ FormatCurrency(Stats.TotalCost, 2) }}</div>
                </div>
                <div class="stat-card" title="Share of input tokens served from the provider's prompt cache">
                    <div class="stat-label">Cache Hit Rate</div>
                    <div class="stat-value">{{ Stats.CacheHitRate * 100 | number:'1.1-1' }}%</div>
                </div>
            </div>

            <!-- Chart Panel -->
            <div class="chart-panel">
                <div class="chart-header">
                    <h3 class="chart-title">Runs Over Time</h3>
                    <div class="chart-toggles">
                        @for (metric of ChartMetricOptions; track metric.key) {
                            <button
                                class="toggle-chip"
                                [class.active]="ActiveChartMetric === metric.key"
                                (click)="OnChartMetricChange(metric.key)">
                                {{ metric.label }}
                            </button>
                        }
                    </div>
                </div>
                <div class="chart-area">
                    @if (ChartBuckets.length === 0) {
                        <div class="chart-empty">No data for selected time range</div>
                    } @else {
                        <div class="chart-bars">
                            @for (bucket of ChartBuckets; track bucket.label) {
                                <div
                                    class="chart-bar-wrapper"
                                    [title]="bucket.label + ': ' + bucket.value"
                                    (click)="OnChartBucketClick(bucket)">
                                    <div class="chart-bar-value">{{ FormatChartValue(bucket.value) }}</div>
                                    <div class="chart-bar" [style.height.%]="bucket.heightPercent"></div>
                                    <div class="chart-bar-label">{{ bucket.label }}</div>
                                </div>
                            }
                        </div>
                    }
                </div>
            </div>

            <!-- Breakdown Cards -->
            <div class="breakdown-grid">
                <!-- By Model -->
                <div class="breakdown-card">
                    <h4 class="breakdown-title">By Model</h4>
                    @for (item of ModelBreakdown; track item.id) {
                        <div class="breakdown-row" (click)="ApplyModelFilter(item.id)">
                            <span class="breakdown-name">{{ item.name }}</span>
                            <span class="breakdown-count">{{ item.count }}</span>
                            <div class="breakdown-bar-track">
                                <div class="breakdown-bar-fill" [style.width.%]="item.percentage"></div>
                            </div>
                        </div>
                    }
                    @if (ModelBreakdown.length === 0) {
                        <div class="breakdown-empty">No data</div>
                    }
                </div>

                <!-- By Prompt -->
                <div class="breakdown-card">
                    <h4 class="breakdown-title">By Prompt</h4>
                    @for (item of PromptBreakdown; track item.id) {
                        <div class="breakdown-row" (click)="ApplyPromptFilter(item.id)">
                            <span class="breakdown-name">{{ item.name }}</span>
                            <span class="breakdown-count">{{ item.count }}</span>
                            <div class="breakdown-bar-track">
                                <div class="breakdown-bar-fill" [style.width.%]="item.percentage"></div>
                            </div>
                        </div>
                    }
                    @if (PromptBreakdown.length === 0) {
                        <div class="breakdown-empty">No data</div>
                    }
                </div>

                <!-- By Status -->
                <div class="breakdown-card">
                    <h4 class="breakdown-title">By Status</h4>
                    @for (item of StatusBreakdown; track item.name) {
                        <div class="breakdown-row" (click)="ApplyStatusFilter(item.name)">
                            <span class="status-dot" [class]="item.cssClass"></span>
                            <span class="breakdown-name">{{ item.name }}</span>
                            <span class="breakdown-count">{{ item.count }} ({{ item.percentage | number:'1.1-1' }}%)</span>
                        </div>
                    }
                    @if (StatusBreakdown.length === 0) {
                        <div class="breakdown-empty">No data</div>
                    }
                </div>
            </div>

            <!-- Run Details Table -->
            <div class="table-panel">
                <div class="table-header">
                    <h3 class="table-title">Run Details</h3>
                    <span class="table-count">{{ FilteredRuns.length | number }} runs</span>
                </div>
                <div class="table-scroll">
                    <table class="runs-table">
                        <thead>
                            <tr>
                                @for (col of TableColumns; track col.field) {
                                    <th
                                        [class.sortable]="col.sortable"
                                        [class.sorted]="SortField === col.field"
                                        (click)="col.sortable ? OnSortChange(col.field) : null">
                                        {{ col.label }}
                                        @if (col.sortable && SortField === col.field) {
                                            <i [class]="SortDirection === 'asc' ? 'fa-solid fa-caret-up' : 'fa-solid fa-caret-down'"></i>
                                        }
                                    </th>
                                }
                            </tr>
                        </thead>
                        <tbody>
                            @for (run of PagedRuns; track run.ID; let i = $index) {
                                <tr [class.row-even]="i % 2 === 0">
                                    <td class="cell-timestamp">{{ FormatTimestamp(run.RunAt) }}</td>
                                    <td class="cell-prompt">{{ run.Prompt ?? '(unnamed)' }}</td>
                                    <td><span class="model-tag">{{ run.Model ?? 'N/A' }}</span></td>
                                    <td><span class="status-pill" [class]="GetStatusClass(run.Status)">{{ run.Status }}</span></td>
                                    <td class="cell-number">{{ FormatDuration(run.ExecutionTimeMS) }}</td>
                                    <td class="cell-number" title="Total tokens processed, including cached input">{{ run.TokensUsed != null ? (TrueTotalTokens(run) | number) : '-' }}</td>
                                    <td class="cell-number">{{ FormatCurrency(run.Cost, 4) }}</td>
                                </tr>
                            }
                            @if (PagedRuns.length === 0) {
                                <tr>
                                    <td colspan="7" class="empty-row">No prompt runs found for the selected filters.</td>
                                </tr>
                            }
                        </tbody>
                    </table>
                </div>

                @if (TotalPages > 1) {
                    <div class="pagination">
                        <button
                            class="page-btn"
                            [disabled]="CurrentPage === 1"
                            (click)="OnPageChange(CurrentPage - 1)">
                            <i class="fa-solid fa-chevron-left"></i>
                        </button>
                        <span class="page-info">Page {{ CurrentPage }} of {{ TotalPages }}</span>
                        <button
                            class="page-btn"
                            [disabled]="CurrentPage === TotalPages"
                            (click)="OnPageChange(CurrentPage + 1)">
                            <i class="fa-solid fa-chevron-right"></i>
                        </button>
                    </div>
                }
            </div>
        }
    `, styles: ["\n        :host {\n            display: block;\n        }\n\n        .loading-container {\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            padding: 80px 0;\n        }\n\n        /* \u2500\u2500 Stats Grid \u2500\u2500 */\n\n        .stats-grid {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n            gap: 12px;\n            margin-top: 16px;\n        }\n\n        .stat-card {\n            background: var(--mj-bg-surface);\n            border: 1px solid var(--mj-border-default);\n            border-radius: 10px;\n            padding: 14px 16px;\n            display: flex;\n            flex-direction: column;\n            gap: 4px;\n        }\n\n        .stat-card.accent-brand {\n            border-left: 3px solid var(--mj-brand-primary);\n        }\n\n        .stat-card.accent-success {\n            border-left: 3px solid var(--mj-status-success);\n        }\n\n        .stat-card.accent-warning {\n            border-left: 3px solid var(--mj-status-warning);\n        }\n\n        .stat-label {\n            font-size: 12px;\n            font-weight: 500;\n            color: var(--mj-text-muted);\n            text-transform: uppercase;\n            letter-spacing: 0.4px;\n        }\n\n        .stat-value {\n            font-size: 20px;\n            font-weight: 700;\n            color: var(--mj-text-primary);\n        }\n\n        /* \u2500\u2500 Chart Panel \u2500\u2500 */\n\n        .chart-panel {\n            margin-top: 16px;\n            background: var(--mj-bg-surface);\n            border: 1px solid var(--mj-border-default);\n            border-radius: 12px;\n            padding: 20px;\n        }\n\n        .chart-header {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            margin-bottom: 16px;\n        }\n\n        .chart-title {\n            font-size: 15px;\n            font-weight: 600;\n            color: var(--mj-text-primary);\n            margin: 0;\n        }\n\n        .chart-toggles {\n            display: flex;\n            gap: 4px;\n        }\n\n        .toggle-chip {\n            padding: 4px 12px;\n            border: 1px solid var(--mj-border-default);\n            border-radius: 16px;\n            background: var(--mj-bg-surface);\n            color: var(--mj-text-secondary);\n            font-size: 12px;\n            font-weight: 500;\n            cursor: pointer;\n            transition: background 0.15s, color 0.15s, border-color 0.15s;\n        }\n\n        .toggle-chip:hover {\n            background: var(--mj-bg-surface-hover);\n            color: var(--mj-text-primary);\n        }\n\n        .toggle-chip.active {\n            background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n            color: var(--mj-brand-primary);\n            border-color: var(--mj-brand-primary);\n            font-weight: 600;\n        }\n\n        .chart-area {\n            height: 220px;\n            display: flex;\n            align-items: flex-end;\n        }\n\n        .chart-empty {\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            width: 100%;\n            height: 100%;\n            color: var(--mj-text-muted);\n            font-size: 13px;\n        }\n\n        .chart-bars {\n            display: flex;\n            align-items: flex-end;\n            gap: 4px;\n            width: 100%;\n            height: 100%;\n            padding-bottom: 24px;\n        }\n\n        .chart-bar-wrapper {\n            flex: 1;\n            min-width: 0;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            cursor: pointer;\n            position: relative;\n            height: 100%;\n            justify-content: flex-end;\n        }\n\n        .chart-bar-value {\n            font-size: 10px;\n            color: var(--mj-text-muted);\n            margin-bottom: 4px;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            max-width: 100%;\n        }\n\n        .chart-bar {\n            width: 80%;\n            min-height: 2px;\n            background: color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n            border-radius: 4px 4px 0 0;\n            transition: background 0.15s, height 0.3s;\n        }\n\n        .chart-bar-wrapper:hover .chart-bar {\n            background: color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-bg-surface));\n        }\n\n        .chart-bar-label {\n            font-size: 10px;\n            color: var(--mj-text-muted);\n            margin-top: 6px;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            max-width: 100%;\n            text-align: center;\n            position: absolute;\n            bottom: 0;\n        }\n\n        /* \u2500\u2500 Breakdown Cards \u2500\u2500 */\n\n        .breakdown-grid {\n            display: grid;\n            grid-template-columns: repeat(3, 1fr);\n            gap: 12px;\n            margin-top: 16px;\n        }\n\n        .breakdown-card {\n            background: var(--mj-bg-surface);\n            border: 1px solid var(--mj-border-default);\n            border-radius: 10px;\n            padding: 16px;\n        }\n\n        .breakdown-title {\n            font-size: 13px;\n            font-weight: 600;\n            color: var(--mj-text-primary);\n            margin: 0 0 12px;\n        }\n\n        .breakdown-row {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            padding: 6px 0;\n            cursor: pointer;\n            border-radius: 4px;\n            transition: background 0.1s;\n        }\n\n        .breakdown-row:hover {\n            background: var(--mj-bg-surface-hover);\n        }\n\n        .breakdown-name {\n            flex: 1;\n            font-size: 13px;\n            color: var(--mj-text-primary);\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            min-width: 0;\n        }\n\n        .breakdown-count {\n            font-size: 12px;\n            color: var(--mj-text-secondary);\n            font-weight: 600;\n            white-space: nowrap;\n        }\n\n        .breakdown-bar-track {\n            width: 60px;\n            height: 6px;\n            background: var(--mj-bg-surface-sunken);\n            border-radius: 3px;\n            overflow: hidden;\n            flex-shrink: 0;\n        }\n\n        .breakdown-bar-fill {\n            height: 100%;\n            background: var(--mj-brand-primary);\n            border-radius: 3px;\n            transition: width 0.3s;\n        }\n\n        .breakdown-empty {\n            font-size: 13px;\n            color: var(--mj-text-muted);\n            padding: 8px 0;\n        }\n\n        .status-dot {\n            width: 8px;\n            height: 8px;\n            border-radius: 50%;\n            flex-shrink: 0;\n        }\n\n        .status-dot.dot-completed { background: var(--mj-status-success); }\n        .status-dot.dot-failed { background: var(--mj-status-error); }\n        .status-dot.dot-running { background: var(--mj-brand-primary); }\n        .status-dot.dot-pending { background: var(--mj-status-warning); }\n        .status-dot.dot-cancelled { background: var(--mj-text-muted); }\n\n        /* \u2500\u2500 Table Panel \u2500\u2500 */\n\n        .table-panel {\n            margin-top: 16px;\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-header {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            padding: 16px 20px;\n            border-bottom: 1px solid var(--mj-border-subtle);\n        }\n\n        .table-title {\n            font-size: 15px;\n            font-weight: 600;\n            color: var(--mj-text-primary);\n            margin: 0;\n        }\n\n        .table-count {\n            font-size: 12px;\n            color: var(--mj-text-muted);\n            font-weight: 500;\n        }\n\n        .table-scroll {\n            overflow-x: auto;\n        }\n\n        .runs-table {\n            width: 100%;\n            border-collapse: collapse;\n            font-size: 13px;\n        }\n\n        .runs-table th {\n            padding: 10px 14px;\n            text-align: left;\n            font-weight: 600;\n            font-size: 12px;\n            color: var(--mj-text-secondary);\n            text-transform: uppercase;\n            letter-spacing: 0.4px;\n            border-bottom: 1px solid var(--mj-border-default);\n            background: var(--mj-bg-surface-card);\n            white-space: nowrap;\n            user-select: none;\n        }\n\n        .runs-table th.sortable {\n            cursor: pointer;\n        }\n\n        .runs-table th.sortable:hover {\n            color: var(--mj-text-primary);\n        }\n\n        .runs-table th.sorted {\n            color: var(--mj-brand-primary);\n        }\n\n        .runs-table th i {\n            margin-left: 4px;\n            font-size: 10px;\n        }\n\n        .runs-table td {\n            padding: 10px 14px;\n            color: var(--mj-text-primary);\n            border-bottom: 1px solid var(--mj-border-subtle);\n        }\n\n        .runs-table tr.row-even {\n            background: var(--mj-bg-surface-card);\n        }\n\n        .runs-table tbody tr:hover {\n            background: var(--mj-bg-surface-hover);\n        }\n\n        .cell-timestamp {\n            white-space: nowrap;\n            color: var(--mj-text-secondary);\n            font-size: 12px;\n        }\n\n        .cell-prompt {\n            font-weight: 600;\n            max-width: 220px;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            white-space: nowrap;\n        }\n\n        .cell-number {\n            text-align: right;\n            font-variant-numeric: tabular-nums;\n            white-space: nowrap;\n        }\n\n        .model-tag {\n            display: inline-flex;\n            padding: 2px 8px;\n            background: var(--mj-bg-surface-sunken);\n            border-radius: 4px;\n            font-size: 12px;\n            color: var(--mj-text-secondary);\n            white-space: nowrap;\n        }\n\n        .status-pill {\n            display: inline-block;\n            padding: 2px 10px;\n            border-radius: 10px;\n            font-size: 12px;\n            font-weight: 600;\n            white-space: nowrap;\n        }\n\n        .pill-completed {\n            background: var(--mj-status-success-bg);\n            color: var(--mj-status-success-text);\n        }\n\n        .pill-failed {\n            background: var(--mj-status-error-bg);\n            color: var(--mj-status-error-text);\n        }\n\n        .pill-running {\n            background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n            color: var(--mj-brand-primary);\n        }\n\n        .pill-pending {\n            background: var(--mj-status-warning-bg);\n            color: var(--mj-status-warning-text);\n        }\n\n        .pill-cancelled {\n            background: var(--mj-bg-surface-sunken);\n            color: var(--mj-text-muted);\n        }\n\n        .empty-row {\n            text-align: center;\n            color: var(--mj-text-muted);\n            padding: 24px 14px;\n        }\n\n        /* \u2500\u2500 Pagination \u2500\u2500 */\n\n        .pagination {\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            gap: 12px;\n            padding: 12px 20px;\n            border-top: 1px solid var(--mj-border-subtle);\n        }\n\n        .page-btn {\n            padding: 6px 12px;\n            border: 1px solid var(--mj-border-default);\n            border-radius: 6px;\n            background: var(--mj-bg-surface);\n            color: var(--mj-text-secondary);\n            cursor: pointer;\n            font-size: 13px;\n            transition: background 0.15s, color 0.15s;\n        }\n\n        .page-btn:hover:not(:disabled) {\n            background: var(--mj-bg-surface-hover);\n            color: var(--mj-text-primary);\n        }\n\n        .page-btn:disabled {\n            opacity: 0.4;\n            cursor: default;\n        }\n\n        .page-info {\n            font-size: 13px;\n            color: var(--mj-text-secondary);\n        }\n\n        /* \u2500\u2500 Responsive \u2500\u2500 */\n\n        @media (max-width: 1200px) {\n            .breakdown-grid {\n                grid-template-columns: repeat(2, 1fr);\n            }\n        }\n\n        @media (max-width: 768px) {\n            .stats-grid {\n                grid-template-columns: repeat(2, 1fr);\n            }\n\n            .breakdown-grid {\n                grid-template-columns: 1fr;\n            }\n\n            .chart-header {\n                flex-direction: column;\n                align-items: flex-start;\n                gap: 8px;\n            }\n        }\n    "] }]
    }], null, { TimeRange: [{
            type: Input
        }], Filters: [{
            type: Input
        }], TimeRangeChange: [{
            type: Output
        }], FiltersChange: [{
            type: Output
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AnalyticsPromptRunsComponent, { className: "AnalyticsPromptRunsComponent", filePath: "src/AI/components/analytics/prompt-runs/prompt-run-analysis.component.ts", lineNumber: 773 }); })();
export function LoadAnalyticsPromptRuns() {
    // Prevents tree-shaking of the component
}
//# sourceMappingURL=prompt-run-analysis.component.js.map