import type { JsonValue } from "../../shared/src/index";
import type {
  EgressTcpConnection,
  HttpTunnelWaiter,
  LoggerFn,
  MicroserviceAvailabilityEntry,
  MicroserviceProxyCacheEntry,
  OperationPerformanceSample,
  ProviderSocket,
  RawTaskRow,
  RequestPerformanceSample,
  RuntimeConfig,
  SqlClient,
  TaskTerminalWaiter,
} from "./types";

export const ctx = {
  sql: null as SqlClient | null,
  config: null as RuntimeConfig | null,
  logger: null as LoggerFn | null,
  dbReady: false,
  serviceStartedAt: new Date(),
  activeProviders: new Map<string, ProviderSocket>(),
  activeSshClients: new Map<string, ProviderSocket>(),
  activeEgressTcpConnections: new Map<string, EgressTcpConnection>(),
  httpTunnelWaiters: new Map<string, HttpTunnelWaiter>(),
  taskTerminalWaiters: new Map<string, Set<TaskTerminalWaiter>>(),
  microserviceProxyCache: new Map<string, MicroserviceProxyCacheEntry>(),
  microserviceProxyRefreshes: new Map<string, Promise<void>>(),
  microserviceAvailabilityCache: new Map<string, MicroserviceAvailabilityEntry>(),
  microserviceAvailabilityRefreshes: new Map<string, Promise<Record<string, JsonValue>>>(),
  activeScheduledRuns: new Set<string>(),
  recentLogs: [] as unknown[],
  requestPerformanceSamples: [] as RequestPerformanceSample[],
  operationPerformanceSamples: [] as OperationPerformanceSample[],
  lastTaskSweepAt: 0,
  taskSweepInFlight: null as Promise<void> | null,
};

export function sql(): SqlClient {
  if (ctx.sql === null) throw new Error("database not initialized");
  return ctx.sql;
}

export function config(): RuntimeConfig {
  if (ctx.config === null) throw new Error("config not initialized");
  return ctx.config;
}

export function logger(level: "debug" | "info" | "warn" | "error", message: string, data?: JsonValue): void {
  if (ctx.logger !== null) ctx.logger(level, message, data);
}
