/**
 * Cron: Group Deal Deadline - runs every minute.
 *
 * Checks for group deals that have passed their effective deadline
 * (COALESCE(extendedDeadline, deals.windowEnd)).
 *
 * - If currentReservationCount >= minGroupSize: deal succeeded → executeGroupDeal
 * - If currentReservationCount < minGroupSize:
 *   - ALL_OR_NOTHING → failGroupDeal (full cancel + refund all holds)
 *   - MINIMUM_THRESHOLD → handlePartialExecution (24h vendor decision window)
 *
 * Batch size capped at 50 per invocation (Workers CPU limit).
 */

import { createDbService } from '@/server/services/db.js';
import { sql } from 'drizzle-orm';
import { withSentry } from '@/server/observability/with-sentry';
import { env as runtimeEnv } from '@/server/env.js';
import { buildServices } from '@/server/services/bundle.js';
import type { CronEnv } from './deal-expiry.js';

const BATCH_SIZE = 50;

const noopPush = {
  sendToUser: async () => {},
  sendToVendor: async () => {},
};

export const runGroupDealDeadline = withSentry(
  async function runGroupDealDeadline(env: CronEnv): Promise<void> {
    const db = createDbService({ DATABASE_URL: env.DATABASE_URL });

    try {
      const { executeGroupDeal, failGroupDeal, handlePartialExecution } =
        await import('@/server/workflows/group-deal.js');

      const services = await buildServices(runtimeEnv);
      const deps = {
        db,
        push: noopPush,
        qrSecret: env.QR_SECRET ?? '',
        doClient: services.doClient,
        payments: services.payments,
        storage: services.storage,
      };

      const expiredGroups = await db.execute(sql`
      SELECT
        gd.id,
        gd.deal_id,
        gd.group_state,
        gd.current_reservation_count,
        gd.min_group_size,
        gd.fill_rule,
        gd.extended_deadline,
        d.window_end
      FROM group_deals gd
      JOIN deals d ON d.id = gd.deal_id
      WHERE gd.group_state IN ('COLLECTING', 'THRESHOLD_MET', 'EXTENDED')
        AND COALESCE(gd.extended_deadline, d.window_end) <= NOW()
      LIMIT ${BATCH_SIZE}
    `);

      const rows = expiredGroups.rows as Array<{
        id: string;
        deal_id: string;
        group_state: string;
        current_reservation_count: number;
        min_group_size: number;
        fill_rule: string;
        extended_deadline: Date | null;
        window_end: Date | null;
      }>;

      for (const row of rows) {
        if (row.current_reservation_count >= row.min_group_size) {
          await executeGroupDeal(deps, row.id);
        } else {
          if (row.fill_rule === 'ALL_OR_NOTHING') {
            await failGroupDeal(deps, row.id);
          } else {
            await handlePartialExecution(deps, row.id);
          }
        }
      }
    } catch (err) {
      if (err instanceof Error && err.message.includes('Cannot find module')) {
        return;
      }
      throw err;
    }
  },
  { name: 'cron.group-deal-deadline', kind: 'cron' },
);
