import { BaseDO } from './_base.js';
import type { MultidealEnv } from '../lib/env.js';
import { getTransactionalDb } from '../lib/db.js';
import { handleSupportCaseAlarm, type CaseAlarmKind } from '../lifecycle/support-cases.js';
import { insertOutboxRow } from '@/server/db/queries/outbox';

/**
 * SupportCaseDO — entity-alarm DO for transaction_cases lifecycle.
 *
 * Key format: case:{uuid} (resolved via idFromName).
 *
 * Phase 4: vendor window expiry → escalated → human_review, SLA alarms,
 * autoclose after N days resolved.
 * Phase 5: escalated → ai_handling (replace second hop).
 */
export class SupportCaseDO extends BaseDO {
  protected override className = 'SupportCaseDO';
  constructor(ctx: DurableObjectState, env: MultidealEnv) {
    super(ctx, env);
  }

  override async alarm(): Promise<void> {
    const stored = await this.ctx.storage.get<string>('arm_kind');
    const alarm = (stored ?? 'vendor_window_expires_at') as CaseAlarmKind;
    // caseId is stored in storage under 'case_id', set during arm or derived from key
    const caseId =
      (await this.ctx.storage.get<string>('case_id')) ??
      (await this.ctx.storage.get<string>('entity_id')) ??
      this.ctx.id.toString();

    const db = getTransactionalDb(this.env);

    const enqueueOutbox = async (kind: string, body: unknown) => {
      await insertOutboxRow(db as never, {
        aggregateType: 'case',
        aggregateId: caseId,
        eventType: kind,
        payload: body as Record<string, unknown>,
      });
    };

    await handleSupportCaseAlarm({ db, enqueueOutbox }, { caseId, alarm });

    await this.ctx.storage.delete('arm_at');
    await this.ctx.storage.delete('arm_kind');
  }

  /**
   * Override fetch to capture caseId from arm request body.
   * Calls super.fetch for all routing, but saves caseId on arm.
   */
  override async fetch(request: Request): Promise<Response> {
    const url = new URL(request.url);
    if (request.method === 'POST' && url.pathname === '/arm') {
      // Parse body to extract caseId if provided (optional enhancement)
      const body = (await request
        .clone()
        .json()
        .catch((err) => {
          void err;
          return {};
        })) as Record<string, unknown>;
      if (typeof body['caseId'] === 'string') {
        await this.ctx.storage.put('case_id', body['caseId']);
      }
      if (typeof body['kind'] === 'string') {
        await this.ctx.storage.put('arm_kind', body['kind']);
      }
    }
    return super.fetch(request);
  }
}
