"use client";

import * as React from "react";
import { Check, ChevronsUpDown, Loader2 } from "lucide-react";
import { cn } from "@/shared/lib/utils";
import { useDebounce } from "@/presentation/hooks/use-debounce";
import { useRepositories } from "@/di/repository-provider";
import { Button } from "@/presentation/components/ui/button";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/presentation/components/ui/popover";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/presentation/components/ui/command";

interface PaginatedSectionSelectProps {
  value?: string;
  onValueChange?: (value: string) => void;
  /** Label to render in the trigger when `value` is set but not yet loaded. */
  selectedLabel?: string;
  placeholder?: string;
  searchPlaceholder?: string;
  emptyText?: string;
  loadingText?: string;
  disabled?: boolean;
  triggerClassName?: string;
  contentClassName?: string;
  perPage?: number;
}

interface Option {
  value: string;
  label: string;
}

export function PaginatedSectionSelect({
  value,
  onValueChange,
  selectedLabel,
  placeholder = "Choisir une section",
  searchPlaceholder = "Rechercher une section...",
  emptyText = "Aucune section",
  loadingText = "Chargement...",
  disabled,
  triggerClassName,
  contentClassName,
  perPage = 10,
}: PaginatedSectionSelectProps) {
  const { helpSectionRepository } = useRepositories();
  const [open, setOpen] = React.useState(false);
  const [search, setSearch] = React.useState("");
  const debouncedSearch = useDebounce(search, 300);
  const [items, setItems] = React.useState<Option[]>([]);
  const [page, setPage] = React.useState(1);
  const [hasMore, setHasMore] = React.useState(false);
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);
  const requestIdRef = React.useRef(0);

  const fetchPage = React.useCallback(
    async (nextPage: number, currentSearch: string, replace: boolean) => {
      const requestId = ++requestIdRef.current;
      setLoading(true);
      setError(null);
      try {
        const res = await helpSectionRepository.findAll({
          page: nextPage,
          per_page: perPage,
          search: currentSearch || undefined,
          sort_by: "name",
          sort_dir: "asc",
        });
        if (requestId !== requestIdRef.current) return;
        const fetched: Option[] = (res.data ?? []).map((s) => ({
          value: s.id?.toString() ?? "",
          label: s.name,
        }));
        setItems((prev) => {
          if (replace) return fetched;
          const seen = new Set(prev.map((o) => o.value));
          return [...prev, ...fetched.filter((o) => !seen.has(o.value))];
        });
        const meta = res.meta;
        setHasMore(meta ? meta.current_page < meta.last_page : false);
        setPage(nextPage);
      } catch (err) {
        if (requestId !== requestIdRef.current) return;
        setError(err instanceof Error ? err.message : "Erreur de chargement");
      } finally {
        if (requestId === requestIdRef.current) setLoading(false);
      }
    },
    [helpSectionRepository, perPage],
  );

  React.useEffect(() => {
    if (!open) return;
    fetchPage(1, debouncedSearch, true);
  }, [open, debouncedSearch, fetchPage]);

  const handleScroll = React.useCallback(
    (e: React.UIEvent<HTMLDivElement>) => {
      if (loading || !hasMore) return;
      const el = e.currentTarget;
      if (el.scrollHeight - el.scrollTop - el.clientHeight < 40) {
        fetchPage(page + 1, debouncedSearch, false);
      }
    },
    [loading, hasMore, page, debouncedSearch, fetchPage],
  );

  const selectedFromItems = items.find((o) => o.value === value);
  const triggerLabel =
    selectedFromItems?.label ?? (value ? selectedLabel : undefined) ?? placeholder;
  const isPlaceholder = !selectedFromItems && (!value || !selectedLabel);

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          role="combobox"
          aria-expanded={open}
          disabled={disabled}
          className={cn(
            "h-10 w-full justify-between font-normal text-sm",
            isPlaceholder && "text-muted-foreground",
            triggerClassName,
          )}
        >
          <span className="truncate">{triggerLabel}</span>
          <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent
        className={cn(
          "p-0 w-[var(--radix-popover-trigger-width)] min-w-56",
          contentClassName,
        )}
        align="start"
      >
        <Command shouldFilter={false}>
          <CommandInput
            placeholder={searchPlaceholder}
            className="h-9"
            value={search}
            onValueChange={setSearch}
          />
          <CommandList onScroll={handleScroll}>
            {!loading && items.length === 0 ? (
              <CommandEmpty>{error ?? emptyText}</CommandEmpty>
            ) : (
              <CommandGroup>
                {items.map((opt) => (
                  <CommandItem
                    key={opt.value}
                    value={opt.value}
                    onSelect={(v) => {
                      onValueChange?.(v);
                      setOpen(false);
                    }}
                  >
                    <Check
                      className={cn(
                        "mr-2 h-4 w-4",
                        value === opt.value ? "opacity-100" : "opacity-0",
                      )}
                    />
                    <span className="truncate">{opt.label}</span>
                  </CommandItem>
                ))}
                {loading && (
                  <div className="flex items-center justify-center gap-2 py-2 text-xs text-muted-foreground">
                    <Loader2 className="h-3.5 w-3.5 animate-spin" />
                    <span>{loadingText}</span>
                  </div>
                )}
              </CommandGroup>
            )}
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
}
