"use client";

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

const API_BASE = "";

const SPECIES_BREEDS = {
  Dog: ["Beagle", "Boxer", "Bulldog", "Chihuahua", "Dachshund", "German Shepherd", "Golden Retriever", "Labrador Retriever", "Poodle", "Rottweiler", "Shih Tzu", "Siberian Husky", "Yorkshire Terrier", "Mixed / Other"],
  Cat: ["Abyssinian", "Bengal", "British Shorthair", "Maine Coon", "Persian", "Ragdoll", "Scottish Fold", "Siamese", "Sphynx", "Mixed / Other"],
  Bird: ["Canary", "Cockatiel", "Cockatoo", "Finch", "Lovebird", "Macaw", "Parakeet", "Parrot", "Other"],
  Rabbit: ["Dutch", "Flemish Giant", "Holland Lop", "Lionhead", "Mini Rex", "Other"],
  Hamster: ["Dwarf", "Roborovski", "Syrian", "Other"],
  "Guinea Pig": ["Abyssinian", "American", "Peruvian", "Teddy", "Other"],
  Reptile: ["Ball Python", "Bearded Dragon", "Blue-tongued Skink", "Corn Snake", "Leopard Gecko", "Other"],
  Fish: ["Angelfish", "Betta", "Cichlid", "Clownfish", "Goldfish", "Guppy", "Tetra", "Other"],
  Other: ["Other"],
};

//Services that only apply to specific species, keyed by species name
const SPECIES_EXCLUSIVE_SERVICES = {
  Bird: ["wing clipping", "beak and nail"],
  Fish: ["aquarium health"],
};

//Services that are banned for specific species, keyed by species name
const SPECIES_BANNED_SERVICES = {
  Bird: ["teeth cleaning"],
};

//Filters out services that are exclusive to a different species, or banned for the selected species.
//When species is unknown, hides all species-exclusive and banned services to avoid invalid options appearing.
function getAvailableServices(services, species) {
  const exclusiveKeywords = Object.values(SPECIES_EXCLUSIVE_SERVICES).flat();
  const allBannedKeywords = Object.values(SPECIES_BANNED_SERVICES).flat();

  if (!species) {
    return services.filter((s) => {
      const name = s.serviceName.toLowerCase();
      return !exclusiveKeywords.some((kw) => name.includes(kw)) &&
             !allBannedKeywords.some((kw) => name.includes(kw));
    });
  }

  return services.filter((s) => {
    const name = s.serviceName.toLowerCase();
    for (const [exclusiveSpecies, keywords] of Object.entries(SPECIES_EXCLUSIVE_SERVICES)) {
      if (exclusiveSpecies !== species && keywords.some((kw) => name.includes(kw))) {
        return false;
      }
    }
    const banned = SPECIES_BANNED_SERVICES[species] ?? [];
    if (banned.some((kw) => name.includes(kw))) {
      return false;
    }
    return true;
  });
}

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

//Custom calendar date picker that prevents selecting dates in the past
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 });
  }

  return (
    <div className="border border-[#ddd] rounded-[10px] overflow-hidden bg-white select-none">
      <div className="flex items-center justify-between bg-orange-500 px-3 py-[0.55rem]">
        <button type="button" className="bg-transparent border-none text-white text-2xl leading-none cursor-pointer px-[0.4rem] rounded hover:bg-white/20 disabled:opacity-40" onClick={prevMonth} disabled={isPrevDisabled} aria-label="Previous month">‹</button>
        <span className="text-[0.95rem] font-bold text-white">{MONTHS[viewMonth]} {viewYear}</span>
        <button type="button" className="bg-transparent border-none text-white text-2xl leading-none cursor-pointer px-[0.4rem] rounded hover:bg-white/20" onClick={nextMonth} aria-label="Next month">›</button>
      </div>
      <div className="grid grid-cols-7 gap-[3px] p-[0.6rem]">
        {DAYS.map((d) => (
          <span key={d} className="text-center text-[0.7rem] font-bold text-[#aaa] py-1 uppercase">{d}</span>
        ))}
        {cells.map(({ key, day }) =>
          day === null ? (
            <span key={key} />
          ) : (
            <button
              key={key}
              type="button"
              className={`flex items-center justify-center aspect-square border-none rounded-md text-[0.875rem] cursor-pointer w-full p-0 transition-colors
                ${isSelected(day) ? "bg-orange-500 text-white font-bold" : isDisabled(day) ? "text-[#ccc] cursor-default bg-transparent" : "bg-transparent text-[#333] hover:bg-orange-100"}`}
              onClick={() => selectDay(day)}
              disabled={isDisabled(day)}
              aria-pressed={isSelected(day)}
            >
              {day}
            </button>
          )
        )}
      </div>
      {parsed && (
        <div className="text-center text-[0.82rem] text-[#666] px-2 pb-2 pt-1 border-t border-[#f0f0f0]">
          Selected: {MONTHS[parsed.getMonth()]} {parsed.getDate()}, {parsed.getFullYear()}
        </div>
      )}
    </div>
  );
}

