import React, { useState, useEffect, useMemo } from "react";
import { useParams, useNavigate, useLocation } from "react-router-dom";
import DoctorForm from "../components/doctors/DoctorForm";
import { useAuth } from "../components/utils/AuthProvider";
import API_KEY from "../components/utils/apiKeys";

const ENDPOINT = "https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors";
const ENDPOINT_AVAILABILITY = "https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctor_availability";

const diasDaSemana = ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"];
const weekdayNumToStr = {
  0: "sunday",
  1: "monday",
  2: "tuesday",
  3: "wednesday",
  4: "thursday",
  5: "friday",
  6: "saturday",
};
const weekdayStrToNum = Object.fromEntries(
  Object.entries(weekdayNumToStr).map(([num, str]) => [str, Number(num)])
);

const EditDoctorPage = () => {
  const { id } = useParams();
  const navigate = useNavigate();
  const location = useLocation();
  const { getAuthorizationHeader } = useAuth();
  
  const [doctor, setDoctor] = useState(null);
  const [availability, setAvailability] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);

  const effectiveId = id;

  const getHeaders = () => {
    const myHeaders = new Headers();
    const authHeader = getAuthorizationHeader();
    if (authHeader) myHeaders.append("Authorization", authHeader);
    myHeaders.append("Content-Type", "application/json");
    if (API_KEY) myHeaders.append("apikey", API_KEY);
    myHeaders.append("Prefer", "return=representation");
    return myHeaders;
  };

  const salvarDisponibilidades = async (doctorId, horariosAtualizados) => {
    try {
      const headers = getHeaders();
      const promises = [];
      const currentIds = new Set();

      for (const dia of horariosAtualizados) {
        if (dia.isChecked && dia.blocos.length > 0) {
          for (const bloco of dia.blocos) {
            const inicio = bloco.inicio.includes(":") ? bloco.inicio : bloco.inicio + ":00";
            const termino = bloco.termino.includes(":") ? bloco.termino : bloco.termino + ":00";

            const payload = {
              doctor_id: doctorId,
              weekday: weekdayNumToStr[dia.weekday],
              start_time: inicio,
              end_time: termino,
              slot_minutes: bloco.slot_minutes || 30,
              appointment_type: bloco.appointment_type || "presencial",
              active: true,
            };

            if (bloco.id && !bloco.isNew) {
              currentIds.add(bloco.id);
              promises.push(
                fetch(`${ENDPOINT_AVAILABILITY}?id=eq.${bloco.id}`, {
                  method: "PATCH",
                  headers,
                  body: JSON.stringify(payload),
                }).then((res) => {
                  if (!res.ok) throw new Error(`Erro no PATCH: ${res.status}`);
                  return { type: "PATCH", id: bloco.id };
                })
              );
            } else {
              promises.push(
                fetch(ENDPOINT_AVAILABILITY, {
                  method: "POST",
                  headers,
                  body: JSON.stringify(payload),
                })
                  .then((res) => res.json())
                  .then((data) => {
                     const createdItem = Array.isArray(data) ? data[0] : data;
                     if (createdItem && createdItem.id) {
                       return { type: "POST", id: createdItem.id };
                     }
                     return { type: "POST", id: null };
                  })
              );
            }
          }
        }
      }

      const results = await Promise.all(promises);

      results.forEach((res) => {
        if (res.type === "POST" && res.id) currentIds.add(res.id);
      });

      const existingDisponibilidadesRes = await fetch(
        `${ENDPOINT_AVAILABILITY}?doctor_id=eq.${String(doctorId)}`,
        { method: "GET", headers }
      );
      
      if (existingDisponibilidadesRes.ok) {
        const existingDisponibilidades = await existingDisponibilidadesRes.json();
        
        const deletePromises = existingDisponibilidades
          .filter((disp) => !currentIds.has(disp.id))
          .map((disp) =>
            fetch(`${ENDPOINT_AVAILABILITY}?id=eq.${disp.id}`, {
              method: "DELETE",
              headers,
            })
          );

        await Promise.all(deletePromises);
      }

      const updatedResponse = await fetch(
        `${ENDPOINT_AVAILABILITY}?doctor_id=eq.${doctorId}&order=weekday.asc,start_time.asc`,
        { method: "GET", headers }
      );

      if (updatedResponse.ok) {
        const updatedData = await updatedResponse.json();
        setAvailability(updatedData);
      }
    } catch (error) {
      throw error;
    }
  };

  const normalizeAvailabilityForForm = (availabilityData) => {
    if (!Array.isArray(availabilityData)) return [];

    const disponibilidadesMedico = availabilityData.filter((d) => 
      String(d.doctor_id) === String(effectiveId) && d.active !== false
    );
    const blocosPorDia = {};
    
    disponibilidadesMedico.forEach((d) => {
      const num = typeof d.weekday === "string" ? weekdayStrToNum[d.weekday.toLowerCase()] : d.weekday;
      if (num === undefined || num === null) return;
      if (!blocosPorDia[num]) blocosPorDia[num] = [];
      blocosPorDia[num].push({
        id: d.id,
        inicio: d.start_time?.substring(0, 5) || "07:00",
        termino: d.end_time?.substring(0, 5) || "17:00",
        slot_minutes: d.slot_minutes || 30,
        appointment_type: d.appointment_type || "presencial",
        isNew: false,
      });
    });
    
    const resultado = [1, 2, 3, 4, 5, 6, 0].map((weekday) => {
      const blocosDoDia = blocosPorDia[weekday] || [];
      return {
        dia: diasDaSemana[weekday],
        weekday: weekday,
        isChecked: blocosDoDia.length > 0,
        blocos:
          blocosDoDia.length > 0
            ? blocosDoDia
            : [
                {
                  id: null,
                  inicio: "07:00",
                  termino: "17:00",
                  slot_minutes: 30,
                  appointment_type: "presencial",
                  isNew: true,
                },
              ],
      };
    });
    
    return resultado;
  };

  const availabilityFormatted = useMemo(() => {
    return normalizeAvailabilityForForm(availability);
  }, [availability, effectiveId]);

  useEffect(() => {
    const fetchDoctorData = async () => {
      if (!effectiveId || effectiveId === "edit") {
        alert("ID do médico não encontrado");
        navigate("/secretaria/medicos");
        return;
      }

      try {
        const doctorResponse = await fetch(`${ENDPOINT}?id=eq.${effectiveId}`, {
          method: "GET",
          headers: getHeaders(),
        });

        if (!doctorResponse.ok) {
          throw new Error("Erro ao carregar dados do médico");
        }

        const doctorData = await doctorResponse.json();
        if (doctorData.length === 0) {
          throw new Error("Médico não encontrado");
        }

        setDoctor(doctorData[0]);

        const availabilityResponse = await fetch(
          `${ENDPOINT_AVAILABILITY}?doctor_id=eq.${effectiveId}&order=weekday.asc,start_time.asc`, 
          {
            method: "GET",
            headers: getHeaders(),
          }
        );

        if (availabilityResponse.ok) {
          const availabilityData = await availabilityResponse.json();
          setAvailability(availabilityData);
        } else {
          setAvailability([]);
        }

      } catch (error) {
        alert("Erro ao carregar dados do médico");
        navigate("/secretaria/medicos");
      } finally {
        setIsLoading(false);
      }
    };

    if (effectiveId) {
      fetchDoctorData();
    }
  }, [effectiveId, navigate]);

  const handleSave = async (formData) => {
    const { availability: updatedAvailability, ...doctorDataToSave } = formData;
    
    try {
      setIsSaving(true);

      const response = await fetch(`${ENDPOINT}?id=eq.${effectiveId}`, {
        method: "PATCH",
        headers: getHeaders(),
        body: JSON.stringify(doctorDataToSave),
      });

      if (!response.ok) {
        throw new Error("Erro ao salvar dados do médico");
      }
      
      if (updatedAvailability && updatedAvailability.length > 0) {
        await salvarDisponibilidades(effectiveId, updatedAvailability);
      }

      alert("Médico e horários atualizados com sucesso!");
      navigate("/secretaria/medicos");

    } catch (error) {
      alert(`Erro ao salvar dados: ${error.message}`);
    } finally {
      setIsSaving(false);
    }
    console.log('Horários a serem salvos:', updatedAvailability);
  };

  const handleCancel = () => {
    navigate("/secretaria/medicos");
  };

  if (isLoading) {
    return (
      <div className="container mt-4">
        <div className="d-flex justify-content-center">
          <div className="spinner-border" role="status">
            <span className="visually-hidden">Carregando...</span>
          </div>
        </div>
        <p className="text-center mt-2">
          Carregando dados do médico ID: {effectiveId || "..."}
        </p>
      </div>
    );
  }

  if (!doctor) {
    if (!isLoading) {
      return (
        <div className="container mt-4">
          <div className="alert alert-danger">
            Médico não encontrado
          </div>
        </div>
      );
    }
    return null;
  }

  const formData = {
    ...doctor,
    availability: (doctor && doctor.availability) ? doctor.availability : availabilityFormatted,
  };

  return (
    <div className="container mt-4">
      <div className="row">
        <div className="col-12">
          <h1>Editar Médico</h1>
          <DoctorForm
            formData={formData}
            setFormData={setDoctor}
            onSave={handleSave}
            onCancel={handleCancel}
            isLoading={isSaving}
            isEditing={true}
          />
        </div>
      </div>
    </div>
  );
};

export default EditDoctorPage;