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

/**
 * FASE 6 — Information Barriers Service
 *
 * Implementa barreras de información (ethical walls) que previenen
 * la comunicación entre grupos de usuarios definidos. Usa el modelo
 * InformationBarrier del schema.
 */
@Injectable()
export class InformationBarriersService {
  constructor(private readonly prisma: PrismaService) {}

  /**
   * Crea una barrera de información entre dos grupos.
   */
  async create(wsId: string, userId: string, dto: {
    name: string;
    group_a_type: string;
    group_a_ids: string[];
    group_b_type: string;
    group_b_ids: string[];
  }) {
    if (dto.group_a_ids.length === 0 || dto.group_b_ids.length === 0) {
      throw new BadRequestException('Both groups must have at least one member');
    }

    // Verificar que no haya solapamiento
    const overlap = dto.group_a_ids.filter((id) => dto.group_b_ids.includes(id));
    if (overlap.length > 0) {
      throw new BadRequestException('Groups cannot overlap');
    }

    return this.prisma.informationBarrier.create({
      data: {
        workspaceId: wsId,
        name: dto.name,
        groupAType: dto.group_a_type,
        groupAIds: dto.group_a_ids,
        groupBType: dto.group_b_type,
        groupBIds: dto.group_b_ids,
        createdBy: userId,
        isActive: true,
      },
    });
  }

  /**
   * Lista todas las barreras del workspace.
   */
  async list(wsId: string) {
    const barriers = await this.prisma.informationBarrier.findMany({
      where: { workspaceId: wsId },
      orderBy: { createdAt: 'desc' },
      include: {
        createdByUser: { select: { id: true, displayName: true } },
      },
    });

    return barriers.map((b) => ({
      id: b.id,
      name: b.name,
      group_a: { type: b.groupAType, ids: b.groupAIds },
      group_b: { type: b.groupBType, ids: b.groupBIds },
      is_active: b.isActive,
      created_by: b.createdByUser,
      created_at: b.createdAt,
    }));
  }

  /**
   * Obtiene una barrera específica.
   */
  async get(wsId: string, barrierId: string) {
    const barrier = await this.prisma.informationBarrier.findFirst({
      where: { id: barrierId, workspaceId: wsId },
      include: {
        createdByUser: { select: { id: true, displayName: true } },
      },
    });
    if (!barrier) throw new NotFoundException('Information barrier not found');

    return {
      id: barrier.id,
      name: barrier.name,
      group_a: { type: barrier.groupAType, ids: barrier.groupAIds },
      group_b: { type: barrier.groupBType, ids: barrier.groupBIds },
      is_active: barrier.isActive,
      created_by: barrier.createdByUser,
      created_at: barrier.createdAt,
    };
  }

  /**
   * Actualiza una barrera.
   */
  async update(wsId: string, barrierId: string, dto: any) {
    const barrier = await this.prisma.informationBarrier.findFirst({
      where: { id: barrierId, workspaceId: wsId },
    });
    if (!barrier) throw new NotFoundException('Information barrier not found');

    const data: any = {};
    if (dto.name) data.name = dto.name;
    if (dto.group_a_type) data.groupAType = dto.group_a_type;
    if (dto.group_a_ids) data.groupAIds = dto.group_a_ids;
    if (dto.group_b_type) data.groupBType = dto.group_b_type;
    if (dto.group_b_ids) data.groupBIds = dto.group_b_ids;
    if (dto.is_active !== undefined) data.isActive = dto.is_active;

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

  /**
   * Activa o desactiva una barrera.
   */
  async toggle(wsId: string, barrierId: string, active: boolean) {
    const barrier = await this.prisma.informationBarrier.findFirst({
      where: { id: barrierId, workspaceId: wsId },
    });
    if (!barrier) throw new NotFoundException('Information barrier not found');

    return this.prisma.informationBarrier.update({
      where: { id: barrierId },
      data: { isActive: active },
    });
  }

  /**
   * Elimina una barrera.
   */
  async delete(wsId: string, barrierId: string) {
    const barrier = await this.prisma.informationBarrier.findFirst({
      where: { id: barrierId, workspaceId: wsId },
    });
    if (!barrier) throw new NotFoundException('Information barrier not found');

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

  /**
   * Verifica si dos usuarios tienen una barrera entre ellos.
   * Devuelve true si NO pueden comunicarse.
   */
  async checkBarrier(wsId: string, userIdA: string, userIdB: string): Promise<{
    blocked: boolean;
    barrier_id?: string;
    barrier_name?: string;
  }> {
    const barriers = await this.prisma.informationBarrier.findMany({
      where: { workspaceId: wsId, isActive: true },
    });

    for (const barrier of barriers) {
      const aInGroupA = barrier.groupAIds.includes(userIdA);
      const aInGroupB = barrier.groupBIds.includes(userIdA);
      const bInGroupA = barrier.groupAIds.includes(userIdB);
      const bInGroupB = barrier.groupBIds.includes(userIdB);

      // Si cada usuario está en un grupo diferente, están bloqueados
      if ((aInGroupA && bInGroupB) || (aInGroupB && bInGroupA)) {
        return {
          blocked: true,
          barrier_id: barrier.id,
          barrier_name: barrier.name,
        };
      }
    }

    return { blocked: false };
  }
}