import { ConflictException, Injectable, NotFoundException, Logger } from '@nestjs/common';
import { AuditService } from 'src/audit/audit.service';
import { PrismaService } from 'src/prisma/prisma.service';
import { CreatePerfileDto } from './dto/create-perfile.dto';
import { UpdatePerfileDto } from './dto/update-perfile.dto';

@Injectable()
export class PerfilesService {
  private readonly logger = new Logger(PerfilesService.name);
  constructor(
    private readonly prisma: PrismaService,
    private readonly auditService: AuditService,
  ) {}

  async create(createPerfileDto: CreatePerfileDto, empresa_id: string, user_id?: string) {
    const { permisos, ...perfilData } = createPerfileDto;

    console.log('📝 Creando perfil con datos:', { perfilData, permisos, empresa_id });

    const existing = await this.prisma.perfiles.findFirst({
      where: {
        perfil: perfilData.perfil,
        empresa_id: empresa_id,
      },
    });

    if (existing) {
      throw new ConflictException('Ya existe un perfil con este nombre en su empresa');
    }

    return this.prisma.$transaction(async (tx) => {
      const perfil = await tx.perfiles.create({
        data: {
          ...perfilData,
          empresa_id,
          created_at: new Date(),
          updated_at: new Date(),
        },
      });

      if (permisos && permisos.length > 0) {
        await tx.perfiles_privilegios.createMany({
          data: permisos.map((p) => ({
            perfil_id: perfil.id,
            modulo_id: p.modulo_id,
            privilegio_id: p.privilegio_id,
            active: true,
          })),
        });
      }

      this.logger.log(`Perfil creado: ${perfil.perfil} (${perfil.id})`, 'PerfilesService');
      await this.auditService.log({
        empresa_id,
        user_id,
        action: 'CREATE',
        entity_type: 'perfil',
        entity_id: perfil.id,
        descripcion: `Perfil creado: ${perfil.perfil}`,
        new_value: { perfil: perfil.perfil, permisos_count: permisos?.length ?? 0 },
      });
      return perfil;
    });
  }

  async findAll(empresa_id: string) {
    return this.prisma.perfiles.findMany({
      where: {
        OR: [{ empresa_id: null }, { empresa_id: empresa_id }],
      },
      orderBy: { perfil: 'asc' },
    });
  }

  async findOne(id: string) {
    const perfil = await this.prisma.perfiles.findUnique({
      where: { id },
      include: {
        perfiles_privilegios: true,
      },
    });
    if (!perfil) throw new NotFoundException('Perfil no encontrado');
    return perfil;
  }

  async update(id: string, updatePerfileDto: UpdatePerfileDto, empresa_id: string, user_id?: string) {
    const perfil = await this.findOne(id);
    const { permisos, ...perfilData } = updatePerfileDto;

    console.log('📝 Actualizando perfil con datos:', { id, perfilData, permisos, empresa_id });

    if (perfil.empresa_id !== empresa_id) {
      throw new ConflictException(
        'No tiene permisos para modificar este perfil (es un rol del sistema o de otra entidad)',
      );
    }

    return this.prisma.$transaction(async (tx) => {
      const updatedPerfil = await tx.perfiles.update({
        where: { id },
        data: {
          ...perfilData,
          updated_at: new Date(),
        },
      });

      if (permisos) {
        // Delete existing permissions
        await tx.perfiles_privilegios.deleteMany({
          where: { perfil_id: id },
        });

        // Insert new ones
        if (permisos.length > 0) {
          await tx.perfiles_privilegios.createMany({
            data: permisos.map((p) => ({
              perfil_id: id,
              modulo_id: p.modulo_id,
              privilegio_id: p.privilegio_id,
              active: true,
            })),
          });
        }
      }
      this.logger.log(`Perfil actualizado: ${updatedPerfil.perfil} (${id})`, 'PerfilesService');
      await this.auditService.log({
        empresa_id,
        user_id,
        action: 'UPDATE',
        entity_type: 'perfil',
        entity_id: id,
        descripcion: `Perfil actualizado: ${updatedPerfil.perfil}`,
        old_value: { perfil: perfil.perfil },
        new_value: { perfil: updatedPerfil.perfil, permisos_count: permisos?.length ?? 0 },
      });
      return updatedPerfil;
    });
  }

  async remove(id: string, empresa_id: string, user_id?: string) {
    const perfil = await this.findOne(id);

    if (perfil.empresa_id !== empresa_id) {
      throw new ConflictException('No tiene permisos para eliminar este perfil');
    }

    // Check if used
    const usage = await this.prisma.usuario_perfiles.count({
      where: { perfil_id: id },
    });
    if (usage > 0) {
      throw new ConflictException('No se puede eliminar el perfil porque está asignado a usuarios');
    }

    const deleted = await this.prisma.perfiles.delete({ where: { id } });
    this.logger.log(`Perfil eliminado: ${perfil.perfil} (${id})`, 'PerfilesService');
    await this.auditService.log({
      empresa_id,
      user_id,
      action: 'DELETE',
      entity_type: 'perfil',
      entity_id: id,
      descripcion: `Perfil eliminado: ${perfil.perfil}`,
      old_value: { perfil: perfil.perfil },
    });
    return deleted;
  }
}
