"use client"

import { useMemo, useRef, useState } from "react"
import { X } from "lucide-react"
import { Input } from "@/components/ui/input"
import type { AgendaInvitationExclusion } from "@/lib/agenda/agenda-settings-types"
import { exclusionKey } from "@/lib/agenda/agenda-settings-types"
import { useAgendaInvitationSuggestions } from "@/lib/agenda/use-agenda-invitation-suggestions"
import { cn } from "@/lib/utils"

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/

export function AgendaSettingsChipPicker({
  items,
  onChange,
  placeholder,
  allowedTypes,
  emptyHint,
}: {
  items: AgendaInvitationExclusion[]
  onChange: (items: AgendaInvitationExclusion[]) => void
  placeholder: string
  allowedTypes?: AgendaInvitationExclusion["type"][]
  emptyHint?: string
}) {
  const [query, setQuery] = useState("")
  const [focused, setFocused] = useState(false)
  const [activeIndex, setActiveIndex] = useState(0)
  const blurTimer = useRef<number | null>(null)

  const taken = useMemo(() => new Set(items.map(exclusionKey)), [items])
  const suggestions = useAgendaInvitationSuggestions(query, taken, {
    types: allowedTypes,
  })

  const addItem = (item: AgendaInvitationExclusion) => {
    if (taken.has(exclusionKey(item))) return
    onChange([...items, item])
    setQuery("")
    setActiveIndex(0)
  }

  const removeItem = (id: string) => {
    onChange(items.filter((item) => exclusionKey(item) !== id))
  }

  const tryAddEmail = () => {
    const email = query.trim().replace(/[,;]$/, "")
    if (!EMAIL_RE.test(email)) return false
    addItem({ type: "email", value: email, label: email })
    return true
  }

  const showSuggestions =
    focused && (suggestions.length > 0 || EMAIL_RE.test(query.trim()))

  const grouped = useMemo(() => {
    const map = new Map<string, typeof suggestions>()
    for (const s of suggestions) {
      const list = map.get(s.group) ?? []
      list.push(s)
      map.set(s.group, list)
    }
    return [...map.entries()]
  }, [suggestions])

  let flatIndex = -1

  return (
    <div className="flex flex-col gap-1.5">
      <div
        className={cn(
          "min-h-9 rounded-md border border-input bg-background px-2 py-1.5",
          "focus-within:ring-2 focus-within:ring-ring/40",
        )}
      >
        {items.length > 0 ? (
          <div className="mb-1 flex flex-wrap gap-1">
            {items.map((item) => (
              <span
                key={exclusionKey(item)}
                className="inline-flex max-w-full items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-[11px] text-foreground"
              >
                <span className="truncate">{item.label}</span>
                <button
                  type="button"
                  className="shrink-0 rounded-full p-0.5 hover:bg-background/80"
                  aria-label={`Retirer ${item.label}`}
                  onClick={() => removeItem(exclusionKey(item))}
                >
                  <X className="size-3" />
                </button>
              </span>
            ))}
          </div>
        ) : null}
        <Input
          value={query}
          placeholder={items.length === 0 ? placeholder : "Ajouter…"}
          className="h-7 border-0 bg-transparent px-0 text-xs shadow-none focus-visible:ring-0"
          onChange={(e) => {
            setQuery(e.target.value)
            setActiveIndex(0)
          }}
          onFocus={() => {
            if (blurTimer.current) window.clearTimeout(blurTimer.current)
            setFocused(true)
          }}
          onBlur={() => {
            blurTimer.current = window.setTimeout(() => setFocused(false), 120)
          }}
          onKeyDown={(e) => {
            if (e.key === "Backspace" && !query && items.length > 0) {
              removeItem(exclusionKey(items[items.length - 1]!))
              return
            }
            if (e.key === "Enter" || e.key === ",") {
              e.preventDefault()
              if (suggestions[activeIndex]) addItem(suggestions[activeIndex]!)
              else tryAddEmail()
              return
            }
            if (!showSuggestions || suggestions.length === 0) return
            if (e.key === "ArrowDown") {
              e.preventDefault()
              setActiveIndex((i) => (i + 1) % suggestions.length)
            } else if (e.key === "ArrowUp") {
              e.preventDefault()
              setActiveIndex((i) => (i - 1 + suggestions.length) % suggestions.length)
            }
          }}
        />
      </div>

      {showSuggestions ? (
        <ul className="max-h-44 overflow-y-auto rounded-md border border-border bg-popover py-1 shadow-md">
          {grouped.map(([group, groupItems]) => (
            <li key={group}>
              <p className="px-2 py-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground">
                {group}
              </p>
              {groupItems.map((s) => {
                flatIndex += 1
                const idx = flatIndex
                return (
                  <button
                    key={s.id}
                    type="button"
                    className={cn(
                      "block w-full px-2 py-1.5 text-left text-xs hover:bg-muted",
                      idx === activeIndex && "bg-muted",
                    )}
                    onMouseDown={(e) => {
                      e.preventDefault()
                      addItem(s)
                    }}
                  >
                    {s.label}
                  </button>
                )
              })}
            </li>
          ))}
        </ul>
      ) : null}

      {emptyHint && items.length === 0 ? (
        <p className="text-[11px] text-muted-foreground">{emptyHint}</p>
      ) : null}
    </div>
  )
}
