'use client';

import { useState, useEffect, useCallback } from 'react';
import { AnimatePresence } from 'framer-motion';
import {
  ChevronLeft, ChevronRight, Plus, Calendar, RefreshCw,
  CalendarDays, CalendarRange, LayoutGrid, List, Info
} from 'lucide-react';
import AgendaSemanal from './agenda-semanal';
import AgendaDiaria from './agenda-diaria';
import AgendaMensual from './agenda-mensual';
import AvisosSidebar from './avisos-sidebar';
import NuevoEventoModal from './nuevo-evento-modal';
import EventoDetailModal from './evento-detail-modal';

export interface Tecnico {
  id: string;
  name: string;
  email: string;
}

export interface EventoAgenda {
  id: string;
  titulo: string;
  tipo: string;
  estado: string;
  fecha: string;
  horaInicio: string | null;
  horaFin: string | null;
  duracionMinutos: number | null;
  todoElDia: boolean;
  notas: string | null;
  prioridad: string;
  avisoId: string | null;
  parteId: string | null;
  asignaciones: {
    id: string;
    tecnicoId: string;
    rol: string;
    tecnico: { id: string; name: string; email?: string };
  }[];
  aviso?: {
    id: string; numero: number; cliente: string; urgencia: string; estado: string; descripcion?: string;
    clienteRef?: { direcciones: { calle: string; numero?: string; ciudad?: string; provincia?: string; codigoPostal?: string }[] } | null;
  } | null;
  parte?: { id: string; numero: number; descripcion: string; estado: string } | null;
  creadoPor?: { id: string; name: string } | null;
}

export interface TravelTime {
  fromEventoId: string;
  toEventoId: string;
  durationText: string;
  durationMinutes: number;
  distanceText: string;
}

type Vista = 'dia' | 'semana' | 'mes';

function getWeekStart(date: Date): Date {
  const d = new Date(date);
  const day = d.getDay();
  const diff = d.getDate() - day + (day === 0 ? -6 : 1);
  d.setDate(diff);
  d.setHours(0, 0, 0, 0);
  return d;
}

function getMonthStart(date: Date): Date {
  return new Date(date.getFullYear(), date.getMonth(), 1);
}

function getMonthEnd(date: Date): Date {
  return new Date(date.getFullYear(), date.getMonth() + 1, 0);
}

function addDays(date: Date, days: number): Date {
  const d = new Date(date);
  d.setDate(d.getDate() + days);
  return d;
}

function formatDateISO(date: Date): string {
  const y = date.getFullYear();
  const m = String(date.getMonth() + 1).padStart(2, '0');
  const d = String(date.getDate()).padStart(2, '0');
  return `${y}-${m}-${d}`;
}

