'use client';

import { useEffect, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { AlertCircle, ArrowRight, Briefcase, X } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { apiFetch } from '@/lib/api/client';
import { cn } from '@/lib/utils';

interface MatchData {
  clientId: string;
  fullName: string;
  score: number;
  confidence: 'high' | 'medium' | 'low';
  reasons: string[];
  interestCount: number;
  emails: string[];
  phonesE164: string[];
}

interface DedupSuggestionPanelProps {
  /** Free-text inputs from the in-flight new-client form. The panel
   *  debounces them and queries /api/v1/clients/match-candidates. */
  email?: string | null;
  phone?: string | null;
  name?: string | null;
  /** Caller wants to attach the new interest to an existing client
   *  rather than creating a new one. The form switches to
   *  interest-only mode and pre-fills the client. */
  onUseExisting: (match: MatchData) => void;
  /** User explicitly said "create new anyway." Hide the panel until
   *  they change input again. */
  onDismiss?: () => void;
}

/**
 * Surfaces existing clients that match the form's in-flight inputs.
 *
 * Renders nothing while inputs are short / no useful match found.
 * On a high-confidence match, the panel interrupts visually with a
 * solid border and a primary "Use this client" button.
 *
 * Wired into the new-client form. Skipped in edit mode.
 */
export function DedupSuggestionPanel({
  email,
  phone,
  name,
  onUseExisting,
  onDismiss,
}: DedupSuggestionPanelProps) {
  const [dismissed, setDismissed] = useState(false);

  // Debounce inputs by 300ms so we don't fire on every keystroke. Keep
  // the latest debounced values in component state.
  const [debounced, setDebounced] = useState({
    email: email ?? '',
    phone: phone ?? '',
    name: name ?? '',
  });

  useEffect(() => {
    const t = setTimeout(() => {
      setDebounced({ email: email ?? '', phone: phone ?? '', name: name ?? '' });
      // Clear the dismissed flag when inputs change — the user typed
      // something new, so the prior dismissal no longer applies.
      setDismissed(false);
    }, 300);
    return () => clearTimeout(t);
  }, [email, phone, name]);

  const hasSomething =
    debounced.email.length > 3 || debounced.phone.length > 3 || debounced.name.length > 2;

  const { data, isFetching } = useQuery<{ data: MatchData[] }>({
    queryKey: ['dedup-match-candidates', debounced],
    queryFn: () => {
      const params = new URLSearchParams();
      if (debounced.email) params.set('email', debounced.email);
      if (debounced.phone) params.set('phone', debounced.phone);
      if (debounced.name) params.set('name', debounced.name);
      return apiFetch<{ data: MatchData[] }>(`/api/v1/clients/match-candidates?${params}`);
    },
    enabled: hasSomething && !dismissed,
    // Same query is fine to cache for a minute — moves are slow at this layer.
    staleTime: 60_000,
  });

  if (dismissed) return null;
  if (!hasSomething) return null;
  if (isFetching && !data) return null;
  const matches = data?.data ?? [];
  if (matches.length === 0) return null;

  const top = matches[0]!;
  const isHigh = top.confidence === 'high';

  return (
    <div
      className={cn(
        'rounded-lg border p-3 mb-3 transition-colors',
        isHigh
          ? 'border-amber-300 bg-amber-50/60 dark:bg-amber-950/30'
          : 'border-border bg-muted/40',
      )}
      data-testid="dedup-suggestion"
    >
      <div className="flex items-start gap-3">
        <div className="mt-0.5">
          <AlertCircle
            className={cn(
              'size-5',
              isHigh ? 'text-amber-700 dark:text-amber-400' : 'text-muted-foreground',
            )}
            aria-hidden
          />
        </div>
        <div className="min-w-0 flex-1">
          <p className="text-sm font-semibold leading-tight">
            {isHigh
              ? 'This looks like an existing client'
              : 'Possible match — check before creating'}
          </p>
          <div className="mt-2 rounded-md border bg-background/80 p-2.5">
            <div className="flex items-center gap-2">
              <p className="truncate text-sm font-medium">{top.fullName}</p>
              <span
                className={cn(
                  'shrink-0 rounded-full px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide',
                  isHigh
                    ? 'bg-amber-200 text-amber-900 dark:bg-amber-800 dark:text-amber-100'
                    : 'bg-muted text-muted-foreground',
                )}
              >
                {top.confidence}
              </span>
            </div>
            <div className="mt-0.5 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-muted-foreground">
              {top.emails[0] ? <span className="truncate">{top.emails[0]}</span> : null}
              {top.phonesE164[0] ? <span>{top.phonesE164[0]}</span> : null}
              <span className="inline-flex items-center gap-1">
                <Briefcase className="size-3" aria-hidden />
                {top.interestCount} {top.interestCount === 1 ? 'interest' : 'interests'}
              </span>
            </div>
            <p className="mt-1.5 text-[11px] text-muted-foreground">{top.reasons.join(' · ')}</p>
          </div>
          <div className="mt-3 flex flex-wrap items-center gap-2">
            <Button
              type="button"
              size="sm"
              onClick={() => onUseExisting(top)}
              data-testid="dedup-use-existing"
            >
              Use this client
              <ArrowRight className="ml-1 size-3.5" aria-hidden />
            </Button>
            <Button
              type="button"
              size="sm"
              variant="ghost"
              onClick={() => {
                setDismissed(true);
                onDismiss?.();
              }}
              data-testid="dedup-dismiss"
            >
              <X className="mr-1 size-3.5" aria-hidden />
              Create new anyway
            </Button>
            {matches.length > 1 ? (
              <span className="text-xs text-muted-foreground">
                +{matches.length - 1} other possible{' '}
                {matches.length - 1 === 1 ? 'match' : 'matches'}
              </span>
            ) : null}
          </div>
        </div>
      </div>
    </div>
  );
}
