import { useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";
import { useTranslation } from "react-i18next";

import { useSearch, HttpError } from "../api/queries";
import { useDebouncedValue } from "../lib/use-debounced-value";
import { segmentClass } from "../lib/class-recipes";
import { SearchResultRow } from "./search-result-row";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { ListSkeleton } from "@/components/ui/skeletons";

const VIS = ["all", "draft", "internal", "public"] as const;

export function SearchPanel() {
  const { t } = useTranslation();
  const [params, setParams] = useSearchParams();
  const [text, setText] = useState(() => params.get("q") ?? "");
  const visibility = params.get("visibility"); // null == "all"
  const debounced = useDebouncedValue(text, 300);

  useEffect(() => {
    setParams(
      (prev) => {
        const next = new URLSearchParams(prev);
        const term = debounced.trim();

        if (term) next.set("q", term);
        else next.delete("q");

        return next;
      },
      { replace: true },
    );
  }, [debounced, setParams]);

  const search = useSearch(debounced, visibility);

  const setVisibility = (value: string) =>
    setParams(
      (prev) => {
        const next = new URLSearchParams(prev);

        if (value === "all") next.delete("visibility");
        else next.set("visibility", value);

        return next;
      },
      { replace: true },
    );

  const hits = search.data?.pages.flatMap((page) => page.hits) ?? [];
  const total = search.data?.pages[0]?.estimated_total ?? 0;
  const hasQuery = debounced.trim().length > 0;

  return (
    <div className="flex h-full flex-col">
      <div className="space-y-2 border-b p-3">
        <Input
          value={text}
          onChange={(event) => setText(event.target.value)}
          placeholder={t("search.placeholder")}
          aria-label={t("search.placeholder")}
        />
        <div className="flex gap-1 text-xs">
          {VIS.map((value) => {
            const active = (visibility ?? "all") === value;

            return (
              <button
                key={value}
                type="button"
                aria-pressed={active}
                onClick={() => setVisibility(value)}
                className={segmentClass(active, "px-2 py-0.5")}
              >
                {value === "all" ? t("search.all") : t(`visibility.${value}`)}
              </button>
            );
          })}
        </div>
      </div>

      <div className="flex-1 overflow-auto">
        {!hasQuery && <p className="p-4 text-sm text-muted-foreground">{t("search.prompt")}</p>}

        {hasQuery && search.isLoading && (
          <ListSkeleton rows={5} rowClassName="h-12 w-full" />
        )}

        {hasQuery && search.isError && (
          <p className="p-4 text-sm text-destructive">
            {search.error instanceof HttpError && search.error.status === 503
              ? t("search.unavailable")
              : t("search.loadError")}
          </p>
        )}

        {hasQuery && !search.isLoading && !search.isError && hits.length === 0 && (
          <p className="p-4 text-sm text-muted-foreground">{t("search.empty")}</p>
        )}

        {hits.length > 0 && (
          <>
            <p role="status" className="px-3 pt-2 text-xs text-muted-foreground">
              {t("search.resultCount", { count: total })}
            </p>
            <ul>
              {hits.map((hit) => (
                <SearchResultRow key={hit.id} hit={hit} />
              ))}
            </ul>
            {search.hasNextPage && (
              <div className="p-3 text-center">
                <Button
                  variant="ghost"
                  size="sm"
                  disabled={search.isFetchingNextPage}
                  onClick={() => search.fetchNextPage()}
                >
                  {t("search.loadMore")}
                </Button>
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
}
