import { Inject, Injectable, NotFoundException } from '@nestjs/common';
import type { IiosPlatformPorts } from '@insignia/iios-contracts';
import { PrismaService } from '../prisma/prisma.service';
import { PLATFORM_PORTS } from '../platform/platform-ports';
import { decideOrThrow } from '../platform/fail-closed';

export interface ThreadMessage {
  interactionId: string;
  actorId: string | null;
  kind: string;
  occurredAt: Date;
  parts: Array<{ kind: string; bodyText: string | null; contentRef: string | null; mimeType: string | null; sizeBytes: number | null }>;
}

@Injectable()
export class ThreadsService {
  constructor(
    private readonly prisma: PrismaService,
    @Inject(PLATFORM_PORTS) private readonly ports: IiosPlatformPorts,
  ) {}

  async getMessages(threadId: string): Promise<{ threadId: string; messages: ThreadMessage[] }> {
    const thread = await this.prisma.iiosThread.findUnique({ where: { id: threadId } });
    if (!thread) throw new NotFoundException('thread not found');

    // Reads are policy-scoped too (fail-closed).
    await decideOrThrow(this.ports, { action: 'iios.thread.read', threadId, scopeId: thread.scopeId });

    const interactions = await this.prisma.iiosInteraction.findMany({
      where: { threadId },
      orderBy: { occurredAt: 'asc' },
      include: { parts: { orderBy: { partIndex: 'asc' } } },
    });

    return {
      threadId,
      messages: interactions.map((i) => ({
        interactionId: i.id,
        actorId: i.actorId,
        kind: i.kind,
        occurredAt: i.occurredAt,
        parts: i.parts.map((p) => ({ kind: p.kind, bodyText: p.bodyText, contentRef: p.contentRef, mimeType: p.mimeType, sizeBytes: p.sizeBytes != null ? Number(p.sizeBytes) : null })),
      })),
    };
  }
}
