import { getCalendarClient, CALENDAR_ID } from './client'
import { addMinutes, format, parseISO, isWithinInterval, startOfDay, endOfDay } from 'date-fns'
import type { HorarioBarbero, SlotDisponible } from '@/types'

/**
 * Obtiene los eventos del Google Calendar para un día específico.
 */
export async function getEventosDia(fecha: Date): Promise<{ inicio: Date; fin: Date }[]> {
  const calendar = getCalendarClient()

  const res = await calendar.events.list({
    calendarId: CALENDAR_ID,
    timeMin: startOfDay(fecha).toISOString(),
    timeMax: endOfDay(fecha).toISOString(),
    singleEvents: true,
    orderBy: 'startTime',
  })

  return (res.data.items ?? []).map((ev) => ({
    inicio: parseISO(ev.start?.dateTime ?? ev.start?.date ?? ''),
    fin: parseISO(ev.end?.dateTime ?? ev.end?.date ?? ''),
  }))
}

/**
 * Genera slots de 30 minutos para un barbero en una fecha,
 * excluyendo los slots que ya están ocupados en Google Calendar.
 */
export async function getSlotsDisponibles(
  fecha: Date,
  horario: HorarioBarbero | undefined,
  duracionMin: number,
  barberoNombre: string
): Promise<SlotDisponible[]> {
  if (!horario || !horario.activo) return []

  const diaSemana = fecha.getDay() // 0=Dom..6=Sab
  if (horario.dia_semana !== diaSemana) return []

  // Construir rango del barbero para ese día
  const [hIni, mIni] = horario.hora_inicio.split(':').map(Number)
  const [hFin, mFin] = horario.hora_fin.split(':').map(Number)

  const inicio = new Date(fecha)
  inicio.setHours(hIni, mIni, 0, 0)

  const fin = new Date(fecha)
  fin.setHours(hFin, mFin, 0, 0)

  // Eventos ya agendados ese día
  const eventosOcupados = await getEventosDia(fecha)

  const slots: SlotDisponible[] = []
  let cursor = new Date(inicio)

  while (addMinutes(cursor, duracionMin) <= fin) {
    const slotFin = addMinutes(cursor, duracionMin)

    // ¿Se superpone con algún evento existente?
    const ocupado = eventosOcupados.some(
      (ev) =>
        cursor < ev.fin && slotFin > ev.inicio
    )

    slots.push({
      inicio: cursor.toISOString(),
      fin: slotFin.toISOString(),
      disponible: !ocupado,
    })

    cursor = addMinutes(cursor, 30) // avanzar de 30 en 30
  }

  return slots
}

/**
 * Crea un evento en Google Calendar para la barbería.
 * Devuelve el eventId creado.
 */
export async function crearEventoCalendario(params: {
  titulo: string
  descripcion: string
  inicio: string
  fin: string
  emailCliente?: string
}): Promise<string> {
  const calendar = getCalendarClient()

  const attendees = params.emailCliente
    ? [{ email: params.emailCliente }]
    : []

  const res = await calendar.events.insert({
    calendarId: CALENDAR_ID,
    sendUpdates: params.emailCliente ? 'all' : 'none',
    requestBody: {
      summary: params.titulo,
      description: params.descripcion,
      start: { dateTime: params.inicio, timeZone: 'America/Mexico_City' },
      end: { dateTime: params.fin, timeZone: 'America/Mexico_City' },
      attendees,
      reminders: {
        useDefault: false,
        overrides: [
          { method: 'email', minutes: 24 * 60 },
          { method: 'popup', minutes: 30 },
        ],
      },
    },
  })

  return res.data.id!
}

/**
 * Cancela/elimina un evento de Google Calendar.
 */
export async function cancelarEventoCalendario(eventId: string): Promise<void> {
  const calendar = getCalendarClient()
  await calendar.events.delete({
    calendarId: CALENDAR_ID,
    eventId,
    sendUpdates: 'all',
  })
}
