import type { GetServerSideProps } from "next";
import Head from "next/head";
import { useEffect, useMemo, useState } from "react";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "~/components/ui/select";
import { LoadingPage } from "~/components/loading";
import { Button } from "~/components/ui/button";
import { Label } from "~/components/ui/label";
import { cn } from "~/lib/utils";
import {
  ChevronDown,
  ChevronRight,
  ChevronsRight,
  ChevronUp,
  Filter,
  FilterX,
  MapIcon,
  RotateCcwIcon,
  Table,
} from "lucide-react";
import { useTranslation } from "~/providers/I18nProvider";
import { AnnunciGrid } from "~/components/annunci_grid";
import { Status500 } from "~/components/status-page";
import { CodiceBox } from "~/components/codiceRicerca";
import { generateSSGHelper } from "~/server/utils/ssgHelper";
import { MapSection } from "~/components/annunci_map";
import { api } from "~/utils/api";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import { Badge } from "~/components/ui/badge";
import {
  RicercaProvider,
  useRicerca,
  type AnnunciOptions,
  type SortTypes,
} from "~/providers/RicercaProvider";
import { AccordionComp } from "~/components/accordionComp";
import { CTA_TipologiaModal } from "~/components/annunci_tutorial";
import { keepPreviousData } from "@tanstack/react-query";

type AnnunciPageProps = {
  options: AnnunciOptions;
};

const Annunci = ({ options }: AnnunciPageProps) => {
  const { t } = useTranslation();

  return (
    <RicercaProvider options={options}>
      <Head>
        <title>{t.heads.annunci_titolo}</title>
        <meta name="description" content={t.heads.annunci_description} />
      </Head>

      <main className="w-full px-2 pb-6 md:px-8">
        <header className="mx-auto max-w-6xl py-5">
          <div className="bg-primary/10 text-primary inline-block rounded-lg px-3 py-1 text-sm">
            {t.annunci.titolo}
          </div>
        </header>

        <Ricerca />
        <AccordionComp
          texts={t.annunci.accordion_minifaq}
          className="max-w-6xl px-4 py-4 md:py-8"
        />
      </main>
    </RicercaProvider>
  );
};

export default Annunci;

export const getServerSideProps = (async () => {
  const helper = generateSSGHelper();
  const options = await helper.annunci.getAnnunciOptions.fetch();
  return {
    props: {
      options,
    },
  };
}) satisfies GetServerSideProps<AnnunciPageProps>;

const Ricerca = () => {
  const { map, page } = useRicerca();
  useEffect(() => {
    window.scrollTo({ top: 0, behavior: "smooth" });
  }, [page]);

  return (
    <>
      <RicercaFilters />
      <br />
      {map ? <MapSection /> : <AnnunciList />}
    </>
  );
};

