import { Injectable, OnModuleInit } from '@nestjs/common';
import { CloudEvent, IIOS_EVENTS } from '@insignia/iios-contracts';
import { PrismaService } from '../prisma/prisma.service';
import { OutboxBus } from '../outbox/outbox.bus';
import { DlqService } from '../outbox/dlq.service';
import { ProjectionCursorService } from '../projection/projection-cursor.service';
import { AiJobService } from './ai.service';

/**
 * Auto-proposal (P7). Reacts to `interaction.normalized` — channel-bearing messages
 * that arrived via an adapter — and runs a CLASSIFY job so inbound content gets an AI
 * moderation proposal automatically. Those flags only ever push routing toward
 * REVIEW/DENY (KG-05); nothing is sent or approved. Idempotent via `claim()` and the
 * job's own idempotency key.
 */
@Injectable()
export class AiProjector implements OnModuleInit {
  private readonly consumer = 'ai-projector';

  constructor(
    private readonly prisma: PrismaService,
    private readonly bus: OutboxBus,
    private readonly dlq: DlqService,
    private readonly ai: AiJobService,
    private readonly cursor: ProjectionCursorService,
  ) {}

  onModuleInit(): void {
    this.dlq.registerHandler(this.consumer, (e) => this.onNormalized(e));
    this.bus.on(IIOS_EVENTS.interactionNormalized, (p) => void this.onNormalized(p as CloudEvent).catch((err) => this.dlq.onConsumerFailure(this.consumer, p as CloudEvent, err)));
  }

  async onNormalized(event: CloudEvent): Promise<void> {
    if (!(await this.claim(event.id))) return; // duplicate → no apply, no cursor advance
    await this.applyNormalized(event);
    await this.cursor.advance(this.consumer, event);
  }

  private async applyNormalized(event: CloudEvent): Promise<void> {
    const { interactionId } = event.data as { interactionId: string };
    const interaction = await this.prisma.iiosInteraction.findUnique({
      where: { id: interactionId },
      include: { channel: true },
    });
    if (!interaction?.channel) return; // native DMs have no origin channel → not auto-classified
    await this.ai.runJob({ interactionId, jobType: 'CLASSIFY' });
  }

  private async claim(eventId: string): Promise<boolean> {
    const res = await this.prisma.iiosProcessedEvent.createMany({
      data: [{ consumerName: this.consumer, eventId }],
      skipDuplicates: true,
    });
    return res.count > 0;
  }
}
