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

/**
 * FASE 6 — Custom Roles Service
 *
 * CRUD para roles personalizados del workspace con permisos granulares.
 */
@Injectable()
export class CustomRolesService {
  constructor(private readonly prisma: PrismaService) {}

  /**
   * Lista todos los roles del workspace (sistema + personalizados).
   */
  async list(wsId: string) {
    const customRoles = await this.prisma.customRole.findMany({
      where: { workspaceId: wsId },
      orderBy: { createdAt: 'asc' },
    });

    return customRoles.map((r) => ({
      id: r.id,
      name: r.name,
      description: r.description,
      permissions: r.permissions,
      is_system: r.isSystem,
      created_at: r.createdAt,
      updated_at: r.updatedAt,
    }));
  }

  /**
   * Obtiene un rol específico.
   */
  async get(wsId: string, roleId: string) {
    const role = await this.prisma.customRole.findFirst({
      where: { id: roleId, workspaceId: wsId },
    });
    if (!role) throw new NotFoundException('Role not found');

    return {
      id: role.id,
      name: role.name,
      description: role.description,
      permissions: role.permissions,
      is_system: role.isSystem,
      created_at: role.createdAt,
      updated_at: role.updatedAt,
    };
  }

  /**
   * Crea un nuevo rol personalizado.
   */
  async create(wsId: string, userId: string, dto: {
    name: string;
    description?: string;
    permissions: string[];
  }) {
    if (!dto.name || dto.name.trim().length < 2) {
      throw new BadRequestException('Role name must have at least 2 characters');
    }
    if (!dto.permissions || dto.permissions.length === 0) {
      throw new BadRequestException('At least one permission is required');
    }

    // Verificar que no exista un rol con ese nombre
    const existing = await this.prisma.customRole.findUnique({
      where: { workspaceId_name: { workspaceId: wsId, name: dto.name } },
    });
    if (existing) {
      throw new BadRequestException('A role with this name already exists');
    }

    return this.prisma.customRole.create({
      data: {
        workspaceId: wsId,
        name: dto.name,
        description: dto.description,
        permissions: dto.permissions,
        isSystem: false,
        createdBy: userId,
      },
    });
  }

  /**
   * Actualiza un rol personalizado.
   */
  async update(wsId: string, roleId: string, dto: any) {
    const role = await this.prisma.customRole.findFirst({
      where: { id: roleId, workspaceId: wsId },
    });
    if (!role) throw new NotFoundException('Role not found');
    if (role.isSystem) {
      throw new BadRequestException('System roles cannot be modified');
    }

    const data: any = {};
    if (dto.name) data.name = dto.name;
    if (dto.description !== undefined) data.description = dto.description;
    if (dto.permissions) data.permissions = dto.permissions;

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

  /**
   * Elimina un rol personalizado.
   */
  async delete(wsId: string, roleId: string) {
    const role = await this.prisma.customRole.findFirst({
      where: { id: roleId, workspaceId: wsId },
    });
    if (!role) throw new NotFoundException('Role not found');
    if (role.isSystem) {
      throw new BadRequestException('System roles cannot be deleted');
    }

    // Verificar si hay miembros asignados a este rol
    const members = await this.prisma.workspaceMember.findMany({
      where: { workspaceId: wsId, role: role.name },
      take: 1,
    });
    if (members.length > 0) {
      throw new BadRequestException('Cannot delete role: users are still assigned to it');
    }

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

  /**
   * Asigna un rol a un miembro del workspace.
   */
  async assignToMember(wsId: string, roleId: string, memberId: string) {
    const role = await this.prisma.customRole.findFirst({
      where: { id: roleId, workspaceId: wsId },
    });
    if (!role) throw new NotFoundException('Role not found');

    const member = await this.prisma.workspaceMember.findUnique({
      where: { workspaceId_userId: { workspaceId: wsId, userId: memberId } },
    });
    if (!member) throw new NotFoundException('Member not found');

    return this.prisma.workspaceMember.update({
      where: { workspaceId_userId: { workspaceId: wsId, userId: memberId } },
      data: { role: role.name },
    });
  }

  /**
   * Devuelve la lista de permisos disponibles.
   */
  getAvailablePermissions(): any[] {
    return [
      { category: 'channels', permissions: [
        { name: 'channels:create', description: 'Crear canales' },
        { name: 'channels:delete', description: 'Eliminar canales' },
        { name: 'channels:archive', description: 'Archivar canales' },
        { name: 'channels:manage', description: 'Gestionar canales (topic, propósito)' },
      ]},
      { category: 'messages', permissions: [
        { name: 'messages:send', description: 'Enviar mensajes' },
        { name: 'messages:delete:any', description: 'Eliminar cualquier mensaje' },
        { name: 'messages:edit:any', description: 'Editar cualquier mensaje' },
        { name: 'messages:pin', description: 'Fijar mensajes' },
      ]},
      { category: 'members', permissions: [
        { name: 'members:invite', description: 'Invitar miembros' },
        { name: 'members:remove', description: 'Eliminar miembros' },
        { name: 'members:manage_roles', description: 'Gestionar roles de miembros' },
        { name: 'members:deactivate', description: 'Desactivar miembros' },
      ]},
      { category: 'files', permissions: [
        { name: 'files:upload', description: 'Subir archivos' },
        { name: 'files:delete:any', description: 'Eliminar cualquier archivo' },
        { name: 'files:share_external', description: 'Compartir archivos externamente' },
      ]},
      { category: 'admin', permissions: [
        { name: 'admin:analytics', description: 'Ver analíticas' },
        { name: 'admin:audit_logs', description: 'Ver logs de auditoría' },
        { name: 'admin:manage_apps', description: 'Gestionar apps' },
        { name: 'admin:manage_integrations', description: 'Gestionar integraciones' },
        { name: 'admin:manage_security', description: 'Gestionar seguridad (SSO, SCIM, DLP)' },
        { name: 'admin:manage_retention', description: 'Gestionar políticas de retención' },
        { name: 'admin:manage_barriers', description: 'Gestionar barreras de información' },
      ]},
      { category: 'ai', permissions: [
        { name: 'ai:use', description: 'Usar funciones de IA' },
        { name: 'ai:manage_embeddings', description: 'Gestionar embeddings' },
        { name: 'ai:generate_workflows', description: 'Generar workflows con IA' },
      ]},
    ];
  }
}