const labelCls = "flex flex-col gap-[0.35rem] text-[0.9rem] font-semibold text-[#444]";
const inputCls = "px-[0.85rem] py-[0.6rem] border border-[#ddd] rounded-lg text-base outline-none transition-all focus:border-[#e68672] focus:shadow-[0_0_0_3px_rgba(230,134,114,0.2)]";
const selectCls = `custom-select ${inputCls} bg-white cursor-pointer`;
const errorCls = "bg-[#fff0f0] border border-[#f5c6c6] text-[#c0392b] rounded-lg px-4 py-3 text-[0.9rem]";
const successCls = "bg-[#f0fdf4] border border-[#bbf7d0] text-[#16a34a] rounded-lg px-4 py-3 text-[0.9rem]";
const submitBtnCls = "py-3 bg-[#e68672] text-white border-none rounded-lg text-base font-bold cursor-pointer transition-all hover:bg-[#d4705e] active:scale-[0.98] disabled:opacity-60 disabled:cursor-not-allowed";

//Modal dialog for quickly adding a new pet without leaving the appointments page
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="fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4" onClick={onClose}>
      <div className="bg-white rounded-2xl shadow-xl p-8 w-full max-w-[480px] flex flex-col gap-4" onClick={(e) => e.stopPropagation()}>
        <h3 className="text-[1.1rem] font-bold text-[#333] m-0">Add a New Pet</h3>
        {petError && <div className={errorCls}>{petError}</div>}
        <form className="flex flex-col gap-4" onSubmit={handleSubmit}>
          <label className={labelCls}>
            Name
            <input className={inputCls} type="text" value={petName} onChange={(e) => setPetName(e.target.value)} required maxLength={50} />
          </label>
          <label className={labelCls}>
            Species
            <select className={selectCls} value={species} onChange={(e) => { setSpecies(e.target.value); setBreed(""); }} required>
              <option value="">Select a species...</option>
              {Object.keys(SPECIES_BREEDS).map((s) => (
                <option key={s} value={s}>{s}</option>
              ))}
            </select>
          </label>
          <label className={labelCls}>
            Breed
            <select className={`${selectCls} disabled:bg-[#f5f5f5] disabled:text-[#aaa] disabled:cursor-not-allowed`} value={breed} onChange={(e) => setBreed(e.target.value)} required disabled={!species}>
              <option value="">{species ? "Select a breed..." : "Select a species first"}</option>
              {(SPECIES_BREEDS[species] || []).map((b) => (
                <option key={b} value={b}>{b}</option>
              ))}
            </select>
          </label>
          <div className="flex gap-3">
            <button type="submit" className={submitBtnCls} disabled={submitting}>
              {submitting ? "Saving..." : "Add Pet"}
            </button>
            <button type="button" className="px-4 py-2 border border-[#ddd] rounded-lg bg-white text-[#555] text-[0.9rem] cursor-pointer hover:border-[#aaa] transition-colors" onClick={onClose}>
              Cancel
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

