import { and, eq, inArray } from 'drizzle-orm';
import type { DrizzleClient } from '@/server/db/client.js';
import { monitorChecks } from '@/server/db/schema.js';
import type { MonitorCheckRecord } from '@/server/db/schema.js';
import { scrubStringValue } from '@/server/observability/pii-scrub.js';

export async function listMonitorCheckRows(db: DrizzleClient): Promise<MonitorCheckRecord[]> {
  return db.select().from(monitorChecks);
}

export async function countFiringMonitorChecks(db: DrizzleClient): Promise<number> {
  const rows = await db
    .select({ key: monitorChecks.key })
    .from(monitorChecks)
    .where(
      and(eq(monitorChecks.enabled, true), inArray(monitorChecks.lastSeverity, ['warn', 'page'])),
    );
  return rows.length;
}

export async function getMonitorCheckRow(
  db: DrizzleClient,
  key: string,
): Promise<MonitorCheckRecord | null> {
  const rows = await db.select().from(monitorChecks).where(eq(monitorChecks.key, key)).limit(1);
  return rows[0] ?? null;
}

/** Seed a row with adapter defaults if absent (idempotent — used at first run / registry sync). */
export async function ensureMonitorCheckRow(
  db: DrizzleClient,
  key: string,
  defaults: {
    enabled: boolean;
    config: Record<string, unknown>;
    severityFloor?: string | null;
    intervalHours?: number | null;
  },
): Promise<void> {
  await db
    .insert(monitorChecks)
    .values({
      key,
      enabled: defaults.enabled,
      config: defaults.config,
      severityFloor: defaults.severityFloor ?? null,
      intervalHours: defaults.intervalHours ?? null,
    })
    .onConflictDoNothing({ target: monitorChecks.key });
}

export async function updateMonitorCheck(
  db: DrizzleClient,
  key: string,
  fields: {
    enabled?: boolean;
    config?: Record<string, unknown>;
    severityFloor?: string | null;
    intervalHours?: number | null;
    includeInDigest?: boolean;
  },
): Promise<MonitorCheckRecord | null> {
  const patch: Record<string, unknown> = { updatedAt: new Date() };
  if (fields.enabled !== undefined) patch.enabled = fields.enabled;
  if (fields.config !== undefined) patch.config = fields.config;
  if (fields.severityFloor !== undefined) patch.severityFloor = fields.severityFloor;
  if (fields.intervalHours !== undefined) patch.intervalHours = fields.intervalHours;
  if (fields.includeInDigest !== undefined) patch.includeInDigest = fields.includeInDigest;
  const [row] = await db
    .update(monitorChecks)
    .set(patch)
    .where(eq(monitorChecks.key, key))
    .returning();
  return row ?? null;
}

/** Persist last-run state after a check executes. */
export async function recordCheckRun(
  db: DrizzleClient,
  key: string,
  severity: string,
  detail: string,
  now: Date,
): Promise<void> {
  await db
    .update(monitorChecks)
    .set({
      lastRunAt: now,
      lastSeverity: severity,
      lastDetail: scrubStringValue(detail),
      updatedAt: now,
    })
    .where(eq(monitorChecks.key, key));
}
