import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';

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

  /**
   * Obtiene las empresas a las que el usuario tiene acceso.
   *
   * Lógica de acceso:
   * 1. SuperAdmin (is_superadmin=true): Ve su empresa + todas las hijas (via parent_id)
   * 2. Usuario normal: Ve su empresa + empresas asignadas explícitamente en usuario_empresas
   * 3. Restricción: Una empresa hija NO puede ver al padre a menos que esté asignada explícitamente
   */
  async getEmpresasAsignadas(usuarioId: string) {
    const usuario = await this.prisma.usuario.findUnique({
      where: { id: usuarioId },
      include: {
        empresa_rel: true,
        usuario_empresas: {
          where: { active: true },
          include: {
            empresa: true,
          },
        },
      },
    });

    if (!usuario) {
      return [];
    }

    const empresasMap = new Map<string, any>();

    // 1. Siempre incluir la empresa principal del usuario
    empresasMap.set(usuario.empresa_id, {
      id: usuario.empresa_id,
      razon_social: usuario.empresa_rel?.razon_social || 'Empresa Principal',
      ruc: usuario.empresa_rel?.ruc || '',
      es_principal: true,
      rol: 'admin',
      tipo: 'principal',
    });

    // 2. Si es SuperAdmin, agregar automáticamente las empresas hijas
    if (usuario.is_superadmin) {
      const empresasHijas = await this.prisma.empresas.findMany({
        where: {
          parent_id: usuario.empresa_id,
          active: true,
        },
        select: {
          id: true,
          razon_social: true,
          ruc: true,
        },
      });

      empresasHijas.forEach((hija) => {
        if (!empresasMap.has(hija.id)) {
          empresasMap.set(hija.id, {
            id: hija.id,
            razon_social: hija.razon_social || 'Empresa Hija',
            ruc: hija.ruc || '',
            es_principal: false,
            rol: 'superadmin',
            tipo: 'hija',
          });
        }
      });
    }

    // 3. Agregar empresas asignadas explícitamente en usuario_empresas
    // (esto permite que un usuario normal administre otras empresas)
    // NOTA: Aquí es donde una hija podría ver al padre SI está asignada explícitamente
    usuario.usuario_empresas.forEach((asignacion) => {
      if (!empresasMap.has(asignacion.empresa_id)) {
        empresasMap.set(asignacion.empresa_id, {
          id: asignacion.empresa.id,
          razon_social: asignacion.empresa.razon_social || 'Empresa Asignada',
          ruc: asignacion.empresa.ruc || '',
          es_principal: false,
          rol: asignacion.rol,
          tipo: 'asignada',
        });
      }
    });

    return Array.from(empresasMap.values());
  }

  async getEmpresaActual(usuarioId: string) {
    const usuario = await this.prisma.usuario.findUnique({
      where: { id: usuarioId },
      select: {
        empresa_id: true,
        empresa_id_actual: true,
        empresa_rel: {
          select: {
            razon_social: true,
            ruc: true,
          },
        },
        empresa_actual: {
          select: {
            razon_social: true,
            ruc: true,
          },
        },
      },
    });

    if (!usuario) {
      return null;
    }

    const empresaActualId = usuario.empresa_id_actual || usuario.empresa_id;

    return {
      id: empresaActualId,
      razon_social:
        empresaActualId === usuario.empresa_id
          ? usuario.empresa_rel?.razon_social
          : usuario.empresa_actual?.razon_social,
      ruc:
        empresaActualId === usuario.empresa_id
          ? usuario.empresa_rel?.ruc
          : usuario.empresa_actual?.ruc,
    };
  }

  async cambiarEmpresaActual(usuarioId: string, empresaId: string) {
    // Verificar que el usuario tenga acceso a esta empresa
    const empresasAsignadas = await this.getEmpresasAsignadas(usuarioId);
    const tieneAcceso = empresasAsignadas.some((e) => e.id === empresaId);

    if (!tieneAcceso) {
      throw new Error('No tienes acceso a esta empresa');
    }

    // Obtener empresa original del usuario
    const usuario = await this.prisma.usuario.findUnique({
      where: { id: usuarioId },
      select: { empresa_id: true },
    });

    // Si vuelve a su empresa original, limpiar empresa_id_actual (null = empresa original)
    const nuevoValor =
      usuario && empresaId === usuario.empresa_id ? null : empresaId;

    await this.prisma.usuario.update({
      where: { id: usuarioId },
      data: { empresa_id_actual: nuevoValor },
    });

    return { success: true, empresa_id_actual: empresaId };
  }
}
 