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 { useRouter } from "next/router";
import toast from "react-hot-toast";
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";

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 router = useRouter();
  const {
    tipo,
    comune,
    consegna,
    sort,
    map,
    page,
    setPage,
    lastPageCount,
    setlastPageCount,
    isLoading: ricercaLoading,
  } = useRicerca();

  const { data, fetchNextPage, isLoading, hasNextPage } =
    api.annunci.getWithCursor.useInfiniteQuery(
      {
        limit: 6,
        tipologia: tipo || undefined,
        comune: comune || undefined,
        consegna: consegna || undefined,
        sort: sort || undefined,
      },
      {
        getNextPageParam: (lastPage) => lastPage.nextCursor,
        enabled: !map,
      },
    );

  const handlePageReset = () => {
    setPage(0);
  };

  const handleFetchNextPage = async () => {
    try {
      await fetchNextPage();
      setPage((prev) => prev + 1);
    } catch {
      await router.push("/annunci");
      toast.error("Errore caricamento annunci");
    }
  };

  const handleFetchPreviousPage = () => {
    setPage((prev) => prev - 1);
  };

  useEffect(() => {
    if (
      hasNextPage !== undefined &&
      hasNextPage === false &&
      lastPageCount === 100
    ) {
      setlastPageCount(page);
    }
  }, [hasNextPage, page, lastPageCount]);

  if (isLoading || ricercaLoading) return <LoadingPage />;
  if ((!isLoading && !data) || !data) return <Status500 />;

  return (
    <>
      <AnnunciGrid pagedata={data.pages[page]!.annunci} />
      <br />
      <PaginationHandler
        handleFetchNextPage={handleFetchNextPage}
        handleFetchPreviousPage={handleFetchPreviousPage}
        handlePageReset={handlePageReset}
        page={page}
        hasNextPage={data?.pages[page]?.nextCursor}
      />
    </>
  );
};

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

const PaginationHandler = ({
  handleFetchNextPage,
  handleFetchPreviousPage,
  handlePageReset,
  page,
  hasNextPage,
}: {
  handleFetchNextPage: () => Promise<void>;
  handleFetchPreviousPage: () => void;
  handlePageReset: () => void;
  page: number;
  hasNextPage: string | undefined;
}) => {
  const [attivo, setAttivo] = useState(true);
  const fetchNextPage = async () => {
    setAttivo(false);
    await handleFetchNextPage();
    setAttivo(true);
  };

  return (
    <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={handlePageReset}
          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={handleFetchPreviousPage}
          disabled={page < 1}
        >
          <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",
            hasNextPage === undefined ? "invisible" : "visible",
          )}
          onClick={fetchNextPage}
          disabled={!hasNextPage || attivo === false}
        >
          <ChevronRight height={30} />
        </button>
      </div>
    </div>
  );
};
