import type {
  CapacityAccountRecord,
  CapacityReportSection,
  CapacityUsageBreakdown,
  ObservabilityReportQuery,
  ReportCoverageGap,
  ReportCoverageStatus,
} from "@overdeck/report-contract";
import type { AgentsPanelData, ClusterPanelData } from "../adapters/cluster";
import type { FactoryRunView } from "../adapters/factory";
import type { SessionsPanelData } from "../adapters/sessions";
import type { SystrayPanelData } from "../adapters/systray";

const CAPACITY_ATTEMPT_LIMIT = 2_000;

type UsageDimension = "model" | "account" | "host" | "project";

interface CapacityAttempt {
  runId: string;
  succeededRun: boolean;
  project?: string;
  model?: string;
  account?: string;
  host?: string;
  tokens: number | null;
  cost: number | null;
  estimatedCost: boolean;
}

export interface CapacityReportInput {
  factoryRuns?: FactoryRunView[];
  limits?: SystrayPanelData;
  sessions?: SessionsPanelData;
  agents?: AgentsPanelData;
  cluster?: ClusterPanelData;
}

function timestamp(value: string | null | undefined): number | undefined {
  if (!value) return undefined;
  const parsed = Date.parse(value);
  return Number.isFinite(parsed) ? parsed : undefined;
}

function runProject(run: FactoryRunView): string | undefined {
  if (run.repoName?.trim()) return run.repoName.trim();
  const normalized = run.repo?.replace(/\\/g, "/").replace(/\/$/, "");
  return normalized?.split("/").at(-1) || undefined;
}

function runSucceeded(run: FactoryRunView): boolean {
  return ["success", "succeeded", "completed", "passed"].includes(run.status?.trim().toLocaleLowerCase() ?? "");
}

function attemptInRange(startedAt: string | null, endedAt: string | null, fromMs: number, toMs: number): boolean {
  const start = timestamp(startedAt);
  const end = timestamp(endedAt) ?? start;
  return start !== undefined && start <= toMs && (end ?? start) >= fromMs;
}

function recordedAttempt(run: FactoryRunView, attempt: FactoryRunView["attempts"][number]): CapacityAttempt {
  const usage = attempt.usage;
  const estimatedCost = usage?.usageEstimated === true;
  return {
    runId: run.adwId,
    succeededRun: runSucceeded(run),
    project: runProject(run),
    model: attempt.model?.trim() || undefined,
    account: attempt.account?.trim() || undefined,
    host: attempt.host?.trim() || undefined,
    tokens: usage?.totalTokens ?? attempt.tokens,
    cost: usage && !estimatedCost ? usage.totalCost : null,
    estimatedCost,
  };
}

function usageBreakdown(attempts: CapacityAttempt[], dimension: UsageDimension): CapacityUsageBreakdown[] {
  const groups = new Map<string, CapacityAttempt[]>();
  for (const attempt of attempts) {
    const value = attempt[dimension]?.trim();
    const key = value || "__unattributed__";
    const rows = groups.get(key) ?? [];
    rows.push(attempt);
    groups.set(key, rows);
  }
  return [...groups].map(([key, rows]) => {
    const costs = rows.map((row) => row.cost);
    return {
      key,
      label: key === "__unattributed__" ? "Unattributed" : key,
      tokens: rows.reduce((total, row) => total + (row.tokens ?? 0), 0),
      cost: costs.every((cost) => cost !== null)
        ? costs.reduce<number>((total, cost) => total + (cost ?? 0), 0)
        : null,
      attempts: rows.length,
      unattributed: key === "__unattributed__",
    };
  }).sort((left, right) => right.tokens - left.tokens || right.attempts - left.attempts || left.label.localeCompare(right.label));
}

