import { useState, useEffect, useCallback } from "react";
import {
  format,
  addMonths,
  subMonths,
  startOfMonth,
  endOfMonth,
  eachDayOfInterval,
  isSameMonth,
  isSameDay,
  isToday,
  isBefore,
  startOfDay,
} from "date-fns";
import { ptBR } from "date-fns/locale";
import {
  MapPin,
  Video,
  Clock,
  ChevronLeft,
  ChevronRight,
  Stethoscope,
  AlertCircle,
  CheckCircle2,
  Search,
} from "lucide-react";
import {
  availabilityService,
  exceptionsService,
  appointmentService,
  smsService,
} from "../services";
import { useAuth } from "../hooks/useAuth";

interface Medico {
  id: string;
  nome: string;
  especialidade: string;
  crm: string;
  foto?: string;
  email?: string;
  telefone?: string;
  valorConsulta?: number;
}

interface TimeSlot {
  inicio: string;
  fim: string;
  ativo: boolean;
}

interface DaySchedule {
  ativo: boolean;
  horarios: TimeSlot[];
}

interface Availability {
  domingo: DaySchedule;
  segunda: DaySchedule;
  terca: DaySchedule;
  quarta: DaySchedule;
  quinta: DaySchedule;
  sexta: DaySchedule;
  sabado: DaySchedule;
}

interface Exception {
  id: string;
  data: string;
  motivo?: string;
}

const dayOfWeekMap: { [key: number]: keyof Availability } = {
  0: "domingo",
  1: "segunda",
  2: "terca",
  3: "quarta",
  4: "quinta",
  5: "sexta",
  6: "sabado",
};

interface AgendamentoConsultaProps {
  medicos: Medico[];
}

