"use client";

import * as React from "react";
import { List, type RowComponentProps } from "react-window";
import { ChevronDown } from "lucide-react";
import type { Pipeline } from "@/api/rtk/pipelines-api";
import { cn } from "@/lib/utils";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import { Spinner } from "@/components/ui/spinner";

const ROW_HEIGHT = 40;
const MAX_VISIBLE_ROWS = 8;
const MAX_LIST_HEIGHT = ROW_HEIGHT * MAX_VISIBLE_ROWS;

export type VirtualizedPipelineSelectProps = {
  pipelines?: Pipeline[];
  loading: boolean;
  value: string | null;
  onChange: (pipelineId: string) => void;
  triggerClassName?: string;
};

type PipelineRowProps = {
  pipelines: Pipeline[];
  selectedId: string | null;
  onSelect: (id: string) => void;
};

function PipelineListRow({
  index,
  style,
  ariaAttributes,
  pipelines,
  selectedId,
  onSelect,
}: RowComponentProps<PipelineRowProps>) {
  const p = pipelines[index];
  if (!p) return null;
  const selected = p.id === selectedId;
  return (
    <div {...ariaAttributes} style={style} className="px-1">
      <button
        type="button"
        role="option"
        aria-selected={selected}
        className={cn(
          "flex h-9 w-full items-center rounded-lg px-3 text-left text-[13px] font-bold font-['Lexend_Deca'] transition-colors",
          "hover:bg-accent/10 hover:text-accent",
          selected && "bg-accent/15 text-accent",
        )}
        onClick={() => onSelect(p.id)}
      >
        <span className="truncate">{p.name}</span>
      </button>
    </div>
  );
}

export function VirtualizedPipelineSelect({
  pipelines,
  loading,
  value,
  onChange,
  triggerClassName,
}: VirtualizedPipelineSelectProps) {
  const [open, setOpen] = React.useState(false);
  const list = React.useMemo(() => pipelines ?? [], [pipelines]);
  const selected = list.find((p) => p.id === value);

  const rowProps = React.useMemo<PipelineRowProps>(
    () => ({
      pipelines: list,
      selectedId: value,
      onSelect: (id: string) => {
        onChange(id);
        setOpen(false);
      },
    }),
    [list, value, onChange],
  );

  const listHeight =
    list.length === 0 ? 0 : Math.min(list.length * ROW_HEIGHT, MAX_LIST_HEIGHT);

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <button
          type="button"
          disabled={loading && list.length === 0}
          aria-haspopup="listbox"
          aria-expanded={open}
          aria-label="Select pipeline"
          className={cn(
            "flex h-10 w-full items-center justify-between gap-2 rounded-xl border border-border/80 bg-white px-3.5 text-[13px] font-bold font-['Lexend_Deca'] shadow-sm transition-all outline-none",
            "hover:border-accent focus-visible:ring-2 focus-visible:ring-accent/20 disabled:cursor-not-allowed disabled:opacity-50",
            triggerClassName,
          )}
        >
          <span className="flex min-w-0 flex-1 items-center gap-2 truncate">
            {loading ? <Spinner className="size-3 shrink-0" /> : null}
            <span className="truncate text-left">
              {selected?.name ?? (loading ? "Loading…" : "Pipeline")}
            </span>
          </span>
          <ChevronDown className="size-4 shrink-0 text-muted-foreground opacity-70" />
        </button>
      </PopoverTrigger>
      <PopoverContent
        align="start"
        className="w-72 max-w-[min(100vw-2rem,24rem)] rounded-2xl border-border/40 p-1 shadow-premium"
        onOpenAutoFocus={(e) => e.preventDefault()}
      >
        {list.length === 0 ? (
          <p className="px-3 py-3 text-center text-sm text-muted-foreground">
            No pipelines
          </p>
        ) : (
          <List<PipelineRowProps>
            rowCount={list.length}
            rowHeight={ROW_HEIGHT}
            rowComponent={PipelineListRow}
            rowProps={rowProps}
            overscanCount={6}
            style={{ height: listHeight, width: "100%" }}
          />
        )}
      </PopoverContent>
    </Popover>
  );
}