function accountRecords(limits: SystrayPanelData | undefined): CapacityAccountRecord[] {
  if (!limits) return [];
  return limits.accounts.map((account) => {
    const resetMs = account.window.primaryResetAt ?? account.window.secondaryResetAt;
    return {
      id: account.slug,
      label: account.label,
      provider: account.provider,
      usedPercent: account.percent,
      status: account.status,
      spendAmount: account.spend?.amount ?? null,
      spendLimit: account.spend?.limit ?? null,
      currency: account.spend?.currency ?? null,
      ...(resetMs !== null ? { resetAt: new Date(resetMs).toISOString() } : {}),
    };
  }).sort((left, right) => (right.usedPercent ?? -1) - (left.usedPercent ?? -1) || left.label.localeCompare(right.label));
}

export function buildCapacityReportSection(
  query: ObservabilityReportQuery,
  input: CapacityReportInput,
): CapacityReportSection {
  const fromMs = Date.parse(query.from);
  const toMs = Date.parse(query.to);
  const allAttempts = (input.factoryRuns ?? []).flatMap((run) => run.attempts
    .filter((attempt) => attemptInRange(attempt.startedAt, attempt.endedAt, fromMs, toMs))
    .filter(() => !query.projects?.length || (runProject(run) !== undefined && query.projects.includes(runProject(run)!)))
    .filter((attempt) => !query.q || [runProject(run), attempt.model, attempt.account, attempt.host]
      .some((value) => value?.toLocaleLowerCase().includes(query.q!.toLocaleLowerCase())))
    .map((attempt) => recordedAttempt(run, attempt)));
  const attempts = allAttempts.slice(0, CAPACITY_ATTEMPT_LIMIT);
  const truncated = allAttempts.length > attempts.length;
  const gaps: ReportCoverageGap[] = [];
  if (!input.factoryRuns) gaps.push({ domain: "capacity", sourceId: "factory", reason: "Factory usage records are unavailable for this report." });
  if (!input.limits) gaps.push({ domain: "capacity", sourceId: "limits", reason: "Account-window records are unavailable for this report." });
  if (!input.sessions) gaps.push({ domain: "capacity", sourceId: "sessions", reason: "Session capacity records are unavailable for this report." });
  if (!input.agents) gaps.push({ domain: "capacity", sourceId: "agents", reason: "Live agent workload is unavailable for this report." });
  if (!input.cluster) gaps.push({ domain: "capacity", sourceId: "cluster", reason: "Build queue capacity is unavailable for this report." });
  if (input.sessions?.ledgerMissing) gaps.push({ domain: "capacity", sourceId: "sessions", reason: "The session ledger has not recorded capacity yet." });
  if (input.sessions?.unreadableFiles.length) gaps.push({ domain: "capacity", sourceId: "sessions", reason: `${input.sessions.unreadableFiles.length.toLocaleString()} session ${input.sessions.unreadableFiles.length === 1 ? "record could" : "records could"} not be read.` });
  if (input.sessions?.hostsRegistryMissing) gaps.push({ domain: "capacity", sourceId: "sessions", reason: "Session host enrollment is unavailable." });
  if (input.limits?.stale) gaps.push({ domain: "capacity", sourceId: "limits", reason: "Account-window records are out of date." });
  if (truncated) gaps.push({ domain: "capacity", sourceId: "factory", reason: `Usage detail is limited to ${CAPACITY_ATTEMPT_LIMIT.toLocaleString()} matching attempts.` });
  const missingTokens = attempts.filter((attempt) => attempt.tokens === null).length;
  const missingCosts = attempts.filter((attempt) => attempt.cost === null).length;
  const estimatedCosts = attempts.filter((attempt) => attempt.estimatedCost).length;
  if (missingTokens > 0) gaps.push({ domain: "capacity", sourceId: "factory", metric: "tokens", reason: `${missingTokens.toLocaleString()} matching ${missingTokens === 1 ? "attempt has" : "attempts have"} no recorded token total.` });
  if (missingCosts > 0) gaps.push({ domain: "capacity", sourceId: "factory", metric: "cost", reason: `${missingCosts.toLocaleString()} matching ${missingCosts === 1 ? "attempt has" : "attempts have"} no recorded provider cost.` });
  if (estimatedCosts > 0) gaps.push({ domain: "capacity", sourceId: "factory", metric: "cost", reason: `${estimatedCosts.toLocaleString()} estimated cost ${estimatedCosts === 1 ? "record is" : "records are"} excluded from reported provider cost.` });
  const attributedAttempts = attempts.filter((attempt) => attempt.account && attempt.model && attempt.host && attempt.project).length;
  const recordedTokens = attempts.filter((attempt) => attempt.tokens !== null);
  const recordedCosts = attempts.filter((attempt) => attempt.cost !== null);
  const succeededAttempts = attempts.filter((attempt) => attempt.succeededRun);
  const succeededRunIds = new Set(succeededAttempts.map((attempt) => attempt.runId));
  const succeededCostComplete = succeededAttempts.length > 0 && succeededAttempts.every((attempt) => attempt.cost !== null);
  const succeededCost = succeededCostComplete
    ? succeededAttempts.reduce((total, attempt) => total + (attempt.cost ?? 0), 0)
    : null;
  const availableSources = [input.factoryRuns, input.limits, input.sessions, input.agents, input.cluster]
    .filter((source) => source !== undefined).length;
  const status: ReportCoverageStatus = availableSources === 0
    ? "unavailable"
    : availableSources < 5 || gaps.some((gap) => gap.metric !== undefined) || truncated
      ? "partial"
      : input.limits?.stale
        ? "stale"
        : "complete";

  return {
    kind: "capacity",
    status,
    title: "Capacity, accounts, and spend",
    metrics: [
      { id: "recorded-tokens", label: "Recorded tokens", value: recordedTokens.length > 0 ? recordedTokens.reduce((total, attempt) => total + (attempt.tokens ?? 0), 0) : attempts.length === 0 && input.factoryRuns ? 0 : null, unit: "tokens", coverage: !input.factoryRuns ? "unavailable" : missingTokens > 0 || truncated ? "partial" : "complete" },
      { id: "recorded-cost", label: "Recorded provider cost", value: recordedCosts.length > 0 ? recordedCosts.reduce((total, attempt) => total + (attempt.cost ?? 0), 0) : null, unit: "currency", numerator: recordedCosts.length, denominator: attempts.length, coverage: !input.factoryRuns ? "unavailable" : missingCosts > 0 || truncated ? "partial" : "complete" },
      { id: "active-sessions", label: "Active sessions", value: input.sessions ? input.sessions.sessions.filter((session) => !session.finishedAt).length + input.sessions.boxResident.length : null, unit: "count", coverage: input.sessions ? input.sessions.ledgerMissing || input.sessions.hostsRegistryMissing ? "partial" : "complete" : "unavailable" },
      { id: "queued-builds", label: "Queued builds", value: input.cluster?.buildslot.queued ?? null, unit: "count", coverage: input.cluster ? "complete" : "unavailable" },
    ],
    byModel: usageBreakdown(attempts, "model"),
    byAccount: usageBreakdown(attempts, "account"),
    byHost: usageBreakdown(attempts, "host"),
    byProject: usageBreakdown(attempts, "project"),
    accounts: accountRecords(input.limits),
    snapshot: {
      activeSessions: input.sessions ? input.sessions.sessions.filter((session) => !session.finishedAt).length + input.sessions.boxResident.length : null,
      liveAgents: input.agents?.totalLive ?? null,
      runningBuilds: input.cluster?.buildslot.running ?? null,
      queuedBuilds: input.cluster?.buildslot.queued ?? null,
      buildWaitP95Ms: input.cluster?.buildslot.p95WaitSeconds !== null && input.cluster?.buildslot.p95WaitSeconds !== undefined ? input.cluster.buildslot.p95WaitSeconds * 1_000 : null,
    },
    costPerSucceededRun: succeededCost !== null && succeededRunIds.size > 0 && !truncated ? succeededCost / succeededRunIds.size : null,
    gaps: attributedAttempts < attempts.length
      ? [...gaps, { domain: "capacity", sourceId: "factory", reason: `${(attempts.length - attributedAttempts).toLocaleString()} matching ${attempts.length - attributedAttempts === 1 ? "attempt is" : "attempts are"} missing an explicit model, account, host, or project attribution.` }]
      : gaps,
    truncated,
    errors: [],
  };
}
