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

export interface DashboardFiltros {
  sucursal_id?: string;
  departamento_id?: string;
  tipo_documento_id?: string;
  fecha_desde?: string; // YYYY-MM-DD (fecha_vencimiento >=)
  fecha_hasta?: string; // YYYY-MM-DD (fecha_vencimiento <=)
}

export interface DashboardVencimientoRow {
  documento_id: string;
  empleado_id: string;
  empleado_nombre: string;
  numero_empleado: string | null;
  sucursal_nombre: string | null;
  departamento_nombre: string | null;
  tipo_codigo: string;
  tipo_nombre: string;
  nombre_original: string;
  fecha_vencimiento: string;
  estado_vencimiento: string;
  dias_para_vencer: number;
}

export interface DashboardLegajoIncompletoRow {
  empleado_id: string;
  empleado_nombre: string;
  numero_empleado: string | null;
  sucursal_nombre: string | null;
  departamento_nombre: string | null;
  tipos_faltantes: Array<{ codigo: string; nombre: string }>;
  tipos_vencidos: Array<{ codigo: string; nombre: string; fecha_vencimiento: string }>;
}

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

  /**
   * Documentos VENCIDOS y POR_VENCER agrupados para el dashboard.
   * Si se pasan filtros (sucursal/departamento/tipo/rango), los aplica.
   */
  async vencimientos(empresaId: string, filtros: DashboardFiltros) {
    const where: Prisma.rrhh_legajo_documentosWhereInput = {
      empresa_id: empresaId,
      estado: 'ACTIVO',
      fecha_vencimiento: { not: null },
      estado_vencimiento: { in: ['VENCIDO', 'POR_VENCER'] },
    };

    if (filtros.tipo_documento_id) where.tipo_documento_id = filtros.tipo_documento_id;
    if (filtros.fecha_desde || filtros.fecha_hasta) {
      where.fecha_vencimiento = {
        ...(where.fecha_vencimiento as Prisma.DateTimeNullableFilter),
        ...(filtros.fecha_desde ? { gte: new Date(filtros.fecha_desde) } : {}),
        ...(filtros.fecha_hasta ? { lte: new Date(filtros.fecha_hasta) } : {}),
      };
    }
    if (filtros.sucursal_id || filtros.departamento_id) {
      where.empleado = {
        ...(filtros.sucursal_id ? { sucursal_id: filtros.sucursal_id } : {}),
        ...(filtros.departamento_id ? { departamento_id: filtros.departamento_id } : {}),
      };
    }

    const docs = await this.prisma.rrhh_legajo_documentos.findMany({
      where,
      orderBy: [{ estado_vencimiento: 'asc' }, { fecha_vencimiento: 'asc' }],
      include: {
        tipo_documento: { select: { codigo: true, nombre: true } },
        empleado: {
          select: {
            id: true,
            numero_empleado: true,
            nombres: true,
            apellidos: true,
            sucursal: { select: { descripcion: true } },
            departamento: { select: { nombre: true } },
          },
        },
      },
    });

    const inicioHoy = this.inicioDeHoy();
    const rows: DashboardVencimientoRow[] = docs.map((d) => {
      const fechaVenc = d.fecha_vencimiento as Date;
      return {
        documento_id: d.id,
        empleado_id: d.empleado_id,
        empleado_nombre: `${d.empleado.apellidos || ''} ${d.empleado.nombres || ''}`.trim(),
        numero_empleado: d.empleado.numero_empleado || null,
        sucursal_nombre: d.empleado.sucursal?.descripcion || null,
        departamento_nombre: d.empleado.departamento?.nombre || null,
        tipo_codigo: d.tipo_documento?.codigo || '',
        tipo_nombre: d.tipo_documento?.nombre || '',
        nombre_original: d.nombre_original,
        fecha_vencimiento: fechaVenc.toISOString().slice(0, 10),
        estado_vencimiento: d.estado_vencimiento as string,
        dias_para_vencer: Math.floor(
          (fechaVenc.getTime() - inicioHoy.getTime()) / (1000 * 60 * 60 * 24),
        ),
      };
    });

    return {
      data: rows,
      total: rows.length,
      vencidos: rows.filter((r) => r.estado_vencimiento === 'VENCIDO').length,
      por_vencer: rows.filter((r) => r.estado_vencimiento === 'POR_VENCER').length,
    };
  }

  /**
   * Funcionarios activos cuyo legajo tiene tipos obligatorios FALTANTES o VENCIDOS.
   * Implementa la "Vista de Tipos Faltantes" (sección 6.2 PDF).
   */
  async legajosIncompletos(empresaId: string, filtros: DashboardFiltros) {
    // 1) Tipos obligatorios activos para esta empresa (sistema + personalizados)
    const tipos = await this.prisma.rrhh_legajo_tipos_documento.findMany({
      where: {
        es_obligatorio: true,
        activo: true,
        OR: [{ empresa_id: null }, { empresa_id: empresaId }],
      },
      select: { id: true, codigo: true, nombre: true },
    });
    if (tipos.length === 0) return { data: [], total: 0 };

    // 2) Empleados ACTIVOS de la empresa con sus documentos ACTIVOS de tipos obligatorios.
    const empleados = await this.prisma.rrhh_empleados.findMany({
      where: {
        empresa_id: empresaId,
        estado: 'ACTIVO',
        ...(filtros.sucursal_id ? { sucursal_id: filtros.sucursal_id } : {}),
        ...(filtros.departamento_id ? { departamento_id: filtros.departamento_id } : {}),
      },
      include: {
        sucursal: { select: { descripcion: true } },
        departamento: { select: { nombre: true } },
        legajo_documentos: {
          where: { estado: 'ACTIVO', tipo_documento_id: { in: tipos.map((t) => t.id) } },
          select: {
            tipo_documento_id: true,
            estado_vencimiento: true,
            fecha_vencimiento: true,
          },
        },
      },
      orderBy: [{ apellidos: 'asc' }, { nombres: 'asc' }],
    });

    const rows: DashboardLegajoIncompletoRow[] = [];
    for (const emp of empleados) {
      const docsPorTipo = new Map<string, (typeof emp.legajo_documentos)[number]>();
      for (const d of emp.legajo_documentos) {
        if (!docsPorTipo.has(d.tipo_documento_id)) docsPorTipo.set(d.tipo_documento_id, d);
      }

      const faltantes: Array<{ codigo: string; nombre: string }> = [];
      const vencidos: Array<{ codigo: string; nombre: string; fecha_vencimiento: string }> = [];

      for (const t of tipos) {
        const doc = docsPorTipo.get(t.id);
        if (!doc) {
          faltantes.push({ codigo: t.codigo, nombre: t.nombre });
        } else if (doc.estado_vencimiento === 'VENCIDO') {
          vencidos.push({
            codigo: t.codigo,
            nombre: t.nombre,
            fecha_vencimiento: doc.fecha_vencimiento
              ? (doc.fecha_vencimiento as Date).toISOString().slice(0, 10)
              : '',
          });
        }
      }

      if (faltantes.length === 0 && vencidos.length === 0) continue;

      rows.push({
        empleado_id: emp.id,
        empleado_nombre: `${emp.apellidos || ''} ${emp.nombres || ''}`.trim(),
        numero_empleado: emp.numero_empleado,
        sucursal_nombre: emp.sucursal?.descripcion || null,
        departamento_nombre: emp.departamento?.nombre || null,
        tipos_faltantes: faltantes,
        tipos_vencidos: vencidos,
      });
    }

    return { data: rows, total: rows.length };
  }

  private inicioDeHoy(): Date {
    const n = new Date();
    return new Date(n.getFullYear(), n.getMonth(), n.getDate());
  }
}
