/**
 * SupportCase lifecycle alarm handlers.
 *
 * Called from SupportCaseDO.alarm().
 * Pattern mirrors group-holds.ts — reads row, verifies state, then acts.
 *
 * Phase-4 policy (locked):
 *   vendor_window_expires_at → escalated → human_review (two hops logged)
 *   Phase 5 will flip the second hop to ai_handling behind a feature flag.
 *
 * The single switchpoint is the 'vendor_window_expires_at' case below.
 */

import { eq } from 'drizzle-orm';
import type { DoTxDbClient } from '../lib/db.js';
import { transactionCases } from '@/server/db/schema';
import { captureCaught } from '@/server/observability/capture.server';
import { asCaseId } from '@/server/platform-seams/ids.js';
import {
  transitionSupportCaseTimeout,
  autocloseSupportCase,
} from '@/server/db/queries/do-lifecycle.js';

export type CaseAlarmKind =
  | 'vendor_window_50pct'
  | 'vendor_window_expires_at'
  | 'sla_ai_due_at'
  | 'sla_human_due_at'
  | 'autoclose_at';

export interface SupportCaseAlarmDeps {
  db: DoTxDbClient;
  enqueueOutbox: (kind: string, body: unknown) => Promise<void>;
  sendVendorPush?: (vendorId: string, payload: unknown) => Promise<void>;
}

export async function handleSupportCaseAlarm(
  deps: SupportCaseAlarmDeps,
  args: { caseId: string; alarm: CaseAlarmKind },
): Promise<{ acted: boolean; newStatus?: string }> {
  const [row] = await deps.db
    .select()
    .from(transactionCases)
    .where(eq(transactionCases.id, asCaseId(args.caseId)))
    .limit(1);

  if (!row) return { acted: false };

  switch (args.alarm) {
    case 'vendor_window_50pct': {
      // Race guard: only act if still in vendor_review
      if (row.status !== 'vendor_review') return { acted: false };

      if (deps.sendVendorPush) {
        await deps
          .sendVendorPush(row.vendorId, {
            title: 'מקרה ממתין לתגובה',
            body: 'חלון הזמן לתגובה על מקרה הלקוח עומד לפוג. אנא הגיבו בהקדם.',
            data: { type: 'case_vendor_window_50pct', caseId: row.id },
          })
          .catch((err) => {
            captureCaught(err, {
              scope: 'server.do-host.lifecycle.support-cases',
              severity: 'warning',
            });
          });
      }

      await deps.enqueueOutbox('support.notif.push', {
        userKind: 'vendor',
        caseId: row.id,
        templateKey: 'vendor_window_50pct',
      });

      return { acted: true };
    }

    case 'vendor_window_expires_at': {
      // Race guard: only act if still in vendor_review
      if (row.status !== 'vendor_review') return { acted: false };

      // Phase-4 policy: two sequential transitions + two log rows
      await transitionSupportCaseTimeout(deps.db, row.id);

      await deps.enqueueOutbox('support.notif.email', {
        caseId: row.id,
        templateKey: 'vendor_window_expired',
      });
      // AI agent will notify/escalate as needed — enqueue AI dispatch
      await deps.enqueueOutbox('support.ai.dispatch', {
        parentType: 'case',
        parentId: row.id,
        trigger: 'vendor_timeout',
      });

      return { acted: true, newStatus: 'ai_handling' };
    }

    case 'sla_ai_due_at':
    case 'sla_human_due_at': {
      // Phase 5: trigger AI agent / alert human agent. Phase 4: log + push admin.
      if (row.status !== 'ai_handling' && row.status !== 'human_review') return { acted: false };

      await deps.enqueueOutbox('support.notif.email', {
        caseId: row.id,
        templateKey: 'sla_breached',
        alarm: args.alarm,
      });

      return { acted: true };
    }

    case 'autoclose_at': {
      // Race guard: only close if resolved
      if (row.status !== 'resolved') return { acted: false };

      await autocloseSupportCase(deps.db, row.id);

      return { acted: true, newStatus: 'closed' };
    }

    default:
      return { acted: false };
  }
}