export default function AgendamentoConsulta({
  medicos,
}: AgendamentoConsultaProps) {
  const { user } = useAuth();
  const [filteredMedicos, setFilteredMedicos] = useState<Medico[]>(medicos);

  // Sempre que a lista de médicos da API mudar, atualiza o filtro
  useEffect(() => {
    setFilteredMedicos(medicos);
  }, [medicos]);
  const [selectedMedico, setSelectedMedico] = useState<Medico | null>(null);
  const [searchTerm, setSearchTerm] = useState("");
  const [selectedSpecialty, setSelectedSpecialty] = useState("all");
  const [currentMonth, setCurrentMonth] = useState(new Date());
  const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);
  const [availability, setAvailability] = useState<Availability | null>(null);
  const [exceptions, setExceptions] = useState<Exception[]>([]);
  const [availableSlots, setAvailableSlots] = useState<string[]>([]);
  const [selectedTime, setSelectedTime] = useState("");
  const [appointmentType, setAppointmentType] = useState<
    "presencial" | "online"
  >("presencial");
  const [motivo, setMotivo] = useState("");
  const [showConfirmDialog, setShowConfirmDialog] = useState(false);
  const [bookingSuccess, setBookingSuccess] = useState(false);
  const [bookingError, setBookingError] = useState("");

  // Removido o carregamento interno de médicos, pois agora vem por prop

  useEffect(() => {
    let filtered = medicos;
    if (searchTerm) {
      filtered = filtered.filter(
        (medico) =>
          medico.nome.toLowerCase().includes(searchTerm.toLowerCase()) ||
          medico.especialidade.toLowerCase().includes(searchTerm.toLowerCase())
      );
    }
    if (selectedSpecialty !== "all") {
      filtered = filtered.filter(
        (medico) => medico.especialidade === selectedSpecialty
      );
    }
    setFilteredMedicos(filtered);
  }, [searchTerm, selectedSpecialty, medicos]);

  const specialties = Array.from(new Set(medicos.map((m) => m.especialidade)));

  useEffect(() => {
    if (selectedMedico) {
      loadDoctorAvailability();
      loadDoctorExceptions();
    }
    // eslint-disable-next-line
  }, [selectedMedico]);

  const loadDoctorAvailability = useCallback(async () => {
    if (!selectedMedico) return;
    try {
      const response = await availabilityService.getAvailability(
        selectedMedico.id
      );
      if (
        response &&
        response.success &&
        response.data &&
        response.data.length > 0
      ) {
        const avail = response.data[0];
        setAvailability({
          domingo: avail.domingo || { ativo: false, horarios: [] },
          segunda: avail.segunda || { ativo: false, horarios: [] },
          terca: avail.terca || { ativo: false, horarios: [] },
          quarta: avail.quarta || { ativo: false, horarios: [] },
          quinta: avail.quinta || { ativo: false, horarios: [] },
          sexta: avail.sexta || { ativo: false, horarios: [] },
          sabado: avail.sabado || { ativo: false, horarios: [] },
        });
      } else {
        setAvailability(null);
      }
    } catch {
      setAvailability(null);
    }
  }, [selectedMedico]);

  const loadDoctorExceptions = useCallback(async () => {
    if (!selectedMedico) return;
    try {
      const response = await exceptionService.listExceptions({
        doctor_id: selectedMedico.id,
      });
      if (response && response.success && response.data) {
        setExceptions(response.data as Exception[]);
      } else {
        setExceptions([]);
      }
    } catch {
      setExceptions([]);
    }
  }, [selectedMedico]);

  const calculateAvailableSlots = useCallback(() => {
    if (!selectedDate || !availability) return;
    const dateStr = format(selectedDate, "yyyy-MM-dd");
    const isBlocked = exceptions.some((exc) => exc.data === dateStr);
    if (isBlocked) {
      setAvailableSlots([]);
      return;
    }
    const dayOfWeek = selectedDate.getDay();
    const dayKey = dayOfWeekMap[dayOfWeek];
    const daySchedule = availability[dayKey];
    if (!daySchedule || !daySchedule.ativo) {
      setAvailableSlots([]);
      return;
    }
    const slots = daySchedule.horarios
      .filter((slot) => slot.ativo)
      .map((slot) => slot.inicio);
    setAvailableSlots(slots);
  }, [selectedDate, availability, exceptions]);

  useEffect(() => {
    if (selectedDate && availability && selectedMedico) {
      calculateAvailableSlots();
    } else {
      setAvailableSlots([]);
    }
  }, [
    selectedDate,
    availability,
    exceptions,
    calculateAvailableSlots,
    selectedMedico,
  ]);

  const isDateBlocked = (date: Date): boolean => {
    const dateStr = format(date, "yyyy-MM-dd");
    return exceptions.some((exc) => exc.data === dateStr);
  };

  const isDateAvailable = (date: Date): boolean => {
    if (!availability) return false;
    if (isBefore(date, startOfDay(new Date()))) return false;
    if (isDateBlocked(date)) return false;
    const dayOfWeek = date.getDay();
    const dayKey = dayOfWeekMap[dayOfWeek];
    const daySchedule = availability[dayKey];
    return (
      daySchedule?.ativo && daySchedule.horarios.some((slot) => slot.ativo)
    );
  };

  const generateCalendarDays = () => {
    const start = startOfMonth(currentMonth);
    const end = endOfMonth(currentMonth);
    const days = eachDayOfInterval({ start, end });
    const startDay = start.getDay();
    const prevMonthDays = [];
    for (let i = startDay - 1; i >= 0; i--) {
      const day = new Date(start);
      day.setDate(day.getDate() - (i + 1));
      prevMonthDays.push(day);
    }
    return [...prevMonthDays, ...days];
  };

  const handlePrevMonth = () => setCurrentMonth(subMonths(currentMonth, 1));
  const handleNextMonth = () => setCurrentMonth(addMonths(currentMonth, 1));
  const handleSelectDoctor = (medico: Medico) => {
    setSelectedMedico(medico);
    setSelectedDate(undefined);
    setSelectedTime("");
    setMotivo("");
    setBookingSuccess(false);
    setBookingError("");
  };
  const handleBookAppointment = () => {
    if (selectedMedico && selectedDate && selectedTime && motivo) {
      setShowConfirmDialog(true);
    }
  };
  const confirmAppointment = async () => {
    if (!selectedMedico || !selectedDate || !selectedTime || !user) return;
    try {
      setBookingError("");
      // Cria o agendamento na API real
      const result = await consultasService.criar({
        patient_id: user.id,
        doctor_id: selectedMedico.id,
        scheduled_at:
          format(selectedDate, "yyyy-MM-dd") + "T" + selectedTime + ":00.000Z",
        duration_minutes: 30,
        appointment_type: appointmentType,
        chief_complaint: motivo,
        patient_notes: "",
        insurance_provider: "",
      });
      if (!result.success) {
        setBookingError(result.error || "Erro ao agendar consulta");
        setShowConfirmDialog(false);
        return;
      }
      // Envia SMS de confirmação (se telefone disponível)
      if (user.telefone) {
        await smsService.enviarConfirmacaoConsulta(
          user.telefone,
          user.nome || "Paciente",
          selectedMedico.nome,
          format(selectedDate, "dd/MM/yyyy") + " às " + selectedTime
        );
      }
      setBookingSuccess(true);
      setShowConfirmDialog(false);
      setTimeout(() => {
        setSelectedMedico(null);
        setSelectedDate(undefined);
        setSelectedTime("");
        setMotivo("");
        setBookingSuccess(false);
      }, 3000);
    } catch (error) {
      setBookingError(
        error instanceof Error
          ? error.message
          : "Erro ao agendar consulta. Tente novamente."
      );
      setShowConfirmDialog(false);
    }
  };
  const calendarDays = generateCalendarDays();

  return (
    <div className="space-y-6">
      {bookingSuccess && (
        <div className="bg-green-50 border border-green-200 rounded-lg p-4 flex items-center gap-3">
          <CheckCircle2 className="h-5 w-5 text-green-600" />
          <div>
            <p className="font-medium text-green-900">
              Consulta agendada com sucesso!
            </p>
            <p className="text-sm text-green-700">
              Você receberá uma confirmação por e-mail em breve.
            </p>
          </div>
        </div>
      )}
      {bookingError && (
        <div className="bg-red-50 border border-red-200 rounded-lg p-4 flex items-center gap-3">
          <AlertCircle className="h-5 w-5 text-red-600" />
          <p className="text-red-900">{bookingError}</p>
        </div>
      )}
      <div>
        <h1 className="text-2xl font-bold">Agendar Consulta</h1>
        <p className="text-muted-foreground">
          Escolha um médico e horário disponível
        </p>
      </div>
      <div className="bg-white rounded-xl border p-6 space-y-4">
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div className="space-y-2">
            <label className="font-medium">
              Buscar por nome ou especialidade
            </label>
            <div className="relative">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
              <input
                type="text"
                placeholder="Ex: Cardiologia, Dr. Silva..."
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                className="pl-9 w-full border rounded-lg py-2 px-3"
              />
            </div>
          </div>
          <div className="space-y-2">
            <label className="font-medium">Especialidade</label>
            <select
              value={selectedSpecialty}
              onChange={(e) => setSelectedSpecialty(e.target.value)}
              className="w-full border rounded-lg py-2 px-3"
            >
              <option value="all">Todas as especialidades</option>
              {specialties.map((esp) => (
                <option key={esp} value={esp}>
                  {esp}
                </option>
              ))}
            </select>
          </div>
        </div>
      </div>
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
        {filteredMedicos.map((medico) => (
          <div
            key={medico.id}
            className={`bg-white rounded-xl border p-6 flex gap-4 items-center ${
              selectedMedico?.id === medico.id ? "border-blue-500" : ""
            }`}
          >
            <div className="h-16 w-16 rounded-full bg-gray-200 flex items-center justify-center text-xl font-bold">
              {medico.nome
                .split(" ")
                .map((n) => n[0])
                .join("")}
            </div>
            <div className="flex-1 space-y-2">
              <div>
                <h3 className="font-semibold">{medico.nome}</h3>
                <p className="text-muted-foreground">{medico.especialidade}</p>
              </div>
              <div className="flex items-center gap-4 text-muted-foreground">
                <span>{medico.crm}</span>
                {medico.valorConsulta ? (
                  <span>R$ {medico.valorConsulta.toFixed(2)}</span>
                ) : null}
              </div>
              <div className="flex items-center justify-between">
                <span className="text-foreground">{medico.email || "-"}</span>
                <div className="flex gap-2">
                  <button
                    className="px-3 py-1 rounded-lg border text-sm hover:bg-blue-50"
                    onClick={() => handleSelectDoctor(medico)}
                  >
                    {selectedMedico?.id === medico.id
                      ? "Selecionado"
                      : "Selecionar"}
                  </button>
                </div>
              </div>
            </div>
          </div>
        ))}
      </div>
      {selectedMedico && (
        <div className="bg-white rounded-lg shadow p-6 space-y-6">
          <div>
            <h2 className="text-xl font-semibold">Detalhes do Agendamento</h2>
            <p className="text-gray-600">
              Consulta com {selectedMedico.nome} -{" "}
              {selectedMedico.especialidade}
            </p>
          </div>
          <div className="flex gap-2">
            <button
              onClick={() => setAppointmentType("presencial")}
              className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-lg border-2 transition-colors ${
                appointmentType === "presencial"
                  ? "border-blue-500 bg-blue-50 text-blue-600"
                  : "border-gray-300 text-gray-600"
              }`}
            >
              <MapPin className="h-5 w-5" />
              <span className="font-medium">Presencial</span>
            </button>
            <button
              onClick={() => setAppointmentType("online")}
              className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-lg border-2 transition-colors ${
                appointmentType === "online"
                  ? "border-blue-500 bg-blue-50 text-blue-600"
                  : "border-gray-300 text-gray-600"
              }`}
            >
              <Video className="h-5 w-5" />
              <span className="font-medium">Online</span>
            </button>
          </div>
          <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
            <div className="space-y-4">
              <div>
                <label className="text-sm font-medium">Selecione a Data</label>
                <div className="mt-2">
                  <div className="flex items-center justify-between mb-4">
                    <button
                      onClick={handlePrevMonth}
                      className="p-2 hover:bg-gray-100 rounded-lg"
                    >
                      <ChevronLeft className="h-5 w-5" />
                    </button>
                    <span className="font-semibold">
                      {format(currentMonth, "MMMM yyyy", { locale: ptBR })}
                    </span>
                    <button
                      onClick={handleNextMonth}
                      className="p-2 hover:bg-gray-100 rounded-lg"
                    >
                      <ChevronRight className="h-5 w-5" />
                    </button>
                  </div>
                  <div className="border rounded-lg overflow-hidden">
                    <div className="grid grid-cols-7 bg-gray-50">
                      {["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"].map(
                        (day) => (
                          <div
                            key={day}
                            className="text-center py-2 text-sm font-medium text-gray-600"
                          >
                            {day}
                          </div>
                        )
                      )}
                    </div>
                    <div className="grid grid-cols-7">
                      {calendarDays.map((day, index) => {
                        const isCurrentMonth = isSameMonth(day, currentMonth);
                        const isSelected =
                          selectedDate && isSameDay(day, selectedDate);
                        const isTodayDate = isToday(day);
                        const isAvailable =
                          isCurrentMonth && isDateAvailable(day);
                        const isBlocked = isCurrentMonth && isDateBlocked(day);
                        const isPast = isBefore(day, startOfDay(new Date()));
                        return (
                          <button
                            key={index}
                            onClick={() => isAvailable && setSelectedDate(day)}
                            disabled={!isAvailable}
                            className={`aspect-square p-2 text-sm border-r border-b border-gray-200 ${
                              !isCurrentMonth ? "text-gray-300 bg-gray-50" : ""
                            } ${
                              isSelected
                                ? "bg-blue-600 text-white font-bold"
                                : ""
                            } ${
                              isTodayDate && !isSelected
                                ? "font-bold text-blue-600"
                                : ""
                            } ${
                              isAvailable && !isSelected
                                ? "hover:bg-blue-50 cursor-pointer"
                                : ""
                            } ${
                              isBlocked
                                ? "bg-red-50 text-red-400 line-through"
                                : ""
                            } ${isPast && !isBlocked ? "text-gray-400" : ""} ${
                              !isAvailable &&
                              !isBlocked &&
                              isCurrentMonth &&
                              !isPast
                                ? "text-gray-300"
                                : ""
                            }`}
                          >
                            {format(day, "d")}
                          </button>
                        );
                      })}
                    </div>
                  </div>
                  <div className="mt-3 space-y-1 text-xs text-gray-600">
                    <p>🟢 Datas disponíveis</p>
                    <p>🔴 Datas bloqueadas</p>
                  </div>
                </div>
              </div>
            </div>
            <div className="space-y-4">
              <div>
                <label className="text-sm font-medium">
                  Horários Disponíveis
                </label>
                {selectedDate ? (
                  <p className="text-sm text-gray-600 mt-1">
                    {format(selectedDate, "EEEE, d 'de' MMMM 'de' yyyy", {
                      locale: ptBR,
                    })}
                  </p>
                ) : (
                  <p className="text-sm text-gray-600 mt-1">
                    Selecione uma data
                  </p>
                )}
              </div>
              {selectedDate && availableSlots.length > 0 ? (
                <div className="grid grid-cols-3 gap-2">
                  {availableSlots.map((slot) => (
                    <button
                      key={slot}
                      onClick={() => setSelectedTime(slot)}
                      className={`flex items-center justify-center gap-1 py-2 rounded-lg border-2 transition-colors ${
                        selectedTime === slot
                          ? "border-blue-500 bg-blue-50 text-blue-600 font-medium"
                          : "border-gray-300 hover:border-blue-300"
                      }`}
                    >
                      <Clock className="h-3 w-3" />
                      {slot}
                    </button>
                  ))}
                </div>
              ) : selectedDate ? (
                <div className="p-4 rounded-lg border border-gray-300 bg-gray-50 text-center">
                  <p className="text-gray-600">
                    Nenhum horário disponível para esta data
                  </p>
                </div>
              ) : (
                <div className="p-4 rounded-lg border border-gray-300 bg-gray-50 text-center">
                  <p className="text-gray-600">
                    Selecione uma data para ver os horários
                  </p>
                </div>
              )}
              <div className="space-y-2">
                <label className="text-sm font-medium">
                  Motivo da Consulta *
                </label>
                <textarea
                  placeholder="Descreva brevemente o motivo da consulta..."
                  value={motivo}
                  onChange={(e) => setMotivo(e.target.value)}
                  rows={4}
                  className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 resize-none"
                />
              </div>
              {selectedDate && selectedTime && (
                <div className="p-4 bg-blue-50 rounded-lg space-y-2">
                  <h4 className="font-semibold">Resumo</h4>
                  <div className="space-y-1 text-sm text-gray-600">
                    <p>📅 Data: {format(selectedDate, "dd/MM/yyyy")}</p>
                    <p>⏰ Horário: {selectedTime}</p>
                    <p>
                      📍 Tipo:{" "}
                      {appointmentType === "online" ? "Online" : "Presencial"}
                    </p>
                    {selectedMedico.valorConsulta && (
                      <p>
                        💰 Valor: R$ {selectedMedico.valorConsulta.toFixed(2)}
                      </p>
                    )}
                  </div>
                </div>
              )}
              <button
                onClick={handleBookAppointment}
                disabled={!selectedTime || !motivo.trim()}
                className="w-full py-3 rounded-lg font-semibold bg-blue-600 text-white hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors"
              >
                Confirmar Agendamento
              </button>
            </div>
          </div>
        </div>
      )}
      {showConfirmDialog && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
          <div className="bg-white rounded-lg shadow-xl max-w-md w-full p-6 space-y-4">
            <h3 className="text-xl font-semibold">Confirmar Agendamento</h3>
            <p className="text-gray-600">
              Revise os detalhes da sua consulta antes de confirmar
            </p>
            <div className="space-y-3">
              <div className="flex items-center gap-3">
                <div className="h-12 w-12 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 font-bold">
                  {selectedMedico?.nome
                    .split(" ")
                    .map((n) => n[0])
                    .join("")
                    .substring(0, 2)}
                </div>
                <div>
                  <p className="font-medium text-gray-900">
                    {selectedMedico?.nome}
                  </p>
                  <p className="text-sm text-gray-600">
                    {selectedMedico?.especialidade}
                  </p>
                </div>
              </div>
              <div className="space-y-2 text-sm text-gray-600">
                <p>
                  📅 Data: {selectedDate && format(selectedDate, "dd/MM/yyyy")}
                </p>
                <p>⏰ Horário: {selectedTime}</p>
                <p>
                  📍 Tipo:{" "}
                  {appointmentType === "online"
                    ? "Consulta Online"
                    : "Consulta Presencial"}
                </p>
                {selectedMedico?.valorConsulta && (
                  <p>💰 Valor: R$ {selectedMedico.valorConsulta.toFixed(2)}</p>
                )}
                <div className="mt-3 pt-3 border-t border-gray-200">
                  <p className="font-medium text-gray-900 mb-1">Motivo:</p>
                  <p className="text-gray-600">{motivo}</p>
                </div>
              </div>
            </div>
            <div className="flex gap-3 pt-4">
              <button
                onClick={() => setShowConfirmDialog(false)}
                className="flex-1 px-4 py-2 rounded-lg border border-gray-300 text-gray-700 hover:bg-gray-50 transition-colors"
              >
                Cancelar
              </button>
              <button
                onClick={confirmAppointment}
                className="flex-1 px-4 py-2 rounded-lg bg-blue-600 text-white hover:bg-blue-700 transition-colors font-medium"
              >
                Confirmar
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
