1/**
2 * Shapes merged daily totals into the per-day provider stacks both chart
3 * implementations (Swift Charts on iOS, plain views elsewhere) render.
4 *
5 * @module usageChartData
6 */
7import type { UsageProviderKind } from "@t3tools/contracts";
8import type { DailyTotals } from "@t3tools/shared/usageMerge";
9
10import { PROVIDER_ORDER } from "./usageProviders";
11
12export type UsageChartMetric = "cost" | "tokens";
13
14export interface UsageChartDay {
15 readonly day: string;
16 /** In {@link PROVIDER_ORDER}, i.e. bottom of the stack first. */
17 readonly values: readonly { readonly provider: UsageProviderKind; readonly value: number }[];
18 readonly total: number;
19}
20
21/** One entry per day in the window, zero-filled where nothing happened. */
22export function buildChartDays(
23 days: readonly string[],
24 daily: readonly DailyTotals[],
25 metric: UsageChartMetric,
26): readonly UsageChartDay[] {
27 const byDay = new Map(daily.map((totals) => [totals.day, totals]));
28 return days.map((day) => {
29 const totals = byDay.get(day);
30 const values = PROVIDER_ORDER.map((provider) => {
31 const entry = totals?.byProvider.get(provider);
32 const value = entry === undefined ? 0 : metric === "cost" ? entry.costUsd : entry.totalTokens;
33 return { provider, value };
34 });
35 return {
36 day,
37 values,
38 total: values.reduce((sum, entry) => sum + entry.value, 0),
39 };
40 });
41}