import { Injectable, ForbiddenException, NotFoundException } from '@nestjs/common';
import { PrismaService } from '@chatapp/database';

@Injectable()
export class LegalHoldsService {
  constructor(private readonly prisma: PrismaService) {}

  private async requireAdmin(wsId: string, userId: string) {
    const member = await this.prisma.workspaceMember.findUnique({
      where: { workspaceId_userId: { workspaceId: wsId, userId } },
    });
    if (!member || (member.role !== 'admin' && member.role !== 'owner')) {
      throw new ForbiddenException('Admin access required');
    }
    return member;
  }

  async list(wsId: string, userId: string) {
    await this.requireAdmin(wsId, userId);

    const holds = await this.prisma.legalHold.findMany({
      where: { workspaceId: wsId },
      orderBy: { createdAt: 'desc' },
      include: {
        createdByUser: { select: { id: true, displayName: true, avatarUrl: true } },
      },
    });

    return {
      holds: holds.map(h => ({
        id: h.id,
        name: h.name,
        description: h.description,
        user_ids: h.userIds,
        channel_ids: h.channelIds,
        start_date: h.startDate,
        end_date: h.endDate,
        created_by: h.createdByUser,
        created_at: h.createdAt,
      })),
    };
  }

  async create(wsId: string, userId: string, dto: any) {
    await this.requireAdmin(wsId, userId);

    const hold = await this.prisma.legalHold.create({
      data: {
        workspaceId: wsId,
        name: dto.name,
        description: dto.description,
        userIds: dto.user_ids || [],
        channelIds: dto.channel_ids || [],
        startDate: dto.start_date ? new Date(dto.start_date) : new Date(),
        endDate: dto.end_date ? new Date(dto.end_date) : null,
        createdBy: userId,
      },
      include: {
        createdByUser: { select: { id: true, displayName: true, avatarUrl: true } },
      },
    });

    return {
      id: hold.id,
      name: hold.name,
      description: hold.description,
      user_ids: hold.userIds,
      channel_ids: hold.channelIds,
      start_date: hold.startDate,
      end_date: hold.endDate,
      created_by: hold.createdByUser,
      created_at: hold.createdAt,
    };
  }

  async update(id: string, wsId: string, userId: string, dto: any) {
    await this.requireAdmin(wsId, userId);

    const hold = await this.prisma.legalHold.findFirst({
      where: { id, workspaceId: wsId },
    });
    if (!hold) throw new NotFoundException('Legal hold not found');

    const data: any = {};
    if (dto.name !== undefined) data.name = dto.name;
    if (dto.description !== undefined) data.description = dto.description;
    if (dto.user_ids !== undefined) data.userIds = dto.user_ids;
    if (dto.channel_ids !== undefined) data.channelIds = dto.channel_ids;
    if (dto.end_date !== undefined) data.endDate = dto.end_date ? new Date(dto.end_date) : null;

    return this.prisma.legalHold.update({ where: { id }, data });
  }

  async release(id: string, wsId: string, userId: string) {
    await this.requireAdmin(wsId, userId);

    const hold = await this.prisma.legalHold.findFirst({
      where: { id, workspaceId: wsId },
    });
    if (!hold) throw new NotFoundException('Legal hold not found');

    return this.prisma.legalHold.update({
      where: { id },
      data: { endDate: new Date() },
    });
  }

  async delete(id: string, wsId: string, userId: string) {
    await this.requireAdmin(wsId, userId);

    const hold = await this.prisma.legalHold.findFirst({
      where: { id, workspaceId: wsId },
    });
    if (!hold) throw new NotFoundException('Legal hold not found');

    await this.prisma.legalHold.delete({ where: { id } });
    return { deleted: true };
  }
}