export default function AgendaContent({
  userRole,
  userId,
  initialDate,
  initialView,
}: {
  userRole: string;
  userId: string;
  initialDate?: string;
  initialView?: Vista;
}) {
  const [vista, setVista] = useState<Vista>(initialView || 'semana');
  const [currentDate, setCurrentDate] = useState<Date | null>(null);
  const [eventos, setEventos] = useState<EventoAgenda[]>([]);
  const [tecnicos, setTecnicos] = useState<Tecnico[]>([]);
  const [loading, setLoading] = useState(true);
  const [showNuevoEvento, setShowNuevoEvento] = useState(false);
  const [selectedEvento, setSelectedEvento] = useState<string | null>(null);
  const [preselectedDate, setPreselectedDate] = useState<string | null>(null);
  const [preselectedTecnico, setPreselectedTecnico] = useState<string | null>(null);
  const [preselectedAvisoId, setPreselectedAvisoId] = useState<string | null>(null);
  const [showAvisosSidebar, setShowAvisosSidebar] = useState(false);
  const [avisosRefreshKey, setAvisosRefreshKey] = useState(0);
  const [travelTimes, setTravelTimes] = useState<TravelTime[]>([]);
  const [showRescheduleEmailPrompt, setShowRescheduleEmailPrompt] = useState(false);
  const [rescheduleData, setRescheduleData] = useState<{ id: string; fecha: string; tecnicoId?: string } | null>(null);

  useEffect(() => {
    if (initialDate) {
      setCurrentDate(new Date(initialDate));
    } else {
      setCurrentDate(new Date());
    }
  }, [initialDate]);

  // Calcular rango de fechas segun vista
  const getDateRange = useCallback((): { desde: string; hasta: string } | null => {
    if (!currentDate) return null;
    if (vista === 'dia') {
      const iso = formatDateISO(currentDate);
      return { desde: iso, hasta: iso };
    } else if (vista === 'semana') {
      const ws = getWeekStart(currentDate);
      return { desde: formatDateISO(ws), hasta: formatDateISO(addDays(ws, 6)) };
    } else {
      // mes: get first monday of month view to last sunday
      const ms = getMonthStart(currentDate);
      const me = getMonthEnd(currentDate);
      const firstDay = ms.getDay();
      const startOffset = firstDay === 0 ? -6 : 1 - firstDay;
      const viewStart = addDays(ms, startOffset);
      const endDay = me.getDay();
      const endOffset = endDay === 0 ? 0 : 7 - endDay;
      const viewEnd = addDays(me, endOffset);
      return { desde: formatDateISO(viewStart), hasta: formatDateISO(viewEnd) };
    }
  }, [currentDate, vista]);

  const fetchTecnicos = useCallback(async () => {
    try {
      const res = await fetch('/api/users');
      if (res.ok) {
        const data = await res.json();
        const users = data.users || data || [];
        if (userRole === 'operario') {
          // Operario solo ve tecnicos de su mismo equipo o a si mismo
          setTecnicos(users.filter((u: Tecnico & { role: string }) => u.id === userId || u.role === 'operario'));
        } else {
          setTecnicos(users.filter((u: { role: string }) => u.role === 'operario' || u.role === 'admin'));
        }
      }
    } catch { /* ignore */ }
  }, [userRole, userId]);

  const fetchEventos = useCallback(async () => {
    const range = getDateRange();
    if (!range) {
      return;
    }
    setLoading(true);
    try {
      const params = new URLSearchParams(range);
      // Si es operario, filtrar por su ID
      if (userRole === 'operario') {
        params.set('tecnicoId', userId);
      }
      const res = await fetch(`/api/agenda?${params}`);

      if (res.ok) {
        try {
          const data = await res.json();
          console.log("AGENDA RAW DATA RECV:", data);
          const baseEventos = data.eventos || [];
          const ausencias = data.ausencias || [];

          const pseudoEventos: EventoAgenda[] = [];
          for (const aus of ausencias) {
            const startD = new Date(aus.fechaInicio);
            const endD = new Date(aus.fechaFin);

            let currentDay = new Date(startD);
            while (currentDay <= endD) {
              const dayIso = currentDay.toISOString().split('T')[0];
              let tituloLabel = aus.tipo === 'VACACIONES' ? '🏖️ Vacaciones' : aus.tipo === 'BAJA_MEDICA' ? '🏥 Baja Médica' : '🏢 Permiso';
              pseudoEventos.push({
                id: `aus-${aus.id}-${dayIso}`,
                titulo: `${tituloLabel} - ${aus.user?.name || ''}`,
                tipo: 'AUSENCIA',
                estado: 'COMPLETADO', // Visual gray-out
                fecha: dayIso,
                horaInicio: '00:00',
                horaFin: '23:59',
                duracionMinutos: 1440,
                todoElDia: true,
                notas: aus.notas || null,
                prioridad: 'ALTA',
                avisoId: null,
                parteId: null,
                asignaciones: [
                  {
                    id: `asig-${aus.id}`,
                    tecnicoId: aus.userId,
                    rol: 'PRINCIPAL',
                    tecnico: { id: aus.userId, name: aus.user?.name || '' }
                  }
                ]
              });
              currentDay.setDate(currentDay.getDate() + 1);
            }
          }
          setEventos([...baseEventos, ...pseudoEventos]);
        } catch (jsonErr: any) {
          console.error("JSON PARSE ERROR ON FRONTEND:", jsonErr);
        }
      } else {
        console.error("BAD RESPONSE FROM SERVER:", res.status);
      }
    } catch (networkErr: any) {
      console.error("NETWORK FETCH ERROR:", networkErr);
    }
    setLoading(false);
  }, [getDateRange, userRole, userId]);

  const fetchTravelTimes = useCallback(async () => {
    if (!currentDate || eventos.length === 0 || tecnicos.length === 0) {
      setTravelTimes([]);
      return;
    }
    // For weekly/daily view, fetch travel times for each technician per day
    const range = getDateRange();
    if (!range) return;

    const allTimes: TravelTime[] = [];
    const start = new Date(range.desde);
    const end = new Date(range.hasta);

    for (const tecnico of tecnicos) {
      const d = new Date(start);
      while (d <= end) {
        const fecha = formatDateISO(d);
        // Only fetch if there are 2+ events with addresses for this tech on this day
        const dayEvents = eventos.filter(e => {
          const ef = e.fecha.split('T')[0];
          return ef === fecha && e.asignaciones.some(a => a.tecnicoId === tecnico.id) && e.aviso?.clienteRef?.direcciones?.[0];
        });
        if (dayEvents.length >= 2) {
          try {
            const res = await fetch(`/api/agenda/travel-times?fecha=${fecha}&tecnicoId=${tecnico.id}`);
            if (res.ok) {
              const data = await res.json();
              if (data.travelTimes) allTimes.push(...data.travelTimes);
            }
          } catch { /* ignore */ }
        }
        d.setDate(d.getDate() + 1);
      }
    }
    setTravelTimes(allTimes);
  }, [currentDate, eventos, tecnicos, getDateRange]);

  useEffect(() => { fetchTecnicos(); }, [fetchTecnicos]);
  useEffect(() => { if (currentDate) fetchEventos(); }, [fetchEventos, currentDate]);
  useEffect(() => { fetchTravelTimes(); }, [fetchTravelTimes]);

  const navigate = (dir: number) => {
    if (!currentDate) return;
    if (vista === 'dia') setCurrentDate(addDays(currentDate, dir));
    else if (vista === 'semana') setCurrentDate(addDays(currentDate, dir * 7));
    else {
      const d = new Date(currentDate);
      d.setMonth(d.getMonth() + dir);
      setCurrentDate(d);
    }
  };

  const goToToday = () => setCurrentDate(new Date());

  const handleCellClick = (fecha: string, tecnicoId?: string) => {
    setPreselectedDate(fecha);
    setPreselectedTecnico(tecnicoId || null);
    setPreselectedAvisoId(null);
    setShowNuevoEvento(true);
  };

  const handleEventoClick = (eventoId: string) => {
    setSelectedEvento(eventoId);
  };

  const handleEventoMoved = async (eventoId: string, newFecha: string, newTecnicoId?: string, isForcedEmail = false) => {
    try {
      const evento = eventos.find(e => e.id === eventoId);
      if (!evento) return;

      // Calculate event duration
      let durationMin = 60;
      if (evento.horaInicio && evento.horaFin) {
        const [sh, sm] = evento.horaInicio.split(':').map(Number);
        const [eh, em] = evento.horaFin.split(':').map(Number);
        durationMin = (eh * 60 + em) - (sh * 60 + sm);
      } else if (evento.duracionMinutos) {
        durationMin = evento.duracionMinutos;
      }

      const targetTecnicoId = newTecnicoId || (evento.asignaciones[0]?.tecnicoId);

      // Find the next free slot for the target technician on the new date
      let horaInicio = evento.horaInicio;
      let horaFin = evento.horaFin;

      if (targetTecnicoId && !evento.todoElDia) {
        try {
          const res = await fetch(`/api/agenda?desde=${newFecha}&hasta=${newFecha}&tecnicoId=${targetTecnicoId}`);
          if (res.ok) {
            const data = await res.json();
            const existingEvents = (data.eventos || [])
              .filter((e: { id: string; horaFin?: string; todoElDia?: boolean; estado?: string }) =>
                e.horaFin && !e.todoElDia && e.estado !== 'CANCELADO' && e.id !== eventoId
              )
              .sort((a: { horaInicio?: string }, b: { horaInicio?: string }) =>
                (a.horaInicio || '').localeCompare(b.horaInicio || '')
              );

            if (existingEvents.length > 0) {
              // Find a non-overlapping slot after the last event
              const lastEvent = existingEvents[existingEvents.length - 1];
              const parseMin = (t: string) => { const [h, m] = t.split(':').map(Number); return h * 60 + m; };
              const lastEndParsed = parseMin(lastEvent.horaFin);
              const suggestedStart = lastEndParsed + 10; // 10 min margin
              const suggestedEnd = suggestedStart + durationMin;

              if (suggestedStart < 20 * 60) {
                const pad = (n: number) => String(n).padStart(2, '0');
                horaInicio = `${pad(Math.floor(suggestedStart / 60))}:${pad(suggestedStart % 60)}`;
                horaFin = `${pad(Math.floor(Math.min(suggestedEnd, 20 * 60) / 60))}:${pad(Math.min(suggestedEnd, 20 * 60) % 60)}`;
              }
            } else if (newTecnicoId && horaInicio) {
              // Moved to a different technician with no events yet → reset to start of day
              const pad = (n: number) => String(n).padStart(2, '0');
              const endMin = 9 * 60 + durationMin;
              horaInicio = '09:00';
              horaFin = `${pad(Math.floor(Math.min(endMin, 20 * 60) / 60))}:${pad(Math.min(endMin, 20 * 60) % 60)}`;
            }
          }
        } catch { /* ignore, use original times */ }
      }

      const body: Record<string, unknown> = {
        fecha: newFecha,
        horaInicio: horaInicio || undefined,
        horaFin: horaFin || undefined,
        forzarSolapamiento: false,
        forzarEmail: isForcedEmail,
      };
      if (newTecnicoId) {
        body.tecnicoIds = [newTecnicoId];
      }
      const res = await fetch(`/api/agenda/${eventoId}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      });
      const data = await res.json();

      if (res.ok) {
        if (data.promptEmail && !isForcedEmail) {
          setRescheduleData({ id: eventoId, fecha: newFecha, tecnicoId: newTecnicoId });
          setShowRescheduleEmailPrompt(true);
        }
        fetchEventos();
      }
    } catch { /* ignore */ }
  };

  const handleAvisoDrop = (avisoId: string, fecha: string, tecnicoId?: string) => {
    setPreselectedDate(fecha);
    setPreselectedTecnico(tecnicoId || null);
    setPreselectedAvisoId(avisoId);
    setShowNuevoEvento(true);
  };

  const handleDayClick = (date: Date) => {
    setCurrentDate(date);
    setVista('dia');
  };

  if (!currentDate) {
    return <div className="p-6 text-gray-500">Cargando...</div>;
  }

  // Label segun vista
  let dateLabel = '';
  if (vista === 'dia') {
    dateLabel = currentDate.toLocaleDateString('es-ES', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });
    dateLabel = dateLabel.charAt(0).toUpperCase() + dateLabel.slice(1);
  } else if (vista === 'semana') {
    const ws = getWeekStart(currentDate);
    const we = addDays(ws, 6);
    dateLabel = `${ws.toLocaleDateString('es-ES', { day: 'numeric', month: 'short' })} - ${we.toLocaleDateString('es-ES', { day: 'numeric', month: 'short', year: 'numeric' })}`;
  } else {
    dateLabel = currentDate.toLocaleDateString('es-ES', { month: 'long', year: 'numeric' });
    dateLabel = dateLabel.charAt(0).toUpperCase() + dateLabel.slice(1);
  }

  return (
    <div className="space-y-3">
      {/* Header */}
      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
        <div>
          <h1 className="text-2xl font-bold text-gray-900">Agenda</h1>
          <p className="text-sm text-gray-500">
            {userRole === 'operario' ? 'Tu planificación de trabajos' : 'Planificación de trabajos por técnico'}
          </p>
        </div>
        <div className="flex items-center gap-2">
          {userRole !== 'operario' && (
            <button
              onClick={() => setShowAvisosSidebar(!showAvisosSidebar)}
              className={`flex items-center gap-1.5 px-3 py-2 text-sm rounded-lg border transition-colors ${showAvisosSidebar ? 'bg-blue-50 border-blue-300 text-blue-700' : 'bg-white border-gray-300 text-gray-700 hover:bg-gray-50'
                }`}
            >
              <List className="w-4 h-4" /> Avisos
            </button>
          )}
          <button
            onClick={() => { setPreselectedDate(null); setPreselectedTecnico(null); setPreselectedAvisoId(null); setShowNuevoEvento(true); }}
            className="flex items-center gap-2 px-4 py-2 bg-[#1a365d] hover:bg-[#2c5282] text-white rounded-lg text-sm font-medium transition-colors"
          >
            <Plus className="w-4 h-4" /> Nuevo Evento
          </button>
        </div>
      </div>

      {/* Navigation bar */}
      <div className="bg-white rounded-xl border p-3 flex flex-col sm:flex-row items-center justify-between gap-3">
        <div className="flex items-center gap-2">
          <button onClick={() => navigate(-1)} className="p-2 hover:bg-gray-100 rounded-lg transition-colors">
            <ChevronLeft className="w-5 h-5 text-gray-600" />
          </button>
          <button onClick={goToToday} className="flex items-center gap-1.5 px-3 py-1.5 text-sm bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors">
            <Calendar className="w-4 h-4" /> Hoy
          </button>
          <button onClick={() => navigate(1)} className="p-2 hover:bg-gray-100 rounded-lg transition-colors">
            <ChevronRight className="w-5 h-5 text-gray-600" />
          </button>
          <span className="text-sm font-semibold text-gray-900 ml-2">{dateLabel}</span>
        </div>

        <div className="flex items-center gap-1 bg-gray-100 rounded-lg p-0.5">
          <button
            onClick={() => setVista('dia')}
            className={`flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${vista === 'dia' ? 'bg-white shadow-sm text-gray-900' : 'text-gray-500 hover:text-gray-700'
              }`}
          >
            <CalendarDays className="w-3.5 h-3.5" /> Día
          </button>
          <button
            onClick={() => setVista('semana')}
            className={`flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${vista === 'semana' ? 'bg-white shadow-sm text-gray-900' : 'text-gray-500 hover:text-gray-700'
              }`}
          >
            <CalendarRange className="w-3.5 h-3.5" /> Semana
          </button>
          <button
            onClick={() => setVista('mes')}
            className={`flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${vista === 'mes' ? 'bg-white shadow-sm text-gray-900' : 'text-gray-500 hover:text-gray-700'
              }`}
          >
            <LayoutGrid className="w-3.5 h-3.5" /> Mes
          </button>
          <button onClick={fetchEventos} className="p-1.5 hover:bg-white rounded-md transition-colors ml-1" title="Refrescar">
            <RefreshCw className={`w-3.5 h-3.5 text-gray-500 ${loading ? 'animate-spin' : ''}`} />
          </button>
        </div>
      </div>

      {/* Main content area */}
      <div className="flex gap-3">
        {/* Avisos sidebar */}
        {showAvisosSidebar && userRole !== 'operario' && (
          <div className="w-64 flex-shrink-0">
            <AvisosSidebar refreshKey={avisosRefreshKey} />
          </div>
        )}

        {/* Calendar view */}
        <div className="flex-1 min-w-0">
          {vista === 'dia' && (
            <AgendaDiaria
              currentDate={currentDate}
              eventos={eventos}
              tecnicos={tecnicos}
              loading={loading}
              userRole={userRole}
              userId={userId}
              travelTimes={travelTimes}
              onCellClick={handleCellClick}
              onEventoClick={handleEventoClick}
              onEventoMoved={handleEventoMoved}
              onAvisoDrop={handleAvisoDrop}
            />
          )}
          {vista === 'semana' && (
            <AgendaSemanal
              weekStart={getWeekStart(currentDate)}
              eventos={eventos}
              tecnicos={tecnicos}
              loading={loading}
              userRole={userRole}
              userId={userId}
              travelTimes={travelTimes}
              onCellClick={handleCellClick}
              onEventoClick={handleEventoClick}
              onEventoMoved={handleEventoMoved}
              onAvisoDrop={handleAvisoDrop}
            />
          )}
          {vista === 'mes' && (
            <AgendaMensual
              currentDate={currentDate}
              eventos={eventos}
              loading={loading}
              onDayClick={handleDayClick}
              onEventoClick={handleEventoClick}
              onEventoMoved={handleEventoMoved}
              onAvisoDrop={handleAvisoDrop}
            />
          )}
        </div>
      </div>

      {/* Modales */}
      <AnimatePresence>
        {showNuevoEvento && (
          <NuevoEventoModal
            tecnicos={tecnicos}
            preselectedDate={preselectedDate}
            preselectedTecnico={preselectedTecnico}
            preselectedAvisoId={preselectedAvisoId}
            onClose={() => setShowNuevoEvento(false)}
            onCreated={() => { setShowNuevoEvento(false); fetchEventos(); setAvisosRefreshKey(k => k + 1); }}
          />
        )}
        {selectedEvento && (
          <EventoDetailModal
            eventoId={selectedEvento}
            tecnicos={tecnicos}
            userRole={userRole}
            onClose={() => setSelectedEvento(null)}
            onUpdated={() => { setSelectedEvento(null); fetchEventos(); }}
          />
        )}
      </AnimatePresence>

      {/* Pop-up de confirmación de email para reagendación (Drag & Drop) */}
      {showRescheduleEmailPrompt && (
        <div className="fixed inset-0 bg-black/50 z-[100] flex items-center justify-center p-4">
          <div className="bg-white rounded-xl shadow-xl w-full max-w-sm p-6 space-y-4">
            <div className="flex items-center gap-3 text-[#1a365d]">
              <Info className="w-6 h-6" />
              <h3 className="text-lg font-bold">Enviar notificación</h3>
            </div>
            <p className="text-sm text-gray-600">
              La cita ha sido cambiada. ¿Desea enviar una notificación por correo electrónico al cliente con el nuevo horario?
            </p>
            <div className="flex justify-end gap-3 pt-2">
              <button
                onClick={() => setShowRescheduleEmailPrompt(false)}
                className="px-4 py-2 text-sm text-gray-500 hover:bg-gray-100 rounded-lg"
              >
                No enviar
              </button>
              <button
                onClick={() => {
                  if (rescheduleData) {
                    handleEventoMoved(rescheduleData.id, rescheduleData.fecha, rescheduleData.tecnicoId, true);
                  }
                  setShowRescheduleEmailPrompt(false);
                }}
                className="px-4 py-2 text-sm bg-[#1a365d] text-white rounded-lg hover:bg-[#2c5282]"
              >
                Enviar ahora
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
