'use client';

import { useState } from 'react';
import { Check, ChevronsUpDown, Save, X } from 'lucide-react';
import { useQuery } from '@tanstack/react-query';

import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from '@/components/ui/command';
import { Label } from '@/components/ui/label';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Switch } from '@/components/ui/switch';
import { Textarea } from '@/components/ui/textarea';
import { apiFetch } from '@/lib/api/client';
import { cn } from '@/lib/utils';

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

export interface RecipientConfigValue {
  emails: string[];
  userIds: string[];
  roleIds: string[];
  everyone: boolean;
}

/**
 * Client mirror of the server's parseRecipientConfig
 * (`src/lib/services/notification-recipients.ts`) - kept inline because that
 * module imports server-only deps (drizzle/db). A legacy `string[]` is treated
 * as explicit emails.
 */
function parseValue(value: unknown): RecipientConfigValue {
  const strArr = (v: unknown): string[] =>
    Array.isArray(v)
      ? v.filter((x): x is string => typeof x === 'string' && x.trim().length > 0)
      : [];
  if (Array.isArray(value)) {
    return { emails: strArr(value), userIds: [], roleIds: [], everyone: false };
  }
  if (value && typeof value === 'object') {
    const o = value as Record<string, unknown>;
    return {
      emails: strArr(o.emails),
      userIds: strArr(o.userIds),
      roleIds: strArr(o.roleIds),
      everyone: o.everyone === true,
    };
  }
  return { emails: [], userIds: [], roleIds: [], everyone: false };
}

function MultiSelect({
  options,
  selected,
  onChange,
  placeholder,
  searchPlaceholder,
  emptyText,
}: {
  options: Option[];
  selected: string[];
  onChange: (next: string[]) => void;
  placeholder: string;
  searchPlaceholder: string;
  emptyText: string;
}) {
  const [open, setOpen] = useState(false);
  const byId = new Map(options.map((o) => [o.id, o.label]));
  const toggle = (id: string) =>
    onChange(selected.includes(id) ? selected.filter((s) => s !== id) : [...selected, id]);

  return (
    <div className="space-y-2">
      {selected.length > 0 ? (
        <div className="flex flex-wrap gap-1.5">
          {selected.map((id) => (
            <Badge key={id} variant="secondary" className="gap-1">
              {byId.get(id) ?? id.slice(0, 8)}
              <button
                type="button"
                onClick={() => toggle(id)}
                className="ml-0.5 rounded-sm hover:bg-muted-foreground/20"
                aria-label={`Remove ${byId.get(id) ?? id}`}
              >
                <X className="h-3 w-3" aria-hidden />
              </button>
            </Badge>
          ))}
        </div>
      ) : null}
      <Popover open={open} onOpenChange={setOpen} modal>
        <PopoverTrigger asChild>
          <Button
            type="button"
            variant="outline"
            role="combobox"
            className="w-full justify-between sm:w-72"
          >
            <span className="truncate text-muted-foreground">{placeholder}</span>
            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" aria-hidden />
          </Button>
        </PopoverTrigger>
        <PopoverContent className="w-[280px] p-0" align="start">
          <Command>
            <CommandInput placeholder={searchPlaceholder} />
            <CommandList>
              <CommandEmpty>{emptyText}</CommandEmpty>
              <CommandGroup>
                {options.map((o) => (
                  <CommandItem key={o.id} value={o.label} onSelect={() => toggle(o.id)}>
                    <Check
                      className={cn(
                        'mr-2 h-4 w-4',
                        selected.includes(o.id) ? 'opacity-100' : 'opacity-0',
                      )}
                    />
                    {o.label}
                  </CommandItem>
                ))}
              </CommandGroup>
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>
    </div>
  );
}

/**
 * Admin control for an inquiry notification-recipient setting. Edits the
 * structured `{emails,userIds,roleIds,everyone}` config (or a legacy email
 * array) and persists via the parent's `onSave`. The server resolver expands
 * users/roles/everyone into concrete addresses at send time.
 */
export function RecipientPicker({
  value,
  saving,
  onSave,
}: {
  value: unknown;
  saving: boolean;
  onSave: (config: RecipientConfigValue) => void;
}) {
  const initial = parseValue(value);
  const [everyone, setEveryone] = useState(initial.everyone);
  const [userIds, setUserIds] = useState<string[]>(initial.userIds);
  const [roleIds, setRoleIds] = useState<string[]>(initial.roleIds);
  const [emailsText, setEmailsText] = useState(initial.emails.join('\n'));

  const { data: usersData } = useQuery<{ data: { id: string; displayName: string | null }[] }>({
    queryKey: ['recipient-user-options'],
    queryFn: () => apiFetch('/api/v1/admin/users/options'),
    staleTime: 5 * 60_000,
  });
  const { data: rolesData } = useQuery<{ data: { id: string; name: string }[] }>({
    queryKey: ['recipient-role-options'],
    queryFn: () => apiFetch('/api/v1/admin/roles'),
    staleTime: 5 * 60_000,
  });

  const userOptions: Option[] = (usersData?.data ?? []).map((u) => ({
    id: u.id,
    label: u.displayName ?? u.id.slice(0, 8),
  }));
  const roleOptions: Option[] = (rolesData?.data ?? []).map((r) => ({ id: r.id, label: r.name }));

  function handleSave() {
    const emails = emailsText
      .split(/[\n,]/)
      .map((e) => e.trim())
      .filter((e) => e.length > 0);
    onSave({ emails, userIds, roleIds, everyone });
  }

  return (
    <div className="space-y-3 rounded-md border p-3">
      <div className="flex items-center justify-between gap-4">
        <div>
          <Label>Everyone with inquiry access</Label>
          <p className="text-xs text-muted-foreground">
            Send to every user whose role grants inquiry visibility.
          </p>
        </div>
        <Switch checked={everyone} onCheckedChange={setEveryone} />
      </div>

      <div className="space-y-1.5">
        <Label className="text-xs uppercase tracking-wide text-muted-foreground">
          Specific users
        </Label>
        <MultiSelect
          options={userOptions}
          selected={userIds}
          onChange={setUserIds}
          placeholder="Add users…"
          searchPlaceholder="Search users…"
          emptyText="No users found."
        />
      </div>

      <div className="space-y-1.5">
        <Label className="text-xs uppercase tracking-wide text-muted-foreground">Roles</Label>
        <MultiSelect
          options={roleOptions}
          selected={roleIds}
          onChange={setRoleIds}
          placeholder="Add roles…"
          searchPlaceholder="Search roles…"
          emptyText="No roles found."
        />
      </div>

      <div className="space-y-1.5">
        <Label className="text-xs uppercase tracking-wide text-muted-foreground">
          Additional email addresses
        </Label>
        <Textarea
          rows={3}
          className="text-sm"
          placeholder="One per line (or comma-separated)"
          value={emailsText}
          onChange={(e) => setEmailsText(e.target.value)}
        />
      </div>

      <Button size="sm" onClick={handleSave} disabled={saving}>
        <Save className="mr-1.5 h-3.5 w-3.5" aria-hidden />
        {saving ? 'Saving…' : 'Save recipients'}
      </Button>
    </div>
  );
}