const RicercaFilters = () => {
  const { t } = useTranslation();
  const {
    map,
    setMap,
    tipo,
    setTipo,
    comune,
    setComune,
    consegna,
    setConsegna,
    sort,
    setSort,
    comuniOptions,
    tipologieOptions,
    consegnaOptions,
    ResetParams,
    nFiltri,
  } = useRicerca();
  const [open, setOpen] = useState(false);

  const mappedConsegnaOptions = useMemo(
    () => consegnaOptions.map((m) => t.preferenze.mesi[m]!).filter(Boolean),
    [consegnaOptions, t.preferenze.mesi],
  );

  return (
    <div className="mx-auto w-full max-w-6xl space-y-5">
      <div className="flex w-full flex-col-reverse gap-4 sm:flex-row sm:gap-2">
        <div className="flex w-full gap-2 sm:w-auto">
          <div className="flex w-full sm:w-auto">
            <DropdownMenu open={open} onOpenChange={setOpen}>
              <DropdownMenuTrigger asChild>
                <Button
                  variant="default"
                  className="group flex w-full flex-row gap-2 sm:w-auto"
                >
                  <Badge className="bg-secondary text-secondary-foreground w-fit rounded-md px-1.5 py-0.5 dark:group-hover:bg-transparent">
                    {nFiltri}
                  </Badge>
                  <Filter className="size-5" />{" "}
                  {nFiltri === 1
                    ? t.annunci.filtro_attivo
                    : t.annunci.filtri_attivi}
                  {open ? <ChevronUp /> : <ChevronDown />}
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent
                className="flex w-60 max-w-3xl flex-col gap-2 p-4"
                align="start"
              >
                <SelectFilter
                  label={t.annunci.fs_tipologia.titolo}
                  options={tipologieOptions}
                  value={tipo}
                  defaultValue={tipo}
                  onValueChange={async (value: string) => {
                    await setTipo(value);
                  }}
                  placeholder={t.seleziona_placeholder}
                  handleReset={async () => {
                    await setTipo("");
                  }}
                />
                <SelectFilter
                  label={t.annunci.comune}
                  options={comuniOptions}
                  value={comune}
                  defaultValue={comune}
                  onValueChange={async (value: string) => {
                    await setComune(value);
                  }}
                  placeholder={t.seleziona_placeholder}
                  handleReset={async () => {
                    await setComune(null);
                  }}
                />
                <SelectFilter
                  label={t.annunci.consegna}
                  options={mappedConsegnaOptions}
                  value={consegna ? t.preferenze.mesi[consegna] || "" : ""}
                  defaultValue={
                    consegna ? t.preferenze.mesi[consegna] || "" : ""
                  }
                  onValueChange={async (value: string) => {
                    if (value === "") {
                      await setConsegna(null);
                      return;
                    }
                    if (t.preferenze.mesi.includes(value)) {
                      await setConsegna(t.preferenze.mesi.indexOf(value));
                      return;
                    } else {
                      console.warn("Value not found in preferenze.mesi");
                      await setConsegna(null);
                    }
                  }}
                  placeholder={t.seleziona_placeholder}
                  handleReset={async () => {
                    await setConsegna(null);
                  }}
                />
                <SelectFilter
                  label={t.ordina_per}
                  options={["Recenti", "Prezzo", "Consegna", "Mq"]}
                  value={sort}
                  defaultValue={sort}
                  onValueChange={async (value: SortTypes) => {
                    await setSort(value);
                  }}
                  placeholder={t.seleziona_placeholder}
                  handleReset={async () => {
                    await setSort("");
                  }}
                />
                <Button
                  variant="destructive"
                  onClick={ResetParams}
                  className="flex flex-row gap-2"
                  disabled={nFiltri === 0}
                >
                  <FilterX className="size-5" /> {t.annunci.filtri_reset}
                </Button>
              </DropdownMenuContent>
            </DropdownMenu>
          </div>
          <Button
            variant="default"
            onClick={async () => {
              await setMap((v) => !v);
            }}
            className="flex w-fit flex-row gap-2"
          >
            {!map ? (
              <>
                <MapIcon className="size-5" />{" "}
                <span className="hidden sm:block">Mappa</span>
              </>
            ) : (
              <>
                <Table className="size-5" />
                <span className="hidden sm:block">Lista</span>
              </>
            )}
          </Button>
        </div>
        <div className="flex w-full items-center justify-between gap-2 sm:w-auto">
          <div className="relative z-20 flex w-full gap-1 sm:w-auto">
            <CodiceBox className="h-10 w-full" optionBoxClassName="top-11 " />
          </div>

          <CTA_TipologiaModal />
        </div>
      </div>
    </div>
  );
};

