import { eq } from 'drizzle-orm';
import type { DrizzleClient } from '@/server/db/client.js';
import { supportStateTransitions, supportTickets, transactionCases } from '@/server/db/schema.js';
import { insertOutboxRow } from '@/server/db/queries/outbox.js';
import { enqueueOutbox } from '@/server/queues/outbox-producer.js';
import { asCaseId } from '@/server/platform-seams/ids.js';
import type { SupportCaseEffect } from './effects.js';

export interface ApplyEffectsContext {
  db: DrizzleClient;
}

export async function applyEffects(
  ctx: ApplyEffectsContext,
  effects: SupportCaseEffect[],
): Promise<void> {
  const { db } = ctx;
  for (const effect of effects) {
    switch (effect.kind) {
      case 'record-transition':
        await db.insert(supportStateTransitions).values({
          parentType: effect.parentType,
          parentId: effect.parentId,
          fromState: effect.fromState,
          toState: effect.toState,
          actorType: effect.actorType,
          actorId: effect.actorId,
          reason: effect.reason ?? null,
          metadata: effect.metadata,
        });
        break;
      case 'set-case-status':
        await db
          .update(transactionCases)
          .set({
            status: effect.status,
            updatedAt: effect.at ?? new Date(),
            ...(effect.resolvedAt !== undefined ? { resolvedAt: effect.resolvedAt } : {}),
            ...(effect.reopenCount !== undefined ? { reopenCount: effect.reopenCount } : {}),
          })
          .where(eq(transactionCases.id, asCaseId(effect.caseId)));
        break;
      case 'set-ticket-status':
        await db
          .update(supportTickets)
          .set({ status: effect.status, updatedAt: effect.at ?? new Date() })
          .where(eq(supportTickets.id, effect.ticketId));
        break;
      case 'enqueue-outbox': {
        const { id } = await insertOutboxRow(db, {
          aggregateType: effect.aggregateType,
          aggregateId: effect.aggregateId,
          eventType: effect.eventType,
          payload: effect.payload,
        });
        await enqueueOutbox(id);
        break;
      }
    }
  }
}
