"use client";

import dynamic from "next/dynamic";
import { useState, useEffect, useCallback, useRef } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { useAuth } from "@/context/AuthContext";

const API_BASE = "";

const DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December",
];

function DatePicker({ value, minDate, onChange }) {
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const min = minDate ? new Date(minDate + "T00:00:00") : today;

  const parsed = value ? new Date(value + "T00:00:00") : null;
  const [viewYear, setViewYear] = useState(parsed ? parsed.getFullYear() : min.getFullYear());
  const [viewMonth, setViewMonth] = useState(parsed ? parsed.getMonth() : min.getMonth());

  function prevMonth() {
    if (viewMonth === 0) { 
      setViewMonth(11); 
      setViewYear((y) => y - 1); 
    }
    
    else {
      setViewMonth((m) => m - 1);
    }
  }

  function nextMonth() {
    if (viewMonth === 11) { 
      setViewMonth(0); setViewYear((y) => y + 1); 
    }

    else {
      setViewMonth((m) => m + 1);
    }
  }

  const firstDay = new Date(viewYear, viewMonth, 1).getDay();
  const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();

  const minYear = min.getFullYear();
  const minMonth = min.getMonth();
  const isPrevDisabled = viewYear < minYear || (viewYear === minYear && viewMonth <= minMonth);

  function selectDay(day) {
    const d = new Date(viewYear, viewMonth, day);
    if (d < min) {
      return;
    }
    const iso = `${viewYear}-${String(viewMonth + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;

    onChange(iso);
  }

  function isSelected(day) {
    if (!parsed) return false;
    return parsed.getFullYear() === viewYear && parsed.getMonth() === viewMonth && parsed.getDate() === day;
  }

  function isDisabled(day) {
    return new Date(viewYear, viewMonth, day) < min;
  }

  const cells = [];
  for (let i = 0; i < firstDay; i++) {
    cells.push({ key: `empty-${viewYear}-${viewMonth}-${String(i)}`, day: null });
  }
  for (let d = 1; d <= daysInMonth; d++) {
    cells.push({ key: `day-${viewYear}-${viewMonth}-${String(d)}`, day: d });
  }

  const s = {
    widget: {
      border: "1px solid #ddd",
      borderRadius: "10px",
      overflow: "hidden",
      background: "white",
      userSelect: "none",
      fontFamily: "inherit",
    },
    header: {
      display: "flex",
      alignItems: "center",
      justifyContent: "space-between",
      background: "orange",
      padding: "0.55rem 0.75rem",
    },
    monthLabel: {
      fontSize: "0.95rem",
      fontWeight: 700,
      color: "white",
    },
    nav: {
      background: "none",
      border: "none",
      color: "white",
      fontSize: "1.5rem",
      lineHeight: 1,
      cursor: "pointer",
      padding: "0 0.4rem",
      borderRadius: "4px",
    },
    grid: {
      display: "grid",
      gridTemplateColumns: "repeat(7, 1fr)",
      gap: "3px",
      padding: "0.6rem",
    },
    dayName: {
      textAlign: "center",
      fontSize: "0.7rem",
      fontWeight: 700,
      color: "#aaa",
      padding: "0.25rem 0",
      textTransform: "uppercase",
    },
    dayBase: {
      display: "flex",
      alignItems: "center",
      justifyContent: "center",
      aspectRatio: "1 / 1",
      border: "none",
      borderRadius: "6px",
      background: "none",
      fontSize: "0.875rem",
      cursor: "pointer",
      color: "#333",
      fontFamily: "inherit",
      padding: 0,
      width: "100%",
    },
    daySelected: {
      background: "orange",
      color: "white",
      fontWeight: 700,
    },
    dayDisabled: {
      color: "#ccc",
      cursor: "default",
    },
    selectedLabel: {
      textAlign: "center",
      fontSize: "0.82rem",
      color: "#666",
      padding: "0.35rem 0.5rem 0.5rem",
      borderTop: "1px solid #f0f0f0",
    },
  };

  return (
    <div style={s.widget}>
      <div style={s.header}>
        <button type="button" style={s.nav} onClick={prevMonth} disabled={isPrevDisabled} aria-label="Previous month">‹</button>
        <span style={s.monthLabel}>{MONTHS[viewMonth]} {viewYear}</span>
        <button type="button" style={s.nav} onClick={nextMonth} aria-label="Next month">›</button>
      </div>
      <div style={s.grid}>
        {DAYS.map((d) => (
          <span key={d} style={s.dayName}>{d}</span>
        ))}
        {cells.map(({ key, day }) =>
          day === null ? (
            <span key={key} />
          ) : (
            <button
              key={key}
              type="button"
              style={{
                ...s.dayBase,
                ...(isSelected(day) ? s.daySelected : {}),
                ...(isDisabled(day) ? s.dayDisabled : {}),
              }}
              onClick={() => selectDay(day)}
              disabled={isDisabled(day)}
              aria-pressed={isSelected(day)}
            >
              {day}
            </button>
          )
        )}
      </div>
      {parsed && (
        <div style={s.selectedLabel}>
          Selected: {MONTHS[parsed.getMonth()]} {parsed.getDate()}, {parsed.getFullYear()}
        </div>
      )}
    </div>
  );
}

function AddPetModal({ token, onClose, onAdded }) {
  const [petName, setPetName] = useState("");
  const [species, setSpecies] = useState("");
  const [breed, setBreed] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [petError, setPetError] = useState(null);

  async function handleSubmit(e) {
    e.preventDefault();
    setPetError(null);
    setSubmitting(true);

    try {
      const res = await fetch(`${API_BASE}/api/v1/my-pets`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({ petName, species, breed: breed || null }),
      });

      if (!res.ok) {
        const data = await res.json().catch(() => null);
        throw new Error(data?.message || `Request failed (${res.status})`);
      }

      onAdded();
      onClose();
    }

    catch (err) {
      setPetError(err.message);
    }

    finally {
      setSubmitting(false);
    }
  }

  return (
    <div className="appt-modal-overlay" onClick={onClose}>
      <div className="appt-modal" onClick={(e) => e.stopPropagation()}>
        <h3 className="profile-pet-form-title">Add a New Pet</h3>
        {petError && <div className="appt-error">{petError}</div>}
        <form onSubmit={handleSubmit}>
          <label className="appt-label">
            Name
            <input
              className="appt-input"
              type="text"
              value={petName}
              onChange={(e) => setPetName(e.target.value)}
              required
              maxLength={50}
            />
          </label>
          <label className="appt-label">
            Species
            <input
              className="appt-input"
              type="text"
              value={species}
              onChange={(e) => setSpecies(e.target.value)}
              required
              maxLength={50}
              placeholder="e.g. Dog, Cat, Bird"
            />
          </label>
          <label className="appt-label">
            Breed (optional)
            <input
              className="appt-input"
              type="text"
              value={breed}
              onChange={(e) => setBreed(e.target.value)}
              maxLength={50}
              placeholder="e.g. Golden Retriever"
            />
          </label>
          <div className="profile-pet-form-actions">
            <button type="submit" className="appt-submit-btn" disabled={submitting}>
              {submitting ? "Saving..." : "Add Pet"}
            </button>
            <button type="button" className="profile-pet-cancel-btn" onClick={onClose}>
              Cancel
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

function AppointmentsPage() {
  const { user, token, loading: authLoading } = useAuth();
  const router = useRouter();
  const searchParams = useSearchParams();
  const preselectedPetId = searchParams.get("petId");
  const didPreselectRef = useRef(false);

  const [stores, setStores] = useState([]);
  const [employees, setEmployees] = useState([]);
  const [services, setServices] = useState([]);
  const [allPets, setAllPets] = useState([]);
  const [customerPets, setCustomerPets] = useState([]);
  const [availableSlots, setAvailableSlots] = useState([]);

  const [storeId, setStoreId] = useState("");
  const [serviceId, setServiceId] = useState("");
  const [employeeId, setEmployeeId] = useState("");
  const [appointmentDate, setAppointmentDate] = useState("");
  const [appointmentTime, setAppointmentTime] = useState("");
  const [selectedPetIds, setSelectedPetIds] = useState([]);

  const [loadingSlots, setLoadingSlots] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);
  const [success, setSuccess] = useState(null);

  const [appointments, setAppointments] = useState([]);
  const [loadingAppointments, setLoadingAppointments] = useState(false);

  const [showAddPetModal, setShowAddPetModal] = useState(false);

const canBookAppointments = user?.role === "CUSTOMER" || user?.role === "ADMIN";

  useEffect(() => {
    if (!authLoading && !user) {
      const target = preselectedPetId ? `/appointments?petId=${encodeURIComponent(preselectedPetId)}` : "/appointments";
      router.push(`/login?next=${encodeURIComponent(target)}`);
    }

  }, [authLoading, user, router, preselectedPetId]);

  const loadCustomerPets = useCallback(() => {
    if (!token || !canBookAppointments) return;
    fetch(`${API_BASE}/api/v1/my-pets`, {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then((r) => r.json())
      .then((data) => setCustomerPets(Array.isArray(data) ? data : []))
      .catch(() => {});
  }, [token, canBookAppointments]);

  useEffect(() => {
    if (!token) {
      return;
    }

    fetch(`${API_BASE}/api/v1/dropdowns/stores`, {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then((r) => r.json())
      .then(setStores)
      .catch(() => {});

    fetch(`${API_BASE}/api/v1/services?size=100`)
      .then((r) => r.json())
      .then((data) => setServices(data.content ?? []))
      .catch(() => {});

    fetch(`${API_BASE}/api/v1/pets?size=200&sort=id,asc&status=Available`)
      .then((r) => r.json())
      .then((data) => setAllPets(data.content ?? []))
      .catch(() => {});

    loadCustomerPets();
  }, [token, loadCustomerPets]);

  useEffect(() => {
    if (didPreselectRef.current) {
      return;
    }
    if (!preselectedPetId || services.length === 0 || allPets.length === 0) {
      return;
    }

    const adoptionSvc = services.find((s) =>
      s.serviceName.toLowerCase().includes("adopt")
    );

    if (adoptionSvc) {
      setServiceId(String(adoptionSvc.serviceId));
    }
    setSelectedPetIds([Number(preselectedPetId)]);
    didPreselectRef.current = true;
  }, [preselectedPetId, services, allPets]);

  const loadAppointments = useCallback(() => {

    if (!token) {
      return;
    }
    setLoadingAppointments(true);
    fetch(`${API_BASE}/api/v1/appointments?size=50&sort=appointmentDate,desc`, {
      headers: {Authorization: `Bearer ${token}`},
    })
      .then((r) => r.json())
      .then((data) => setAppointments(data.content ?? []))
      .catch(() => {})
      .finally(() => setLoadingAppointments(false));
  }, [token]);

  useEffect(() => {
    loadAppointments();
  }, [loadAppointments]);

  useEffect(() => {
    if (!token || !storeId) {
      setEmployees([]);
      setEmployeeId("");
      return;
    }

    fetch(`${API_BASE}/api/v1/dropdowns/stores/${storeId}/employees`, {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then((r) => r.json())
      .then((data) => setEmployees(Array.isArray(data) ? data : []))
      .catch(() => setEmployees([]));
  }, [token, storeId]);

  useEffect(() => {
    if (!employees.length) {
      setEmployeeId("");
      return;
    }

    const currentExists = employees.some((employee) => String(employee.id) === String(employeeId));
    if (!currentExists) {
      setEmployeeId(String(employees[0].id));
    }
  }, [employees, employeeId]);

  useEffect(() => {
    if (!storeId || !serviceId || !appointmentDate) {
      setAvailableSlots([]);
      setAppointmentTime("");

      return;
    }
    setLoadingSlots(true);
    setAppointmentTime("");
    const params = new URLSearchParams({ storeId, serviceId, date: appointmentDate });
    fetch(`${API_BASE}/api/v1/appointments/availability?${params}`)
      .then((r) => {
        if (!r.ok) {
          throw new Error("Failed to check availability");
        }

        return r.json();
      })
      .then(setAvailableSlots)
      .catch(() => setAvailableSlots([]))
      .finally(() => setLoadingSlots(false));
  }, [storeId, serviceId, appointmentDate]);

  const selectedService = services.find((s) => s.serviceId === Number(serviceId));
  const isAdoptionService = selectedService ? selectedService.serviceName.toLowerCase().includes("adopt") : false;
  const isCustomerPetService = !!selectedService && !isAdoptionService;

  const adoptablePets = allPets.filter(
    (p) => p.petStatus && p.petStatus.toLowerCase() === "available"
  );

  function handleServiceChange(newServiceId) {
    setServiceId(newServiceId);
    setSelectedPetIds([]);
  }

  function togglePet(petId) {
    if (isAdoptionService) {
      setSelectedPetIds((prev) =>
        prev.includes(petId) ? [] : [petId]
      );
    } 
    
    else {
      setSelectedPetIds((prev) =>
        prev.includes(petId) ? prev.filter((id) => id !== petId) : [...prev, petId]
      );
    }
  }

  function formatTime(timeStr) {
    const [h, m] = timeStr.split(":");
    const hour = parseInt(h, 10);
    const ampm = hour >= 12 ? "PM" : "AM";
    const display = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;

    return `${display}:${m} ${ampm}`;
  }

  function getMinDate() {
    const d = new Date();

    return d.toISOString().split("T")[0];
  }

  const formValid =
    storeId && serviceId && appointmentDate && appointmentTime && selectedPetIds.length > 0;

  async function handleSubmit(e) {
    e.preventDefault();
    setError(null);
    setSuccess(null);

    if (!canBookAppointments) {
      setError("Only customer accounts can book appointments from the web app.");

      return;
    }

    if (selectedPetIds.length === 0) {
      setError(isAdoptionService ? "Please select a pet to adopt." : "Please select at least one pet.");

      return;
    }

    setSubmitting(true);

    try {
      const body = {
        customerId: user.customerId || user.id,
        storeId: Number(storeId),
        serviceId: Number(serviceId),
        employeeId: employeeId ? Number(employeeId) : undefined,
        appointmentDate,
        appointmentTime: appointmentTime + ":00",
        appointmentStatus: "Booked",
      };

      if (selectedPetIds.length > 0) {
        body.petId = selectedPetIds[0];
      }

      const res = await fetch(`${API_BASE}/api/v1/appointments`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify(body),
      });

      if (!res.ok) {
        const data = await res.json().catch(() => null);

        throw new Error(data?.message || data?.error || `Request failed (${res.status})`);
      }

      setSuccess("Appointment booked successfully!");
      setStoreId("");
      setServiceId("");
      setAppointmentDate("");
      setAppointmentTime("");
      setSelectedPetIds([]);
      setAvailableSlots([]);
      loadAppointments();
    } 
    
    catch (err) {
      setError(err.message);
    } 
    
    finally {
      setSubmitting(false);
    }
  }

  if (authLoading) {
    
    return (
      <main className="appt-page">
        <p className="appt-loading">Loading...</p>
      </main>
    );
  }

  if (!user) return null;

  const petsToShow = isAdoptionService ? adoptablePets : isCustomerPetService ? customerPets : [];
  const petSectionLabel = isAdoptionService ? "Select a Pet to Adopt" : "Select Pet(s)";
  const noPetsMessage = isAdoptionService
    ? "No pets are currently available for adoption."
    : "No pets found on your profile.";

  return (
    <main className="appt-page">
      {showAddPetModal && (
        <AddPetModal
          token={token}
          onClose={() => setShowAddPetModal(false)}
          onAdded={loadCustomerPets}
        />
      )}

      <section className="appt-hero">
        <h1 className="appt-hero-title">Schedule an Appointment</h1>
        <p className="appt-hero-subtitle">Book a service for your pet or schedule a pet adoption visit</p>
        <div className="title-decoration"></div>
      </section>

      <section className="appt-content">
        {canBookAppointments ? (
          <form className="appt-form" onSubmit={handleSubmit}>
            <h2 className="appt-form-title">New Appointment</h2>

            {error && <div className="appt-error">{error}</div>}
            {success && <div className="appt-success">{success}</div>}

            <label className="appt-label">
              Store Location
              <select
                className="appt-select"
                value={storeId}
                onChange={(e) => setStoreId(e.target.value)}
                required
              >
                <option value="">Select a store...</option>
                {stores.map((s) => (
                  <option key={s.id} value={s.id}>{s.label}</option>
                ))}
              </select>
            </label>

            <label className="appt-label">
              Service
              <select
                className="appt-select"
                value={serviceId}
                onChange={(e) => handleServiceChange(e.target.value)}
                required
              >
                <option value="">Select a service...</option>
                {services.map((s) => (
                  <option key={s.serviceId} value={s.serviceId}>
                    {s.serviceName} — ${Number(s.servicePrice).toFixed(2)} ({s.serviceDuration} min)
                  </option>
                ))}
              </select>
            </label>

            {employees.length > 0 && (
              <label className="appt-label">
                Employee
                <select
                  className="appt-select"
                  value={employeeId}
                  onChange={(e) => setEmployeeId(e.target.value)}
                >
                  {employees.map((employee) => (
                    <option key={employee.id} value={employee.id}>{employee.label}</option>
                  ))}
                </select>
              </label>
            )}

            {selectedService && (
              <div className="appt-service-info">
                <p>{selectedService.serviceDesc}</p>
              </div>
            )}

            <div className="appt-label">
              Date
              <DatePicker
                value={appointmentDate}
                minDate={getMinDate()}
                onChange={setAppointmentDate}
              />
            </div>

            {storeId && serviceId && appointmentDate && (
              <div className="appt-label">
                <span>Available Time Slots</span>
                {loadingSlots ? (
                  <p className="appt-slots-loading">Checking availability...</p>
                ) : availableSlots.length === 0 ? (
                  <p className="appt-no-slots">No available slots for this date. Please try another date.</p>
                ) : (
                  <div className="appt-slots-grid">
                    {availableSlots.map((slot) => (
                      <button
                        key={slot}
                        type="button"
                        className={`appt-slot-btn ${appointmentTime === slot ? "appt-slot-btn--selected" : ""}`}
                        onClick={() => setAppointmentTime(slot)}
                      >
                        {formatTime(slot)}
                      </button>
                    ))}
                  </div>
                )}
              </div>
            )}

            {serviceId && (
              <div className="appt-label">
                <span>{petSectionLabel}</span>
                {isCustomerPetService && (
                  <button
                    type="button"
                    className="appt-add-pet-btn"
                    onClick={() => setShowAddPetModal(true)}
                  >
                    + Add New Pet
                  </button>
                )}
                {petsToShow.length === 0 ? (
                  <p className="appt-no-slots">{noPetsMessage}</p>
                ) : isAdoptionService ? (
                  <div className="appt-adopt-grid">
                    {petsToShow.map((p) => (
                      <label
                        key={p.petId}
                        className={`appt-adopt-card ${selectedPetIds.includes(p.petId) ? "appt-adopt-card--selected" : ""}`}
                      >
                        <input
                          type="radio"
                          name="adoptionPet"
                          value={p.petId}
                          checked={selectedPetIds.includes(p.petId)}
                          onChange={() => togglePet(p.petId)}
                          className="appt-adopt-radio"
                        />
                        {p.imageUrl ? (
                          <img src={p.imageUrl} alt={p.petName} className="appt-adopt-img" />
                        ) : (
                          <div className="appt-adopt-img-placeholder">🐾</div>
                        )}
                        <div className="appt-adopt-info">
                          <span className="appt-adopt-name">{p.petName}</span>
                          <span className="appt-adopt-detail">{p.petSpecies} · {p.petBreed}</span>
                          <span className="appt-adopt-detail">Age: {p.petAge}</span>
                        </div>
                      </label>
                    ))}
                  </div>
                ) : (
                  <div className="appt-pets-grid">
                    {petsToShow.map((p) => (
                      <label
                        key={p.customerPetId}
                        className={`appt-pet-chip ${selectedPetIds.includes(p.customerPetId) ? "appt-pet-chip--selected" : ""}`}
                      >
                        <input
                          type="checkbox"
                          checked={selectedPetIds.includes(p.customerPetId)}
                          onChange={() => togglePet(p.customerPetId)}
                          className="appt-pet-checkbox"
                        />
                        {p.petName}
                        <span className="appt-pet-chip-species">({p.species})</span>
                      </label>
                    ))}
                  </div>
                )}
              </div>
            )}

            <button
              type="submit"
              className="appt-submit-btn"
              disabled={!formValid || submitting}
            >
              {submitting ? "Booking..." : isAdoptionService ? "Schedule Adoption Visit" : "Book Appointment"}
            </button>
          </form>
        ) : null}

        <div className="appt-history">
          <h2 className="appt-form-title">{canBookAppointments ? "Your Appointments" : "Appointments"}</h2>
          {loadingAppointments ? (
            <p className="appt-loading">Loading appointments...</p>
          ) : appointments.length === 0 ? (
            <p className="appt-empty">No appointments yet.</p>
          ) : (
            <div className="appt-list">
              {appointments.map((a) => (
                <div key={a.appointmentId} className="appt-card">
                  <div className="appt-card-header">
                    <span className="appt-card-service">{a.serviceName}</span>
                    <span className={`appt-card-status appt-card-status--${a.appointmentStatus.toLowerCase()}`}>
                      {a.appointmentStatus}
                    </span>
                  </div>
                  <div className="appt-card-details">
                    <span>{a.storeName}</span>
                    <span>{a.appointmentDate} at {formatTime(a.appointmentTime)}</span>
                  </div>
                  {a.petNames && a.petNames.length > 0 && (
                    <div className="appt-card-pets">
                      Pets: {a.petNames.join(", ")}
                    </div>
                  )}
                  {a.customerPetNames && a.customerPetNames.length > 0 && (
                    <div className="appt-card-pets">
                      Pets: {a.customerPetNames.join(", ")}
                    </div>
                  )}
                </div>
              ))}
            </div>
          )}
        </div>
      </section>
    </main>
  );
}

export default dynamic(() => Promise.resolve(AppointmentsPage), {
  ssr: false,
});