//Appointments page - book a service or adoption, and view past and active appointments
function AppointmentsPage() {
  const { user, token, loading: authLoading } = useAuth();
  const router = useRouter();
  const searchParams = useSearchParams();
  const preselectedPetId = searchParams.get("petId");

  const adoptionMode   = searchParams.get("adoptionMode") === "true";
  const adoptionPetId  = searchParams.get("petId");
  const adoptionPetName    = searchParams.get("petName") || "";
  const adoptionPetSpecies = searchParams.get("petSpecies") || "";
  const adoptionPetBreed   = searchParams.get("petBreed") || "";
  const adoptionStoreId    = searchParams.get("storeId") || "";
  const adoptionStoreName  = searchParams.get("storeName") || "";

  const didPreselectRef = useRef(false);
  const errorRef = useRef(null);
  const historyRef = useRef(null);

  const [adoptionVerified, setAdoptionVerified]       = useState(!adoptionMode);
  const [adoptionVerifyError, setAdoptionVerifyError] = useState(null);
  const [adoptionVerifyLoading, setAdoptionVerifyLoading] = useState(adoptionMode);

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

  useEffect(() => {
    if (error && errorRef.current) {
      errorRef.current.scrollIntoView({ behavior: "smooth", block: "center" });
    }
  }, [error]);

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

  const [adoptions, setAdoptions] = useState([]);
  const [loadingAdoptions, setLoadingAdoptions] = useState(false);

  const [showAddPetModal, setShowAddPetModal] = useState(false);
  const [cancellingId, setCancellingId] = useState(null);
  const [apptSearch, setApptSearch] = useState("");
  const [adoptionSearch, setAdoptionSearch] = useState("");
  const [showPastAppts, setShowPastAppts] = useState(false);
  const [showPastAdoptions, setShowPastAdoptions] = useState(false);

  //Pagination state for each of the four history lists
  const HISTORY_PAGE_SIZE = 5;
  const [apptPage, setApptPage] = useState(0);
  const [pastApptPage, setPastApptPage] = useState(0);
  const [adoptionPage, setAdoptionPage] = useState(0);
  const [pastAdoptionPage, setPastAdoptionPage] = useState(0);

  //Reset appointment page to 0 when the search text changes
  useEffect(() => { setApptPage(0); }, [apptSearch]);
  //Reset adoption page to 0 when the search text changes
  useEffect(() => { setAdoptionPage(0); }, [adoptionSearch]);

  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]);

  useEffect(() => {
    if (!adoptionMode || !adoptionPetId) return;
    setAdoptionVerifyLoading(true);
    fetch(`${API_BASE}/api/v1/pets/${adoptionPetId}`)
      .then((r) => {
        if (!r.ok) throw new Error("Pet not found. This link may be invalid.");
        return r.json();
      })
      .then((pet) => {
        if (pet.petStatus?.toLowerCase() !== "available") {
          throw new Error(`${pet.petName || "This pet"} is no longer available for adoption (status: ${pet.petStatus}).`);
        }
        if (adoptionStoreId && String(pet.storeId) !== String(adoptionStoreId)) {
          throw new Error("Store mismatch: this pet is not located at the specified store.");
        }
        setAdoptionVerified(true);
      })
      .catch((err) => setAdoptionVerifyError(err.message))
      .finally(() => setAdoptionVerifyLoading(false));
  }, [adoptionMode, adoptionPetId, adoptionStoreId]);

  //Loads the user's registered pets for the pet selector
  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(() => setError("Failed to load stores."));

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

    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 (adoptionMode) {
      if (adoptionStoreId && services.length > 0) {
        setStoreId(adoptionStoreId);
        const adoptionSvc =
          services.find((s) => s.serviceName.toLowerCase().includes("adopt")) ||
          services[0];
        if (adoptionSvc) {
          setServiceId(String(adoptionSvc.serviceId));
          didPreselectRef.current = true;
        }
      }
      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;
  }, [adoptionMode, adoptionStoreId, preselectedPetId, services, allPets]);

  //Fetches the user's booked appointments
  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]);

  //Fetches the user's adoption requests
  const loadAdoptions = useCallback(() => {
    if (!token) return;
    setLoadingAdoptions(true);
    fetch(`${API_BASE}/api/v1/adoptions?size=50&sort=adoptionDate,desc`, {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then((r) => r.json())
      .then((data) => setAdoptions(data.content ?? []))
      .catch(() => {})
      .finally(() => setLoadingAdoptions(false));
  }, [token]);

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

  //Cancels an appointment after asking the user to confirm
  async function handleCancelAppointment(appointmentId) {
    if (!confirm("Cancel this appointment?")) return;
    setCancellingId(appointmentId);
    try {
      const res = await fetch(`${API_BASE}/api/v1/appointments/${appointmentId}/cancel`, {
        method: "PATCH",
        headers: { Authorization: `Bearer ${token}` },
      });
      if (!res.ok) {
        const data = await res.json().catch(() => null);
        throw new Error(data?.message || `Failed to cancel appointment (${res.status})`);
      }
      loadAppointments();
    } catch (err) {
      alert(err.message);
    } finally {
      setCancellingId(null);
    }
  }

  //Cancels an adoption request after asking the user to confirm
  async function handleCancelAdoption(adoptionId) {
    if (!confirm("Cancel this adoption request?")) return;
    setCancellingId(adoptionId);
    try {
      const res = await fetch(`${API_BASE}/api/v1/adoptions/${adoptionId}/cancel`, {
        method: "PATCH",
        headers: { Authorization: `Bearer ${token}` },
      });
      if (!res.ok) {
        const data = await res.json().catch(() => null);
        throw new Error(data?.message || `Failed to cancel adoption (${res.status})`);
      }
      loadAdoptions();
    } catch (err) {
      alert(err.message);
    } finally {
      setCancellingId(null);
    }
  }

  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 eligiblePets = customerPets.filter(
    (p) => p.petStatus?.toLowerCase() === "owned" || p.petStatus?.toLowerCase() === "adopted"
  );

  const selectedService = services.find((s) => s.serviceId === Number(serviceId));
  const selectedPet = !adoptionMode
    ? (eligiblePets.find((p) => p.customerPetId === selectedPetIds[0]) || null)
    : null;
  const availableServices = getAvailableServices(services, selectedPet?.species);

  function handleServiceChange(newServiceId) {
    setServiceId(newServiceId);
  }

  //Selects a pet and clears the chosen service if it is not valid for that species
  function handlePetSelect(petId) {
    const newPet = eligiblePets.find((p) => p.customerPetId === petId);
    setSelectedPetIds([petId]);
    if (serviceId && newPet) {
      const newAvailable = getAvailableServices(services, newPet.species);
      if (!newAvailable.some((s) => String(s.serviceId) === String(serviceId))) {
        setServiceId("");
        setAppointmentTime("");
        setAvailableSlots([]);
      }
    }
  }

  //Converts a 24-hour time string to 12-hour AM/PM format
  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 = adoptionMode
    ? Boolean(employeeId && appointmentDate && adoptionVerified)
    : storeId && serviceId && appointmentDate && appointmentTime && selectedPetIds.length > 0;

  //Submits either a new appointment or an adoption request depending on the current mode
  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 (!adoptionMode && selectedPetIds.length === 0) {
      setError("Please select a pet for your appointment.");
      return;
    }

    if (!adoptionMode && selectedPet && selectedPet.petStatus?.toLowerCase() !== "owned" && selectedPet.petStatus?.toLowerCase() !== "adopted") {
      setError("The selected pet is no longer eligible for appointments. Please refresh the page.");
      return;
    }

    if (!adoptionMode && selectedPet && serviceId) {
      const chosenService = services.find((s) => String(s.serviceId) === String(serviceId));
      if (chosenService && getAvailableServices([chosenService], selectedPet.species).length === 0) {
        setError(`"${chosenService.serviceName}" is not available for ${selectedPet.species}s. Please select a valid service.`);
        return;
      }
    }

    setSubmitting(true);

    try {
      if (adoptionMode) {
        const body = {
          petId: Number(adoptionPetId),
          employeeId: employeeId ? Number(employeeId) : undefined,
          sourceStoreId: adoptionStoreId ? Number(adoptionStoreId) : undefined,
          adoptionDate: appointmentDate,
        };

        const res = await fetch(`${API_BASE}/api/v1/adoptions/request`, {
          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(`Adoption request submitted! ${adoptionPetName} is now marked as Pending. We'll be in touch soon.`);
        setEmployeeId("");
        loadAdoptions();
        setTimeout(() => historyRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }), 300);
        return;
      }

      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();
      setTimeout(() => historyRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }), 300);
    }

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

    finally {
      setSubmitting(false);
    }
  }

  if (authLoading) {
    return (
      <main className="min-h-screen">
        <p className="text-center text-[#666] py-12">Loading...</p>
      </main>
    );
  }

  if (!user) return null;

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

      <section className="text-center py-16 px-8 bg-gradient-to-b from-[#f9f9f9] to-white">
        <h1 className="text-5xl font-bold text-[#333] mb-4 tracking-tight max-[768px]:text-3xl max-[480px]:text-[1.6rem]">
          {adoptionMode ? "Schedule an Adoption" : "Schedule an Appointment"}
        </h1>
        <p className="text-2xl font-light text-[#666] mb-8 max-[768px]:text-[1.2rem]">
          {adoptionMode ? "Schedule a pet adoption visit" : "Book a service for your pet."}
        </p>
        <div className="w-[100px] h-1 bg-[#e68672] mx-auto mt-8 rounded-sm"></div>
      </section>

      <section className="max-w-[1200px] mx-auto px-8 pb-16 flex gap-8 items-start max-[900px]:flex-col">
        {canBookAppointments ? (
          <form className="bg-white rounded-2xl shadow-[0_4px_16px_rgba(0,0,0,0.08)] p-8 flex-1 flex flex-col gap-4 max-[900px]:w-full" onSubmit={handleSubmit}>
            <h2 className="text-xl font-bold text-[#333] m-0">{adoptionMode ? "New Adoption" : "New Appointment"}</h2>

            {error && <div className={errorCls} ref={errorRef}>{error}</div>}

            {adoptionMode && adoptionVerifyLoading && (
              <p className="text-[#666] text-center py-2">Verifying pet details…</p>
            )}
            {adoptionMode && adoptionVerifyError && (
              <div className={errorCls}>{adoptionVerifyError}</div>
            )}

            {(!adoptionMode || adoptionVerified) && (<>

            {adoptionMode && (
              <label className={labelCls}>
                Pet
                <div className="px-[0.85rem] py-[0.6rem] border border-[#ddd] rounded-lg bg-[#f5f5f5] text-[#555]">
                  {[adoptionPetName, adoptionPetSpecies, adoptionPetBreed].filter(Boolean).join(" · ")}
                </div>
              </label>
            )}

            {!adoptionMode && (
              <div className={labelCls}>
                <span>Select Your Pet</span>
                {eligiblePets.length === 0 ? (
                  <p className="text-[#888] text-[0.9rem] m-0">
                    You have no adopted pets available.{" "}
                    <Link href="/profile" className="text-[#e68672] hover:underline">Add a pet on your profile page.</Link>
                  </p>
                ) : (
                  <div className="flex flex-wrap gap-2">
                    {eligiblePets.map((p) => (
                      <label
                        key={p.customerPetId}
                        className={`flex items-center gap-2 cursor-pointer px-3 py-2 rounded-full border-2 text-[0.85rem] font-semibold transition-all
                          ${selectedPetIds.includes(p.customerPetId)
                            ? "border-[#e68672] bg-[#fff4f2] text-[#e68672]"
                            : "border-[#ddd] bg-white text-[#333] hover:border-[#e68672]"}`}
                      >
                        <input
                          type="radio"
                          name="customerPet"
                          checked={selectedPetIds.includes(p.customerPetId)}
                          onChange={() => handlePetSelect(p.customerPetId)}
                          className="hidden"
                        />
                        {p.petName}
                        <span className="text-[#888] font-normal">({p.species})</span>
                      </label>
                    ))}
                  </div>
                )}
              </div>
            )}

            {(adoptionMode || selectedPetIds.length > 0) && (<>

            <label className={labelCls}>
              Store Location
              {adoptionMode ? (
                <div className="px-[0.85rem] py-[0.6rem] border border-[#ddd] rounded-lg bg-[#f5f5f5] text-[#555]">{adoptionStoreName || "Pet's store"}</div>
              ) : (
                <select className={selectCls} 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>

            {!adoptionMode && (
              <label className={labelCls}>
                Service
                {availableServices.length === 0 ? (
                  <p className="text-[#888] text-[0.9rem] m-0">
                    No services are available for {selectedPet?.species || "this pet"}.
                  </p>
                ) : (
                  <select className={selectCls} value={serviceId} onChange={(e) => handleServiceChange(e.target.value)} required>
                    <option value="">Select a service...</option>
                    {availableServices.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={labelCls}>
                Employee
                <select className={selectCls} value={employeeId} onChange={(e) => setEmployeeId(e.target.value)}>
                  {employees.map((employee) => (
                    <option key={employee.id} value={employee.id}>{employee.label}</option>
                  ))}
                </select>
              </label>
            )}

            {!adoptionMode && selectedService && (
              <div className="bg-[#f9f9f9] rounded-lg px-4 py-3 text-[0.85rem] text-[#555] border border-[#eee]">
                <p className="m-0">{selectedService.serviceDesc}</p>
              </div>
            )}

            <div className={labelCls}>
              Date
              <DatePicker
                value={appointmentDate}
                minDate={getMinDate()}
                onChange={setAppointmentDate}
              />
            </div>

            {!adoptionMode && storeId && serviceId && appointmentDate && (
              <div className={labelCls}>
                <span>Available Time Slots</span>
                {loadingSlots ? (
                  <p className="text-[#888] text-[0.9rem] m-0">Checking availability...</p>
                ) : availableSlots.length === 0 ? (
                  <p className="text-[#888] text-[0.9rem] m-0">No available slots for this date. Please try another date.</p>
                ) : (
                  <div className="flex flex-wrap gap-2">
                    {availableSlots.map((slot) => (
                      <button
                        key={slot}
                        type="button"
                        className={`px-3 py-2 rounded-lg border-2 text-[0.85rem] cursor-pointer transition-all
                          ${appointmentTime === slot
                            ? "border-[#e68672] bg-[#e68672] text-white"
                            : "border-[#ddd] bg-white text-[#333] hover:border-[#e68672]"}`}
                        onClick={() => setAppointmentTime(slot)}
                      >
                        {formatTime(slot)}
                      </button>
                    ))}
                  </div>
                )}
              </div>
            )}

            </>)}

            <button type="submit" className={submitBtnCls} disabled={!formValid || submitting}>
              {submitting ? "Booking..." : adoptionMode ? "Schedule Adoption" : "Book Appointment"}
            </button>

            {success && <div className={successCls}>{success}</div>}

            </>)}
          </form>
        ) : null}

        {/* History panel */}
        <div className="bg-white rounded-2xl shadow-[0_4px_16px_rgba(0,0,0,0.08)] p-8 flex-1 flex flex-col gap-4 max-[900px]:w-full" ref={historyRef}>
          <h2 className="text-xl font-bold text-[#333] m-0">{canBookAppointments ? "Your Appointments" : "Appointments"}</h2>
          {loadingAppointments ? (
            <p className="text-[#666] text-center py-4">Loading appointments...</p>
          ) : (() => {
            const activeAppts = appointments.filter((a) => a.appointmentStatus?.toLowerCase() === "booked");
            const pastAppts = appointments.filter((a) => a.appointmentStatus?.toLowerCase() !== "booked");
            const q = apptSearch.toLowerCase();
            const filteredActive = activeAppts.filter((a) =>
              !q || [a.serviceName, a.storeName, a.petName].some((v) => v?.toLowerCase().includes(q))
            );
            //Paginate active appointments
            const apptTotalPages = Math.ceil(filteredActive.length / HISTORY_PAGE_SIZE);
            const apptSlice = filteredActive.slice(apptPage * HISTORY_PAGE_SIZE, (apptPage + 1) * HISTORY_PAGE_SIZE);
            //Paginate past appointments
            const pastApptTotalPages = Math.ceil(pastAppts.length / HISTORY_PAGE_SIZE);
            const pastApptSlice = pastAppts.slice(pastApptPage * HISTORY_PAGE_SIZE, (pastApptPage + 1) * HISTORY_PAGE_SIZE);
            return (
              <>
                <input
                  className="px-4 py-2 border border-[#ddd] rounded-lg text-[0.9rem] outline-none w-full focus:border-[#e68672] transition-colors"
                  type="text"
                  placeholder="Search appointments…"
                  value={apptSearch}
                  onChange={(e) => setApptSearch(e.target.value)}
                />
                {filteredActive.length === 0 ? (
                  <p className="text-[#888] text-[0.9rem] py-4 m-0">{activeAppts.length === 0 ? "No active appointments." : "No results."}</p>
                ) : (
                  <>
                    <div className="flex flex-col gap-3">
                      {apptSlice.map((a) => (
                        <div key={a.appointmentId} className="bg-[#f9f9f9] rounded-xl p-4 border border-[#eee]">
                          <div className="flex items-center justify-between mb-2">
                            <span className="font-semibold text-[#333]">{a.serviceName}</span>
                            <span className={`text-xs font-semibold rounded-full px-2.5 py-1 appt-card-status--${a.appointmentStatus?.toLowerCase()}`}>
                              {a.appointmentStatus}
                            </span>
                          </div>
                          <div className="flex gap-4 text-[0.85rem] text-[#666] mb-2 flex-wrap">
                            <span>{a.storeName}</span>
                            <span>{a.appointmentDate} at {formatTime(a.appointmentTime)}</span>
                          </div>
                          {a.petName && (
                            <div className="text-[0.85rem] text-[#888] mb-2">Pet: {a.petName}</div>
                          )}
                          <div className="flex gap-2">
                            <button
                              type="button"
                              className="px-3 py-1.5 rounded-lg border border-[#f5c6c6] bg-[#fff0f0] text-[#c0392b] text-[0.85rem] cursor-pointer hover:bg-[#ffd7d7] transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
                              disabled={cancellingId === a.appointmentId}
                              onClick={() => handleCancelAppointment(a.appointmentId)}
                            >
                              {cancellingId === a.appointmentId ? "Cancelling..." : "Cancel"}
                            </button>
                          </div>
                        </div>
                      ))}
                    </div>
                    {apptTotalPages > 1 && (
                      <div className="flex items-center justify-between gap-2 mt-1 flex-wrap">
                        <button
                          className="px-3 py-1.5 rounded-lg border border-[#ddd] bg-white text-[0.85rem] cursor-pointer hover:border-[#e68672] transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
                          onClick={() => setApptPage((p) => p - 1)}
                          disabled={apptPage === 0}
                          type="button"
                        >
                          &larr; Prev
                        </button>
                        <span className="text-[0.82rem] text-[#888]">Page {apptPage + 1} of {apptTotalPages}</span>
                        <button
                          className="px-3 py-1.5 rounded-lg border border-[#ddd] bg-white text-[0.85rem] cursor-pointer hover:border-[#e68672] transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
                          onClick={() => setApptPage((p) => p + 1)}
                          disabled={apptPage >= apptTotalPages - 1}
                          type="button"
                        >
                          Next &rarr;
                        </button>
                      </div>
                    )}
                  </>
                )}
                {pastAppts.length > 0 && (
                  <div className="mt-2">
                    <button className="text-[0.85rem] text-[#e68672] cursor-pointer bg-transparent border-none font-semibold hover:underline" onClick={() => { setShowPastAppts((v) => !v); setPastApptPage(0); }}>
                      {showPastAppts ? "Hide" : "Show"} past appointments ({pastAppts.length})
                    </button>
                    {showPastAppts && (
                      <>
                        <div className="flex flex-col gap-3 mt-3 opacity-75">
                          {pastApptSlice.map((a) => (
                            <div key={a.appointmentId} className="bg-[#f9f9f9] rounded-xl p-4 border border-[#eee]">
                              <div className="flex items-center justify-between mb-2">
                                <span className="font-semibold text-[#333]">{a.serviceName}</span>
                                <span className={`text-xs font-semibold rounded-full px-2.5 py-1 appt-card-status--${a.appointmentStatus?.toLowerCase()}`}>
                                  {a.appointmentStatus}
                                </span>
                              </div>
                              <div className="flex gap-4 text-[0.85rem] text-[#666] flex-wrap">
                                <span>{a.storeName}</span>
                                <span>{a.appointmentDate} at {formatTime(a.appointmentTime)}</span>
                              </div>
                              {a.petName && (
                                <div className="text-[0.85rem] text-[#888] mt-1">Pet: {a.petName}</div>
                              )}
                            </div>
                          ))}
                        </div>
                        {pastApptTotalPages > 1 && (
                          <div className="flex items-center justify-between gap-2 mt-2 flex-wrap">
                            <button
                              className="px-3 py-1.5 rounded-lg border border-[#ddd] bg-white text-[0.85rem] cursor-pointer hover:border-[#e68672] transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
                              onClick={() => setPastApptPage((p) => p - 1)}
                              disabled={pastApptPage === 0}
                              type="button"
                            >
                              &larr; Prev
                            </button>
                            <span className="text-[0.82rem] text-[#888]">Page {pastApptPage + 1} of {pastApptTotalPages}</span>
                            <button
                              className="px-3 py-1.5 rounded-lg border border-[#ddd] bg-white text-[0.85rem] cursor-pointer hover:border-[#e68672] transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
                              onClick={() => setPastApptPage((p) => p + 1)}
                              disabled={pastApptPage >= pastApptTotalPages - 1}
                              type="button"
                            >
                              Next &rarr;
                            </button>
                          </div>
                        )}
                      </>
                    )}
                  </div>
                )}
              </>
            );
          })()}

          <h2 className="text-xl font-bold text-[#333] m-0 mt-4">{canBookAppointments ? "Your Adoptions" : "Adoptions"}</h2>
          {loadingAdoptions ? (
            <p className="text-[#666] text-center py-4">Loading adoptions...</p>
          ) : (() => {
            const activeAdoptions = adoptions.filter((a) => a.adoptionStatus?.toLowerCase() === "pending");
            const pastAdoptions = adoptions.filter((a) => a.adoptionStatus?.toLowerCase() !== "pending");
            const q = adoptionSearch.toLowerCase();
            const filteredActive = activeAdoptions.filter((a) =>
              !q || [a.petName, a.sourceStoreName].some((v) => v?.toLowerCase().includes(q))
            );
            //Paginate active adoptions
            const adoptionTotalPages = Math.ceil(filteredActive.length / HISTORY_PAGE_SIZE);
            const adoptionSlice = filteredActive.slice(adoptionPage * HISTORY_PAGE_SIZE, (adoptionPage + 1) * HISTORY_PAGE_SIZE);
            //Paginate past adoptions
            const pastAdoptionTotalPages = Math.ceil(pastAdoptions.length / HISTORY_PAGE_SIZE);
            const pastAdoptionSlice = pastAdoptions.slice(pastAdoptionPage * HISTORY_PAGE_SIZE, (pastAdoptionPage + 1) * HISTORY_PAGE_SIZE);
            return (
              <>
                <input
                  className="px-4 py-2 border border-[#ddd] rounded-lg text-[0.9rem] outline-none w-full focus:border-[#e68672] transition-colors"
                  type="text"
                  placeholder="Search adoptions…"
                  value={adoptionSearch}
                  onChange={(e) => setAdoptionSearch(e.target.value)}
                />
                {filteredActive.length === 0 ? (
                  <p className="text-[#888] text-[0.9rem] py-4 m-0">{activeAdoptions.length === 0 ? "No active adoption requests." : "No results."}</p>
                ) : (
                  <>
                    <div className="flex flex-col gap-3">
                      {adoptionSlice.map((a) => (
                        <div key={a.adoptionId} className="bg-[#f9f9f9] rounded-xl p-4 border border-[#eee]">
                          <div className="flex items-center justify-between mb-2">
                            <span className="font-semibold text-[#333]">{a.petName}</span>
                            <span className={`text-xs font-semibold rounded-full px-2.5 py-1 appt-card-status--${a.adoptionStatus?.toLowerCase()}`}>
                              {a.adoptionStatus}
                            </span>
                          </div>
                          <div className="flex gap-4 text-[0.85rem] text-[#666] mb-2 flex-wrap">
                            <span>{a.sourceStoreName}</span>
                            <span>{a.adoptionDate}</span>
                          </div>
                          <div className="flex gap-2">
                            <button
                              type="button"
                              className="px-3 py-1.5 rounded-lg border border-[#f5c6c6] bg-[#fff0f0] text-[#c0392b] text-[0.85rem] cursor-pointer hover:bg-[#ffd7d7] transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
                              disabled={cancellingId === a.adoptionId}
                              onClick={() => handleCancelAdoption(a.adoptionId)}
                            >
                              {cancellingId === a.adoptionId ? "Cancelling..." : "Cancel"}
                            </button>
                          </div>
                        </div>
                      ))}
                    </div>
                    {adoptionTotalPages > 1 && (
                      <div className="flex items-center justify-between gap-2 mt-1 flex-wrap">
                        <button
                          className="px-3 py-1.5 rounded-lg border border-[#ddd] bg-white text-[0.85rem] cursor-pointer hover:border-[#e68672] transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
                          onClick={() => setAdoptionPage((p) => p - 1)}
                          disabled={adoptionPage === 0}
                          type="button"
                        >
                          &larr; Prev
                        </button>
                        <span className="text-[0.82rem] text-[#888]">Page {adoptionPage + 1} of {adoptionTotalPages}</span>
                        <button
                          className="px-3 py-1.5 rounded-lg border border-[#ddd] bg-white text-[0.85rem] cursor-pointer hover:border-[#e68672] transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
                          onClick={() => setAdoptionPage((p) => p + 1)}
                          disabled={adoptionPage >= adoptionTotalPages - 1}
                          type="button"
                        >
                          Next &rarr;
                        </button>
                      </div>
                    )}
                  </>
                )}
                {pastAdoptions.length > 0 && (
                  <div className="mt-2">
                    <button className="text-[0.85rem] text-[#e68672] cursor-pointer bg-transparent border-none font-semibold hover:underline" onClick={() => { setShowPastAdoptions((v) => !v); setPastAdoptionPage(0); }}>
                      {showPastAdoptions ? "Hide" : "Show"} past adoptions ({pastAdoptions.length})
                    </button>
                    {showPastAdoptions && (
                      <>
                        <div className="flex flex-col gap-3 mt-3 opacity-75">
                          {pastAdoptionSlice.map((a) => (
                            <div key={a.adoptionId} className="bg-[#f9f9f9] rounded-xl p-4 border border-[#eee]">
                              <div className="flex items-center justify-between mb-2">
                                <span className="font-semibold text-[#333]">{a.petName}</span>
                                <span className={`text-xs font-semibold rounded-full px-2.5 py-1 appt-card-status--${a.adoptionStatus?.toLowerCase()}`}>
                                  {a.adoptionStatus}
                                </span>
                              </div>
                              <div className="flex gap-4 text-[0.85rem] text-[#666] flex-wrap">
                                <span>{a.sourceStoreName}</span>
                                <span>{a.adoptionDate}</span>
                              </div>
                            </div>
                          ))}
                        </div>
                        {pastAdoptionTotalPages > 1 && (
                          <div className="flex items-center justify-between gap-2 mt-2 flex-wrap">
                            <button
                              className="px-3 py-1.5 rounded-lg border border-[#ddd] bg-white text-[0.85rem] cursor-pointer hover:border-[#e68672] transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
                              onClick={() => setPastAdoptionPage((p) => p - 1)}
                              disabled={pastAdoptionPage === 0}
                              type="button"
                            >
                              &larr; Prev
                            </button>
                            <span className="text-[0.82rem] text-[#888]">Page {pastAdoptionPage + 1} of {pastAdoptionTotalPages}</span>
                            <button
                              className="px-3 py-1.5 rounded-lg border border-[#ddd] bg-white text-[0.85rem] cursor-pointer hover:border-[#e68672] transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
                              onClick={() => setPastAdoptionPage((p) => p + 1)}
                              disabled={pastAdoptionPage >= pastAdoptionTotalPages - 1}
                              type="button"
                            >
                              Next &rarr;
                            </button>
                          </div>
                        )}
                      </>
                    )}
                  </div>
                )}
              </>
            );
          })()}
        </div>
      </section>
    </main>
  );
}

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