import { createDbService } from '@/server/services/db.js';
import { sql } from 'drizzle-orm';
import { formatAgorotShekels } from '@/lib/money.js';
import type { AlertSeverity } from '@/server/cron/settlement-monitor.js';
import { redactError } from '../redact.js';
import type { CheckAdapter, CheckContext, CheckResult } from '../types.js';

export interface HoldsAgedMetrics {
  heldSumAgorot: number;
  oldestHeldDays: number;
}
export interface HoldsAgedConfig {
  maxAgeDays: number;
}

export function evaluateHoldsAged(
  m: HoldsAgedMetrics,
  cfg: HoldsAgedConfig,
): { severity: AlertSeverity; detail: string } {
  if (m.oldestHeldDays > cfg.maxAgeDays) {
    return {
      severity: 'page',
      detail: `oldest held release is ${m.oldestHeldDays}d old (> ${cfg.maxAgeDays}d), held sum ${formatAgorotShekels(m.heldSumAgorot)}`,
    };
  }
  return {
    severity: 'info',
    detail: `oldest held ${m.oldestHeldDays}d, held sum ${formatAgorotShekels(m.heldSumAgorot)}`,
  };
}

export const settlementHoldsAged: CheckAdapter = {
  key: 'settlement_holds_aged',
  title: 'Aged settlement holds',
  defaultConfig: { maxAgeDays: 14 },
  defaultIntervalHours: 6,
  async run(ctx: CheckContext): Promise<CheckResult> {
    const cfg = { maxAgeDays: Number(ctx.config.maxAgeDays ?? 14) };
    try {
      const db = createDbService({ DATABASE_URL: ctx.env.DATABASE_URL });
      const res = await db.execute<{ held_sum: number; oldest: string | null }>(sql`
        SELECT COALESCE(SUM(net_amount_agorot), 0)::bigint AS held_sum,
               MIN(held_at) AS oldest
        FROM vendor_payout_releases
        WHERE status = 'held'
      `);
      const row = res.rows[0];
      const oldest = row?.oldest ? new Date(row.oldest) : null;
      const oldestHeldDays = oldest
        ? Math.floor((ctx.now.getTime() - oldest.getTime()) / 86_400_000)
        : 0;
      const m: HoldsAgedMetrics = {
        heldSumAgorot: Number(row?.held_sum ?? 0),
        oldestHeldDays,
      };
      const ev = evaluateHoldsAged(m, cfg);
      return {
        key: this.key,
        severity: ev.severity,
        title: this.title,
        detail: ev.detail,
        metrics: { heldSumAgorot: m.heldSumAgorot, oldestHeldDays },
      };
    } catch (err) {
      return {
        key: this.key,
        severity: 'warn',
        degraded: true,
        title: this.title,
        detail: redactError(err, 'check threw'),
      };
    }
  },
};
