'use client';

import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { ArrowRight, GitMerge, X } from 'lucide-react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import { PageHeader } from '@/components/shared/page-header';
import { EmptyState } from '@/components/shared/empty-state';
import { Skeleton } from '@/components/ui/skeleton';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { cn } from '@/lib/utils';

interface CandidatePair {
  id: string;
  score: number;
  reasons: string[];
  createdAt: string;
  clientA: { id: string; fullName: string; createdAt: string };
  clientB: { id: string; fullName: string; createdAt: string };
}

/**
 * Admin review queue for the dedup background scoring job.
 *
 * Lists every pending merge candidate (pairs where score >=
 * `dedup_review_queue_threshold`). For each pair the admin can:
 *   - Pick a winner via the side-by-side card → confirms a merge
 *   - Dismiss → removes from the queue (a future score increase
 *     re-creates the pair on the next scoring run)
 *
 * Only minimal merge UI here: the user picks which side is the winner
 * (no per-field choice), and the loser archives. A richer side-by-side
 * field-merge dialog is a future enhancement.
 */
export function DuplicatesReviewQueue() {
  const queryClient = useQueryClient();

  const { data, isLoading } = useQuery<{ data: CandidatePair[] }>({
    queryKey: ['admin', 'duplicates'],
    queryFn: () => apiFetch<{ data: CandidatePair[] }>('/api/v1/admin/duplicates'),
  });

  const pairs = data?.data ?? [];

  return (
    <div className="space-y-4">
      <PageHeader
        title="Duplicate clients"
        description={
          pairs.length === 0
            ? 'No pending pairs to review.'
            : `${pairs.length} pair${pairs.length === 1 ? '' : 's'} flagged for review.`
        }
      />

      {isLoading ? (
        <div className="space-y-3">
          {[0, 1, 2].map((i) => (
            <Skeleton key={i} className="h-32 w-full" />
          ))}
        </div>
      ) : pairs.length === 0 ? (
        <EmptyState
          title="All clear"
          description="The background scoring job hasn't surfaced any potential duplicates yet."
        />
      ) : (
        <ul className="space-y-3">
          {pairs.map((pair) => (
            <li key={pair.id}>
              <CandidateRow pair={pair} queryClient={queryClient} />
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

function CandidateRow({
  pair,
  queryClient,
}: {
  pair: CandidatePair;
  queryClient: ReturnType<typeof useQueryClient>;
}) {
  const [busy, setBusy] = useState<'merge' | 'dismiss' | null>(null);
  const [winnerId, setWinnerId] = useState<string>(pair.clientA.id);

  const mergeMutation = useMutation({
    mutationFn: () =>
      apiFetch(`/api/v1/admin/duplicates/${pair.id}/merge`, {
        method: 'POST',
        body: { winnerId },
      }),
    onSuccess: () => {
      const loserName =
        winnerId === pair.clientA.id ? pair.clientB.fullName : pair.clientA.fullName;
      const winnerName =
        winnerId === pair.clientA.id ? pair.clientA.fullName : pair.clientB.fullName;
      toast.success(`Merged "${loserName}" into "${winnerName}"`);
      queryClient.invalidateQueries({ queryKey: ['admin', 'duplicates'] });
      queryClient.invalidateQueries({ queryKey: ['clients'] });
    },
    onError: (err) => toastError(err),
    onSettled: () => setBusy(null),
  });

  const dismissMutation = useMutation({
    mutationFn: () => apiFetch(`/api/v1/admin/duplicates/${pair.id}/dismiss`, { method: 'POST' }),
    onSuccess: () => {
      toast.message('Dismissed');
      queryClient.invalidateQueries({ queryKey: ['admin', 'duplicates'] });
    },
    onError: (err) => toastError(err),
    onSettled: () => setBusy(null),
  });

  return (
    <div className="rounded-lg border bg-card p-4">
      <div className="mb-3 flex items-baseline justify-between gap-3">
        <div>
          <span className="rounded-full bg-muted px-2 py-0.5 text-xs font-medium uppercase tracking-wide text-muted-foreground">
            score {pair.score}
          </span>{' '}
          <span className="text-xs text-muted-foreground">{pair.reasons.join(' · ')}</span>
        </div>
        <span className="text-xs text-muted-foreground">
          flagged {new Date(pair.createdAt).toLocaleDateString()}
        </span>
      </div>

      <div className="grid gap-3 sm:grid-cols-[1fr_auto_1fr]">
        <ClientCard
          client={pair.clientA}
          isSelected={winnerId === pair.clientA.id}
          onSelect={() => setWinnerId(pair.clientA.id)}
        />
        <div className="flex items-center justify-center text-muted-foreground">
          <ArrowRight className="size-4" aria-hidden />
        </div>
        <ClientCard
          client={pair.clientB}
          isSelected={winnerId === pair.clientB.id}
          onSelect={() => setWinnerId(pair.clientB.id)}
        />
      </div>

      <div className="mt-3 flex flex-wrap items-center gap-2">
        <Button
          size="sm"
          onClick={() => {
            setBusy('merge');
            mergeMutation.mutate();
          }}
          disabled={busy !== null}
        >
          <GitMerge className="mr-1 size-3.5" aria-hidden />
          Merge into selected
        </Button>
        <Button
          size="sm"
          variant="ghost"
          onClick={() => {
            setBusy('dismiss');
            dismissMutation.mutate();
          }}
          disabled={busy !== null}
        >
          <X className="mr-1 size-3.5" aria-hidden />
          Dismiss
        </Button>
        <p className="text-xs text-muted-foreground">
          The unselected card becomes the loser; its interests + contacts move to the selected
          client and the original is archived.
        </p>
      </div>
    </div>
  );
}

function ClientCard({
  client,
  isSelected,
  onSelect,
}: {
  client: CandidatePair['clientA'];
  isSelected: boolean;
  onSelect: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onSelect}
      className={cn(
        'rounded-md border p-3 text-left transition-colors',
        isSelected
          ? 'border-primary bg-primary/5 ring-1 ring-primary/30'
          : 'border-border hover:bg-muted/40',
      )}
    >
      <p className="text-sm font-medium">{client.fullName}</p>
      <p className="mt-0.5 text-xs text-muted-foreground">
        Created {new Date(client.createdAt).toLocaleDateString()}
      </p>
      {isSelected ? (
        <span className="mt-1 inline-block rounded-full bg-primary/10 px-1.5 py-0.5 text-xs font-semibold text-primary">
          KEEP
        </span>
      ) : null}
    </button>
  );
}