const AnnunciList = () => {
  const {
    tipo,
    comune,
    consegna,
    sort,
    map,
    page,
    setPage,
    isLoading: ricercaLoading,
  } = useRicerca();

  const { data, status, isPlaceholderData } =
    api.annunci.getWithCursor.useQuery(
      {
        page,
        pageSize: 6,
        tipologia: tipo || undefined,
        comune: comune || undefined,
        consegna: consegna || undefined,
        sort: sort || undefined,
      },
      {
        placeholderData: keepPreviousData,
        enabled: !map,
        staleTime: 5000,
      },
    );
  const utils = api.useUtils();
  useEffect(() => {
    const prefetchData = async () => {
      if (!isPlaceholderData && data?.hasMore) {
        await utils.annunci.getWithCursor.prefetch({
          page: page + 1,
          pageSize: 6,
          tipologia: tipo || undefined,
          comune: comune || undefined,
          consegna: consegna || undefined,
          sort: sort || undefined,
        });
      }
    };
    prefetchData().catch((err) => {
      console.error("Error prefetching next page:", err);
    });
  }, [data, isPlaceholderData, page]);

  if (ricercaLoading) return <LoadingPage />;
  if (status === "error") return <Status500 />;

  return (
    <>
      {status === "pending" ? (
        <LoadingPage />
      ) : (
        <AnnunciGrid pagedata={data.annunci} />
      )}
      <br />

      <div className="mx-auto grid max-w-sm grid-cols-5 items-center justify-between gap-2">
        <div className="flex items-center justify-center">
          <button
            aria-label="Reset Page"
            className={cn(
              "rounded-lg bg-red-500/80 px-4 py-2 text-white hover:bg-red-500 active:shadow-lg",
              page < 2 ? "invisible" : "visible",
            )}
            onClick={async () => {
              await setPage(0);
            }}
            disabled={page < 2}
          >
            <ChevronsRight className="rotate-180" height={30} />
          </button>
        </div>
        <div className="flex items-center justify-center">
          <button
            aria-label="Previous Page"
            className={cn(
              "rounded-lg bg-red-500/80 px-4 py-2 text-white hover:bg-red-500 active:shadow-lg",
              page < 1 ? "invisible" : "visible",
            )}
            onClick={async () => {
              await setPage((old) => (old ? Math.max(old - 1, 0) : 0));
            }}
            disabled={page === 0}
          >
            <ChevronRight height={30} className="rotate-180" />
          </button>
        </div>
        <div className="flex items-center justify-center">
          <span className="text-lg font-semibold text-neutral-500">
            {page + 1}
          </span>
        </div>
        <div className="flex items-center justify-center">
          <button
            aria-label="Next Page"
            className={cn(
              "rounded-lg bg-red-500/80 px-4 py-2 text-white hover:bg-red-500 active:shadow-lg",
              data?.hasMore ? "visible" : "invisible",
            )}
            onClick={async () => {
              await setPage((old) =>
                old ? (data?.hasMore ? old + 1 : old) : 1,
              );
            }}
            disabled={isPlaceholderData || !data?.hasMore}
          >
            <ChevronRight height={30} />
          </button>
        </div>
      </div>
    </>
  );
};

interface SelectFilterProps<T> {
  label: string;
  options: string[];
  defaultValue?: T;
  value: T | undefined;
  onValueChange: (value: T) => void;
  handleReset: () => void;
  placeholder: string;
}

export const SelectFilter = <T extends string>({
  label,
  options,
  defaultValue,
  value,
  onValueChange,
  placeholder,
  handleReset,
}: SelectFilterProps<T>) => {
  return (
    <div className="flex flex-col gap-2">
      <div className="flex h-4 flex-row gap-4 px-1">
        <Label
          className={cn(
            "text-muted-foreground font-semibold",
            value !== "" && "text-primary",
          )}
        >
          {label}
        </Label>
        {value !== "" && (
          <button type="button" onClick={handleReset}>
            <RotateCcwIcon className="size-4" />
          </button>
        )}
      </div>

      <Select
        defaultValue={defaultValue}
        value={value}
        onValueChange={onValueChange}
      >
        <SelectTrigger className="w-full">
          <SelectValue placeholder={placeholder} />
        </SelectTrigger>
        <SelectContent>
          {options.map((option) => (
            <SelectItem key={option} value={option} className="text-left">
              {option}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
    </div>
  );
};
