'use client';

import type { DiscordRoleOption } from '@nexumi/shared';
import { Check, ChevronsUpDown, X } from 'lucide-react';
import { useMemo, useState } from 'react';
import { useTranslations } from '@/components/locale-provider';
import { Button } from '@/components/ui/button';
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList
} from '@/components/ui/command';
import { DiscordResourceMultiSelect } from '@/components/ui/discord-resource-multi-select';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { useGuildRoles } from '@/hooks/use-guild-roles';
import { cn } from '@/lib/utils';

function toOptions(roles: DiscordRoleOption[]) {
  return roles.map((role) => ({
    id: role.id,
    name: role.name,
    prefix: '@'
  }));
}

function normalizeSearch(value: string): string {
  return value.trim().toLocaleLowerCase();
}

interface RoleSelectBaseProps {
  guildId: string;
  disabled?: boolean;
  placeholder?: string;
}

interface DiscordRoleSelectProps extends RoleSelectBaseProps {
  value: string;
  onChange: (next: string) => void;
  allowClear?: boolean;
}

/** Single role picker (searchable). Empty string = cleared. */
export function DiscordRoleSelect({
  guildId,
  value,
  onChange,
  disabled = false,
  placeholder,
  allowClear = true
}: DiscordRoleSelectProps) {
  const t = useTranslations();
  const { roles, loading, error, reload } = useGuildRoles(guildId);
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState('');

  const options = useMemo(() => toOptions(roles), [roles]);
  const selected = options.find((option) => option.id === value);
  const filtered = useMemo(() => {
    const needle = normalizeSearch(query);
    if (!needle) {
      return options;
    }
    return options.filter((option) => {
      const haystack = normalizeSearch(`${option.prefix}${option.name} ${option.id}`);
      return haystack.includes(needle);
    });
  }, [options, query]);

  return (
    <Popover
      open={open}
      onOpenChange={(next) => {
        setOpen(next);
        if (!next) {
          setQuery('');
        }
      }}
    >
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          role="combobox"
          aria-expanded={open}
          disabled={disabled || loading}
          className="h-9 w-full justify-between px-3 font-normal"
        >
          <span className={cn('truncate', !selected && 'text-muted-foreground')}>
            {selected
              ? `${selected.prefix}${selected.name}`
              : (placeholder ?? t('modulePages.commands.roleSearchPlaceholder'))}
          </span>
          <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="p-0" align="start">
        <Command shouldFilter={false}>
          <CommandInput
            value={query}
            onValueChange={setQuery}
            placeholder={placeholder ?? t('modulePages.commands.roleSearchPlaceholder')}
          />
          <CommandList>
            <CommandEmpty>
              {error ? (
                <button type="button" className="underline" onClick={() => reload()}>
                  {t('common.saveError')}
                </button>
              ) : (
                t('common.noResults')
              )}
            </CommandEmpty>
            <CommandGroup>
              {allowClear && value ? (
                <CommandItem
                  value="__clear__"
                  onSelect={() => {
                    onChange('');
                    setOpen(false);
                  }}
                >
                  <X className="size-4 opacity-60" />
                  <span className="text-muted-foreground">{t('common.clearSelection')}</span>
                </CommandItem>
              ) : null}
              {filtered.map((option) => (
                <CommandItem
                  key={option.id}
                  value={`${option.name} ${option.id}`}
                  onSelect={() => {
                    onChange(option.id);
                    setOpen(false);
                  }}
                >
                  <Check className={cn('size-4', value === option.id ? 'opacity-100' : 'opacity-0')} />
                  <span className="truncate">
                    {option.prefix}
                    {option.name}
                  </span>
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
}

interface DiscordRoleMultiSelectProps extends RoleSelectBaseProps {
  value: string[];
  onChange: (next: string[]) => void;
}

/** Multi role picker (searchable). */
export function DiscordRoleMultiSelect({
  guildId,
  value,
  onChange,
  disabled = false,
  placeholder
}: DiscordRoleMultiSelectProps) {
  const t = useTranslations();
  const { roles, loading } = useGuildRoles(guildId);
  const options = useMemo(() => toOptions(roles), [roles]);

  return (
    <DiscordResourceMultiSelect
      options={options}
      value={value}
      onChange={onChange}
      disabled={disabled || loading}
      placeholder={placeholder ?? t('modulePages.commands.roleSearchPlaceholder')}
    />
  );
}
