"use client"

import * as React from "react"
import { usePathname, useRouter, useSearchParams } from "next/navigation"

import { useT } from "@/components/locale-provider"
import { Button } from "@/components/ui/button"
import {
  Combobox,
  ComboboxChip,
  ComboboxChips,
  ComboboxChipsInput,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxItem,
  ComboboxList,
} from "@/components/ui/combobox"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
} from "@/components/ui/input-group"
import { IconSearch, IconX } from "@tabler/icons-react"

/**
 * Search and filters for the positions table.
 *
 * The url is the state. Typing replaces after a pause, so Back does not undo
 * letters one at a time; picking or clearing a department pushes, so Back
 * restores the previous selection. A filtered view is therefore a link somebody
 * can send.
 */
export function PositionsToolbar({
  departments,
  vacantCount,
}: {
  departments: string[]
  vacantCount: number
}) {
  const t = useT()
  const router = useRouter()
  const pathname = usePathname()
  const params = useSearchParams()

  const query = params.get("q") ?? ""
  const selected = params.getAll("dept")
  const vacantOnly = params.get("vacant") === "1"

  // The field keeps local state so it stays responsive under the fingers, and
  // realigns when the url changes without it, which is the Back button. React
  // documents this adjustment during render; doing it in an effect would render
  // once with the old value and again with the new one.
  const [text, setText] = React.useState(query)
  const [seenQuery, setSeenQuery] = React.useState(query)
  if (query !== seenQuery) {
    setSeenQuery(query)
    setText(query)
  }

  const pending = React.useRef<ReturnType<typeof setTimeout> | null>(null)
  React.useEffect(
    () => () => {
      if (pending.current) clearTimeout(pending.current)
    },
    [],
  )

  const write = React.useCallback(
    (next: URLSearchParams, mode: "push" | "replace") => {
      const href = next.size ? `${pathname}?${next}` : pathname
      router[mode](href, { scroll: false })
    },
    [pathname, router],
  )

  const onType = (value: string) => {
    setText(value)
    if (pending.current) clearTimeout(pending.current)
    pending.current = setTimeout(() => {
      const next = new URLSearchParams(params.toString())
      if (value) next.set("q", value)
      else next.delete("q")
      write(next, "replace")
    }, 250)
  }

  const onDepartments = (values: string[]) => {
    const next = new URLSearchParams(params.toString())
    next.delete("dept")
    for (const v of values) next.append("dept", v)
    write(next, "push")
  }

  const onVacant = () => {
    const next = new URLSearchParams(params.toString())
    if (vacantOnly) next.delete("vacant")
    else next.set("vacant", "1")
    write(next, "push")
  }

  return (
    <div className="flex flex-wrap items-center gap-3">
      <InputGroup className="h-10 w-full sm:w-72">
        <InputGroupAddon>
          <IconSearch />
        </InputGroupAddon>
        <InputGroupInput
          placeholder={t("positions.searchPlaceholder")}
          value={text}
          onChange={(e) => onType(e.target.value)}
          aria-label={t("positions.searchPlaceholder")}
        />
        {text ? (
          <InputGroupAddon align="inline-end">
            <InputGroupButton
              aria-label={t("action.clear")}
              onClick={() => onType("")}
            >
              <IconX />
            </InputGroupButton>
          </InputGroupAddon>
        ) : null}
      </InputGroup>

      <Combobox
        items={departments}
        multiple
        value={selected}
        onValueChange={onDepartments}
      >
        <ComboboxChips className="min-h-10 w-full sm:w-80">
          {selected.map((name) => (
            <ComboboxChip key={name} aria-label={name}>
              {name}
            </ComboboxChip>
          ))}
          <ComboboxChipsInput
            placeholder={selected.length ? "" : t("nav.allDepartments")}
            aria-label={t("positions.filterByDepartment")}
          />
        </ComboboxChips>
        <ComboboxContent>
          <ComboboxEmpty>{t("team.noSuchDepartment")}</ComboboxEmpty>
          <ComboboxList>
            {(name: string) => (
              <ComboboxItem key={name} value={name}>
                {name}
              </ComboboxItem>
            )}
          </ComboboxList>
        </ComboboxContent>
      </Combobox>

      <Button
        variant={vacantOnly ? "default" : "outline"}
        onClick={onVacant}
        aria-pressed={vacantOnly}
      >
        {t("positions.vacantOnly")}
        <span className="tabular-nums">{vacantCount}</span>
      </Button>
    </div>
  )
}
