import { z } from 'zod';
import { getDb } from '../../../db/client.js';
import type { DrizzleClient } from '../../../db/client.js';
import { notifications } from '../../../db/schema.js';
import { replaceHrefFor } from '../../../admin/resources/image-moderation/cascade.js';
import type { OutboxHandler } from '../types.js';

const payloadSchema = z
  .object({
    imageId: z.uuid(),
    ownerType: z.enum(['user', 'vendor']),
    ownerId: z.uuid(),
    entityType: z.string().min(1),
    entityId: z.uuid(),
    purpose: z.string().min(1),
    reason: z.string().min(1),
  })
  .loose();

type Payload = z.infer<typeof payloadSchema>;

export async function deliverImageRejected(
  db: DrizzleClient,
  payload: Payload,
  source: { id: string; aggregateType: string; aggregateId: string },
): Promise<void> {
  if (source.aggregateType !== payload.ownerType || source.aggregateId !== payload.ownerId) {
    throw new Error('Image rejection recipient does not match outbox aggregate');
  }
  await db
    .insert(notifications)
    .values({
      id: payload.imageId,
      recipientType: payload.ownerType,
      recipientId: payload.ownerId,
      eventType: 'image.rejected',
      severity: 'warning',
      payload: {
        imageId: payload.imageId,
        ownerType: payload.ownerType,
        ownerId: payload.ownerId,
        entityType: payload.entityType,
        entityId: payload.entityId,
        purpose: payload.purpose,
        reason: payload.reason,
        sourceOutboxId: source.id,
        replaceHref: replaceHrefFor(payload.purpose, payload.entityId),
      },
    })
    .onConflictDoNothing({ target: notifications.id });
}

export const imageRejected: OutboxHandler<Payload> = {
  type: 'image.rejected',
  payloadSchema,
  async handle(ctx, payload, event) {
    const db = getDb({ DATABASE_URL: ctx.DATABASE_URL });
    await deliverImageRejected(db, payload, {
      id: event.id,
      aggregateType: event.aggregateType,
      aggregateId: event.aggregateId,
    });
  },
};
