import React, { useState, useEffect, useMemo } from "react";
import HorariosDisponibilidade from "../components/doctors/HorariosDisponibilidade";
import { useAuth } from "../components/utils/AuthProvider";
import API_KEY from "../components/utils/apiKeys";
import "./style/DisponibilidadesDoctorPage.css";

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

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 DisponibilidadesDoctorPage = () => {
  const { getAuthorizationHeader } = useAuth();
  const [disponibilidades, setDisponibilidades] = useState([]);
  const [doctors, setDoctors] = useState([]);
  const [searchTerm, setSearchTerm] = useState("");
  const [editando, setEditando] = useState(null);
  const [expandedDoctors, setExpandedDoctors] = useState({});
  const [showSuggestions, setShowSuggestions] = useState(false);
  const [availabilityEdit, setAvailabilityEdit] = useState([]);

  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;
  };

  useEffect(() => {
    const fetchDoctors = async () => {
      try {
        const requestOptions = {
          method: "GET",
          headers: getHeaders(),
        };
        const response = await fetch(DOCTORS_ENDPOINT, requestOptions);
        const result = await response.json();
        setDoctors(Array.isArray(result) ? result : []);
      } catch (error) {
        setDoctors([]);
      }
    };
    fetchDoctors();
  }, [getAuthorizationHeader]);

  useEffect(() => {
    const fetchDisponibilidades = async () => {
      try {
        const res = await fetch(ENDPOINT, { method: "GET", headers: getHeaders() });
        if (res.ok) {
          const data = await res.json();
          setDisponibilidades(Array.isArray(data) ? data : []);
        }
      } catch (error) {
        setDisponibilidades([]);
      }
    };
    fetchDisponibilidades();
  }, [getAuthorizationHeader]);

  const toggleExpandDoctor = (doctorId) => {
    setExpandedDoctors((prev) => ({ ...prev, [doctorId]: !prev[doctorId] }));
  };

  const salvarTodasDisponibilidades = 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}?id=eq.${bloco.id}`, {
                  method: "PATCH",
                  headers,
                  body: JSON.stringify(payload),
                }).then(() => ({ type: 'PATCH', id: bloco.id }))
              );
            } else {
              promises.push(
                fetch(ENDPOINT, {
                  method: "POST",
                  headers,
                  body: JSON.stringify(payload),
                })
                .then(res => res.json())
                .then(data => {
                   const createdItem = Array.isArray(data) ? data[0] : data;
                   return { type: 'POST', id: createdItem?.id };
                })
              );
            }
          }
        }
      }

      const results = await Promise.all(promises);
      
      results.forEach(res => {
          if (res.type === 'POST' && res.id) currentIds.add(res.id);
      });

      const existingRes = await fetch(`${ENDPOINT}?doctor_id=eq.${String(doctorId)}`, { 
          method: "GET", headers 
      });
      
      if (existingRes.ok) {
          const existingData = await existingRes.json();
          const deletePromises = existingData
              .filter(dbItem => !currentIds.has(dbItem.id))
              .map(dbItem => 
                  fetch(`${ENDPOINT}?id=eq.${dbItem.id}`, { method: "DELETE", headers })
              );
          await Promise.all(deletePromises);
      }

      setEditando(null);
      setAvailabilityEdit([]);
      const res = await fetch(ENDPOINT, { method: "GET", headers: getHeaders() });
      if (res.ok) {
        const data = await res.json();
        setDisponibilidades(Array.isArray(data) ? data : []);
      }
    } catch (error) {
      console.error(error);
    }
  };

  const deletarDisponibilidade = async (id) => {
    if (!window.confirm("Deseja realmente excluir esta disponibilidade?")) return;
    try {
      const res = await fetch(`${ENDPOINT}?id=eq.${id}`, { method: "DELETE", headers: getHeaders() });
      if (res.ok) setDisponibilidades((prev) => prev.filter((d) => d.id !== id));
    } catch (error) {}
  };

  const disponibilidadesAgrupadas = useMemo(() => {
    const agrupadas = {};
    doctors.forEach((doctor) => {
      agrupadas[doctor.id] = {
        doctor_id: doctor.id,
        doctor_name: doctor.full_name || doctor.name,
        disponibilidades: [],
      };
    });
    disponibilidades.forEach((disp) => {
      if (agrupadas[disp.doctor_id]) agrupadas[disp.doctor_id].disponibilidades.push(disp);
    });
    Object.values(agrupadas).forEach((grupo) => {
      if (grupo.disponibilidades.length === 0) {
        grupo.disponibilidades.push({
          id: `empty-${grupo.doctor_id}`,
          doctor_id: grupo.doctor_id,
          doctor_name: grupo.doctor_name,
          is_empty: true,
        });
      }
    });
    let resultado = Object.values(agrupadas);
    if (searchTerm) resultado = resultado.filter((grupo) => grupo.doctor_name.toLowerCase().includes(searchTerm.toLowerCase()));
    return resultado;
  }, [disponibilidades, doctors, searchTerm]);

  const formatTime = (timeString) => {
    if (!timeString) return "";
    return timeString.includes(":") ? timeString.substring(0, 5) : timeString;
  };

  const getDiaSemana = (weekday) => {
    const dias = {
      0: "Domingo",
      1: "Segunda",
      2: "Terça",
      3: "Quarta",
      4: "Quinta",
      5: "Sexta",
      6: "Sábado",
      sunday: "Domingo",
      monday: "Segunda",
      tuesday: "Terça",
      wednesday: "Quarta",
      thursday: "Quinta",
      friday: "Sexta",
      saturday: "Sábado",
    };
    const key = typeof weekday === "string" ? weekday.toLowerCase() : weekday;
    return dias[key] || "Desconhecido";
  };

  const initialAvailabilityParaEdicao = useMemo(() => {
    if (!editando) return [];
    const disponibilidadesMedico = disponibilidades.filter((d) => String(d.doctor_id) === String(editando));
    const blocosPorDia = {};
    disponibilidadesMedico.forEach((d) => {
      const num = typeof d.weekday === "string" ? weekdayStrToNum[d.weekday.toLowerCase()] : d.weekday;
      if (num === undefined) return;
      if (!blocosPorDia[num]) blocosPorDia[num] = [];
      if (d.active !== false) {
        blocosPorDia[num].push({
          id: d.id,
          inicio: formatTime(d.start_time) || "07:00",
          termino: formatTime(d.end_time) || "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;
  }, [disponibilidades, editando]);

  const handleUpdateHorarios = (horariosAtualizados) => {
    if (!editando) return;
    setAvailabilityEdit(horariosAtualizados || []);
  };

  const filteredDoctors = useMemo(() => {
    if (!searchTerm) return doctors;
    return doctors.filter((doc) => (doc.full_name || doc.name).toLowerCase().includes(searchTerm.toLowerCase()));
  }, [doctors, searchTerm]);

  const handleCancelarEdicao = () => {
    setEditando(null);
    setAvailabilityEdit([]);
  };

  const handleDoctorSelect = (doctor) => {
    setSearchTerm(doctor.full_name || doctor.name);
    setShowSuggestions(false);
  };

  const handleClearSearch = () => {
    setSearchTerm("");
    setShowSuggestions(false);
  };

  const getStatusBadgeClass = (disp) => {
    if (disp.is_empty) return "status-badge status-not-configured";
    if (disp.active === false) return "status-badge status-inactive";
    return "status-badge status-active";
  };

  const getStatusText = (disp) => {
    if (disp.is_empty) return "Não configurado";
    if (disp.active === false) return "Inativa";
    return "Ativa";
  };

  return (
    <div className="disponibilidades-container">
      <h1 className="disponibilidades-title">Disponibilidades dos Médicos</h1>

      <div className="search-container">
        <div className="search-input-container">
          <input
            type="text"
            placeholder="Buscar médico por nome..."
            value={searchTerm}
            onChange={(e) => {
              setSearchTerm(e.target.value);
              setShowSuggestions(true);
            }}
            onFocus={() => setShowSuggestions(true)}
            className="search-input"
          />
          {searchTerm && (
            <button onClick={handleClearSearch} className="clear-search-btn">
              ×
            </button>
          )}
        </div>

        {showSuggestions && searchTerm && filteredDoctors.length > 0 && (
          <div className="suggestions-dropdown">
            {filteredDoctors.map((doc) => (
              <div key={doc.id} onClick={() => handleDoctorSelect(doc)} className="suggestion-item">
                {doc.full_name || doc.name}
              </div>
            ))}
          </div>
        )}
      </div>

      <section className="calendario-ou-filaespera">
        <div className="fila-container">
          <h2 className="section-title">{editando ? `Editar Horários` : "Lista de Disponibilidades"}</h2>

          {doctors.length === 0 ? (
            <p className="loading-text">Carregando médicos...</p>
          ) : editando ? (
            <>
              <div className="edit-container">
                {initialAvailabilityParaEdicao.length > 0 ? (
                  <HorariosDisponibilidade initialAvailability={initialAvailabilityParaEdicao} onUpdate={handleUpdateHorarios} onCancel={handleCancelarEdicao} />
                ) : (
                  <p className="loading-text">Carregando horários para edição...</p>
                )}
              </div>

              <div className="disp-buttons-container">
                <button
                  onClick={() =>
                    salvarTodasDisponibilidades(editando, availabilityEdit.length > 0 ? availabilityEdit : initialAvailabilityParaEdicao)
                  }
                  className="disp-btn-primary"
                >
                  Salvar Alterações
                </button>

                <button onClick={handleCancelarEdicao} className="disp-btn-danger">
                  Cancelar
                </button>
              </div>
            </>
          ) : (
            <div className="doctor-group-container">
              {disponibilidadesAgrupadas.length === 0 ? (
                <p className="no-results">Nenhum médico encontrado</p>
              ) : (
                disponibilidadesAgrupadas.map((grupo) => (
                  <div key={grupo.doctor_id} className={`doctor-group ${expandedDoctors[grupo.doctor_id] ? "expanded" : ""}`}>
                    <div className="doctor-header" onClick={() => toggleExpandDoctor(grupo.doctor_id)}>
                      <h3 className="doctor-name">
                        {grupo.doctor_name}
                        <span className="doctor-hours">({grupo.disponibilidades.filter((d) => !d.is_empty).length} horários)</span>
                      </h3>
                      <span className={`expand-icon ${expandedDoctors[grupo.doctor_id] ? "expanded" : ""}`}>▼</span>
                    </div>

                    {expandedDoctors[grupo.doctor_id] && (
                      <div className="doctor-content">
                        <div className="edit-btn-container">
                          <button onClick={() => setEditando(grupo.doctor_id)} className="disp-btn-edit">
                            {grupo.disponibilidades.some((d) => !d.is_empty) ? "Editar" : "Cadastrar Horários"}
                          </button>
                        </div>

                        <div className="table-container">
                          <table className="disponibilidades-table">
                            <thead>
                              <tr>
                                <th>Dia da Semana</th>
                                <th>Início</th>
                                <th>Término</th>
                                <th>Intervalo (min)</th>
                                <th>Tipo</th>
                                <th>Status</th>
                                <th>Ações</th>
                              </tr>
                            </thead>
                            <tbody>
                              {grupo.disponibilidades.map((disp) => (
                                <tr key={disp.id}>
                                  <td>{disp.is_empty ? "Nenhum horário cadastrado" : getDiaSemana(disp.weekday)}</td>
                                  <td>{disp.is_empty ? "-" : formatTime(disp.start_time)}</td>
                                  <td>{disp.is_empty ? "-" : formatTime(disp.end_time)}</td>
                                  <td>{disp.is_empty ? "-" : disp.slot_minutes || 30}</td>
                                  <td>{disp.is_empty ? "-" : disp.appointment_type || "presencial"}</td>
                                  <td>
                                    <span className={getStatusBadgeClass(disp)}>{getStatusText(disp)}</span>
                                  </td>
                                  <td>{!disp.is_empty && <button onClick={() => deletarDisponibilidade(disp.id)} className="disp-btn-delete">Excluir</button>}</td>
                                </tr>
                              ))}
                            </tbody>
                          </table>
                        </div>
                      </div>
                    )}
                  </div>
                ))
              )}
            </div>
          )}
        </div>
      </section>
    </div>
  );
};

export default DisponibilidadesDoctorPage;