import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { ModulesContextService } from './modules-context.service';

/**
 * Decide si para una empresa/usuario hay que inyectar contexto RRHH
 * al motor de IA (chat, insights, alertas, timeline, predicciones).
 *
 * Reglas (definidas en docs/plan-ia-dashboard-rrhh.md):
 *  - tieneModuloRRHH(empresaId): la empresa tiene el módulo "RRHH"
 *    activo en su suscripción.
 *  - puedeVerRRHH(usuarioId, empresaId): el usuario tiene al menos
 *    un privilegio del módulo RRHH (o es superadmin).
 *  - puedeVerSalarios(usuarioId, empresaId): el usuario tiene un
 *    privilegio sensible (calcular/cerrar liquidaciones). En caso
 *    contrario solo puede ver agregados anónimos en el chat.
 *
 * Cache liviano en memoria (60s) para no martillar la DB con cada
 * mensaje de chat.
 */
interface CacheEntry<T> {
  value: T;
  expiresAt: number;
}

const TTL_MS = 60_000;

@Injectable()
export class RrhhContextService {
  private readonly logger = new Logger(RrhhContextService.name);
  private readonly cache = new Map<string, CacheEntry<boolean>>();

  constructor(
    private readonly prisma: PrismaService,
    private readonly modulesContext: ModulesContextService,
  ) {}

  async tieneModuloRRHH(empresaId: string): Promise<boolean> {
    return this.modulesContext.tieneDominio(empresaId, 'RRHH');
  }

  async puedeVerRRHH(usuarioId: string, empresaId: string): Promise<boolean> {
    if (!(await this.tieneModuloRRHH(empresaId))) return false;
    return this._cached(`view:${usuarioId}`, async () => {
      const usuario = await this.prisma.usuario.findUnique({
        where: { id: usuarioId },
        select: { is_superadmin: true },
      });
      if (usuario?.is_superadmin) return true;

      const perm = await this.prisma.perfiles_privilegios.findFirst({
        where: {
          active: true,
          modulos: { codigo: 'RRHH' },
          perfiles: { usuario_perfiles: { some: { user_id: usuarioId } } },
        },
        select: { id: true },
      });
      return !!perm;
    });
  }

  async puedeVerSalarios(usuarioId: string, empresaId: string): Promise<boolean> {
    if (!(await this.tieneModuloRRHH(empresaId))) return false;
    return this._cached(`sal:${usuarioId}`, async () => {
      const usuario = await this.prisma.usuario.findUnique({
        where: { id: usuarioId },
        select: { is_superadmin: true },
      });
      if (usuario?.is_superadmin) return true;

      const perm = await this.prisma.perfiles_privilegios.findFirst({
        where: {
          active: true,
          modulos: { codigo: 'RRHH' },
          privilegios: {
            codigo: { in: ['RRHH_LIQUIDACIONES_CALCULAR', 'RRHH_LIQUIDACIONES_CERRAR'] },
          },
          perfiles: { usuario_perfiles: { some: { user_id: usuarioId } } },
        },
        select: { id: true },
      });
      return !!perm;
    });
  }

  private async _cached(key: string, fn: () => Promise<boolean>): Promise<boolean> {
    const hit = this.cache.get(key);
    const now = Date.now();
    if (hit && hit.expiresAt > now) return hit.value;
    const value = await fn().catch((e) => {
      this.logger.warn(`rrhh-context fallo (${key}): ${e.message}`);
      return false;
    });
    this.cache.set(key, { value, expiresAt: now + TTL_MS });
    return value;
  }
}
