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

const utcDateOnly = (d: Date): Date =>
  new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));

export type TurnoVigenteResult = {
  asignacion_id: string;
  turno_id: string;
  tipo_asignacion: 'PERPETUA' | 'OCASIONAL';
  prioridad: number;
  turno: {
    id: string;
    nombre: string;
    tipo: string;
    activo: boolean;
    bloques: Array<{
      id: string;
      orden: number;
      hora_entrada: Date;
      hora_salida: Date;
    }>;
  };
} | null;

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

  async resolverTurnoVigente(
    empresaId: string,
    empleadoId: string,
    fechaInput: Date | string,
  ): Promise<TurnoVigenteResult> {
    const fecha = typeof fechaInput === 'string' ? new Date(fechaInput) : fechaInput;
    const fechaDia = utcDateOnly(fecha);

    const asignaciones = await this.prisma.rrhh_empleados_turnos.findMany({
      where: {
        empresa_id: empresaId,
        empleado_id: empleadoId,
        OR: [{ fecha_inicio: null }, { fecha_inicio: { lte: fechaDia } }],
        AND: [{ OR: [{ fecha_fin: null }, { fecha_fin: { gte: fechaDia } }] }],
      },
      include: {
        turno: {
          include: {
            bloques: {
              orderBy: { orden: 'asc' },
            },
          },
        },
      },
      orderBy: [
        { prioridad: 'asc' },
        { created_at: 'desc' },
      ],
    });

    const candidatas = asignaciones
      .filter((a) => this.aplicaDiaSemana(a.turno, fechaDia))
      .sort((a, b) => {
        if (a.tipo_asignacion !== b.tipo_asignacion) {
          return a.tipo_asignacion === 'OCASIONAL' ? -1 : 1;
        }
        if (a.prioridad !== b.prioridad) return a.prioridad - b.prioridad;
        return b.created_at!.getTime() - a.created_at!.getTime();
      });

    const vigente = candidatas[0];
    if (!vigente) return null;

    return {
      asignacion_id: vigente.id,
      turno_id: vigente.turno_id,
      tipo_asignacion: vigente.tipo_asignacion as 'PERPETUA' | 'OCASIONAL',
      prioridad: vigente.prioridad,
      turno: {
        id: vigente.turno.id,
        nombre: vigente.turno.nombre,
        tipo: vigente.turno.tipo,
        activo: vigente.turno.activo,
        bloques: vigente.turno.bloques,
      },
    };
  }

  private aplicaDiaSemana(
    turno: {
      lunes: boolean;
      martes: boolean;
      miercoles: boolean;
      jueves: boolean;
      viernes: boolean;
      sabado: boolean;
      domingo: boolean;
    },
    fecha: Date,
  ) {
    const dow = fecha.getUTCDay();
    if (dow === 0) return turno.domingo;
    if (dow === 1) return turno.lunes;
    if (dow === 2) return turno.martes;
    if (dow === 3) return turno.miercoles;
    if (dow === 4) return turno.jueves;
    if (dow === 5) return turno.viernes;
    return turno.sabado;
  }
}
