/* eslint-disable react-hooks/exhaustive-deps */
import { useQuery } from "@tanstack/react-query";
import RestartIcon from "./icons/RestartIcon";
import Button from "./ui/Button";
import MultiRangeSlider from "./ui/MultiRangeSlider";
import { api } from "../api/ky";
import { RefObject, useEffect, useState } from "react";
import { useSearchParams } from "react-router";
import { projects } from "../data/projects";
import { useDebounce } from "../hooks/useDebounce";
import clsx from "clsx";
import ProjectSelect from "./ProjectSelect";
import UnitTypesSelect from "./UnitTypesSelect";
import Select from "./ui/Select";
import { AnimatePresence, motion } from "motion/react";
import CloseIcon from "./icons/CloseIcon";
import Project from "../types/Project";

export interface Filters {
  unitTypes: string[];
  views: string[];
  area: [number, number];
  cost: [number, number];
  floor: [number, number];
}

function SearchFilters({
  inModal = false,
  setInModal,
  ref,
  cost,
  floor,
  area,
  setCost,
  setFloor,
  setArea,
}: {
  inModal?: boolean;
  setInModal: (inModal: boolean) => void;
  ref?: RefObject<HTMLDivElement | null>;
  cost: [number, number];
  floor: [number, number];
  area: [number, number];
  setCost: (cost: [number, number]) => void;
  setFloor: (floor: [number, number]) => void;
  setArea: (area: [number, number]) => void;
}) {
  const [project, setProject] = useState<string>();
  const [unitTypes, setUnitTypes] = useState<string[]>([]);
  const [view, setView] = useState<string>("Any view");

  const [searchParams, setSearchParams] = useSearchParams();

  const { data: filters } = useQuery({
    queryKey: ["filters", project],
    enabled: !!project,
    queryFn: () =>
      api
        .get(`units/filters?${project ? `project=${project}` : ""}`)
        .json<Filters>(),
  });

  useEffect(() => {
    const projectValue = searchParams.get("project") || projects[0].title;
    if (projectValue) setProject(projectValue);

    const viewValue = searchParams.get("view");
    if (viewValue) setView(viewValue);

    const unitTypesValue = searchParams.getAll("unitTypes");
    if (unitTypesValue) setUnitTypes(unitTypesValue);
  }, [searchParams]);

  function resetFilters() {
    window.location.href = "/search";
  }

  const [costInModal, setCostInModal] = useState<[number, number]>(cost);
  const [areaInModal, setAreaInModal] = useState<[number, number]>(area);
  const [floorInModal, setFloorInModal] = useState<[number, number]>(floor);

  useEffect(() => {
    if (filters) {
      setCostInModal(filters.cost);
      setAreaInModal(filters.area);
      setFloorInModal(filters.floor);
    }
  }, [filters, setAreaInModal, setCostInModal, setFloorInModal]);

  useEffect(() => {
    if (inModal) return;
    setCost(costInModal);
    setArea(areaInModal);
    setFloor(floorInModal);
  }, [setCost, costInModal, setArea, areaInModal, setFloor, floorInModal]);

  const debouncedCost = useDebounce(inModal ? costInModal : cost, 500);
  const debouncedArea = useDebounce(inModal ? areaInModal : area, 500);
  const debouncedFloor = useDebounce(inModal ? floorInModal : floor, 500);

  const { data: count } = useQuery({
    queryKey: [
      "units",
      "count",
      project,
      unitTypes,
      view,
      debouncedCost,
      debouncedArea,
      debouncedFloor,
    ],
    enabled:
      !!project &&
      debouncedCost[0] >= 0 &&
      debouncedCost[1] >= 0 &&
      debouncedArea[0] >= 0 &&
      debouncedArea[1] >= 0 &&
      debouncedFloor[0] >= 0 &&
      debouncedFloor[1] >= 0,
    queryFn: () =>
      api
        .get(
          `units/count?${project ? `project=${project}` : ""}${unitTypes
            .map((unitType) => `&unitTypes=${unitType}`)
            .join("")}${view !== "Any view" ? `&view=${view}` : ""}${
            debouncedCost
              ? `&cost=${Math.round(debouncedCost[0])},${Math.round(
                  debouncedCost[1]
                )}`
              : ""
          }${
            debouncedArea
              ? `&area=${Math.round(debouncedArea[0])},${Math.round(
                  debouncedArea[1]
                )}`
              : ""
          }${
            debouncedFloor
              ? `&floor=${Math.round(debouncedFloor[0])},${Math.round(
                  debouncedFloor[1]
                )}`
              : ""
          }`
        )
        .json<number>(),
  });

  function handleClose() {
    const projectValue = searchParams.get("project") || projects[0].title;
    if (projectValue) setProject(projectValue);

    const viewValue = searchParams.get("view");
    setView(viewValue || "Any view");

    const unitTypesValue = searchParams.getAll("unitTypes");
    if (unitTypesValue) setUnitTypes(unitTypesValue);
    setInModal(false);
  }

  function handleSelectProject(project: Project) {
    setProject(project.title);
    if (!inModal)
      setSearchParams((prev) => {
        prev.set("project", project.title);
        return prev;
      });
  }

  function handleSelectView(view: string) {
    setView(view);
    if (!inModal)
      setSearchParams((prev) => {
        if (view !== "Any view") prev.set("view", view);
        else prev.delete("view");
        return prev;
      });
  }

  function handleSelectUnitTypes(unitTypes: string[]) {
    setUnitTypes(unitTypes);
    if (!inModal)
      setSearchParams((prev) => {
        prev.delete("unitTypes");
        unitTypes.forEach((unitType) => prev.append("unitTypes", unitType));
        return prev;
      });
  }

  function applyFilters() {
    setInModal(false);
    setSearchParams((prev) => {
      prev.set("project", project!);
      if (view !== "Any view") prev.set("view", view);
      else prev.delete("view");
      prev.delete("unitTypes");
      unitTypes.forEach((unitType) => prev.append("unitTypes", unitType));
      return prev;
    });
    setCost(costInModal);
    setArea(areaInModal);
    setFloor(floorInModal);
    window.scroll({ top: 0, behavior: "smooth" });
  }

  return (
    <>
      {inModal && (
        <div
          className="fixed inset-0 2xl:top-[4.444vw] bg-[#0D1922]/40 cursor-pointer"
          onClick={handleClose}
        />
      )}
      <div
        ref={ref}
        className={clsx(
          "2xl:p-[2.222vw] md:max-2xl:p-6 p-4 bg-white 2xl:rounded-b-[1.667vw] rounded-b-3xl 2xl:space-y-[2.222vw] md:max-2xl:space-y-8 space-y-4",
          inModal &&
            "fixed 2xl:top-[calc(2.778vw+4.444vw)] 2xl:left-[2.778vw] 2xl:right-[2.778vw] 2xl:rounded-[1.667vw] rounded-3xl md:max-2xl:left-6 md:max-2xl:right-6 md:max-2xl:top-24"
        )}
      >
        {inModal && (
          <Button
            onlyIcon
            className="absolute right-[2.222vw] !bg-[#F3F3F2]"
            onClick={handleClose}
          >
            <div className="2xl:w-[1.389vw] 2xl:h-[1.389vw] w-5 h-5 text-[#0D1922]">
              <CloseIcon />
            </div>
          </Button>
        )}
        <div className="2xl:space-y-[1.111vw] space-y-4">
          <p className="2xl:text-[2.222vw] md:max-2xl:text-[32px] text-2xl font-semibold leading-[135%]">
            Search
          </p>
          {project && (
            <ProjectSelect
              projects={projects}
              onSelect={handleSelectProject}
              defaultProject={projects.find(({ title }) => title === project)!}
            />
          )}
        </div>
        <hr className="2xl:h-[0.069vw] h-px border-[#E2E2DC]" />
        {filters && (
          <>
            <div className="2xl:space-y-[0.556vw] space-y-2">
              <p className="text-s text-[#0D1922]/70">Apartment type</p>
              <UnitTypesSelect
                unitTypes={filters.unitTypes}
                onSelect={handleSelectUnitTypes}
                defaultSelected={unitTypes}
              />
            </div>
            <div className="grid 2xl:grid-cols-4 md:max-2xl:grid-cols-2 md:max-2xl:grid-rows-2 2xl:gap-[1.111vw] gap-4">
              <MultiRangeSlider
                min={filters?.cost[0]}
                max={filters?.cost[1]}
                currentMin={inModal ? costInModal[0] : cost[0]}
                currentMax={inModal ? costInModal[1] : cost[1]}
                offset={1}
                onChange={setCostInModal}
                label="Cost, AED"
              />
              <MultiRangeSlider
                min={filters?.floor[0]}
                max={filters?.floor[1]}
                currentMin={inModal ? floorInModal[0] : floor[0]}
                currentMax={inModal ? floorInModal[1] : floor[1]}
                offset={1}
                onChange={setFloorInModal}
                label="Floor"
              />
              <MultiRangeSlider
                min={filters?.area[0]}
                max={filters?.area[1]}
                currentMin={inModal ? areaInModal[0] : area[0]}
                currentMax={inModal ? areaInModal[1] : area[1]}
                offset={1}
                onChange={setAreaInModal}
                label="Total Area, Sqft"
              />
              <Select
                defaultOption={view}
                label="View"
                options={["Any view", ...filters.views]}
                onSelect={handleSelectView}
              />
            </div>
            <div className="flex items-center 2xl:gap-[1.111vw] md:max-2xl:gap-4">
              {inModal ? (
                <Button onClick={applyFilters}>
                  Show{" "}
                  <AnimatePresence mode="wait">
                    {count !== undefined && (
                      <motion.span
                        key={count}
                        initial={{ opacity: 0 }}
                        animate={{ opacity: 1 }}
                        exit={{ opacity: 0 }}
                      >
                        {count}
                      </motion.span>
                    )}
                  </AnimatePresence>{" "}
                  apartments
                </Button>
              ) : (
                <AnimatePresence mode="wait">
                  {count && (
                    <motion.p
                      key={count}
                      initial={{ opacity: 0 }}
                      animate={{ opacity: 1 }}
                      exit={{ opacity: 0 }}
                      className="text-[#00BED7] text-s"
                    >
                      {count} Apartments found
                    </motion.p>
                  )}
                </AnimatePresence>
              )}
              <Button variant="secondary" onClick={resetFilters}>
                <span className="2xl:w-[1.389vw] 2xl:h-[1.389vw] w-5 h-5 text-[#0D1922]/70">
                  <RestartIcon />
                </span>
                <p className="text-s">Reset filters</p>
              </Button>
            </div>
          </>
        )}
      </div>
    </>
  );
}

export default SearchFilters;
