'use client';

import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { CheckCircle2, ClipboardCopy, Clock, Mail, Send } from 'lucide-react';
import { formatDistanceToNowStrict } from 'date-fns';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { apiFetch } from '@/lib/api/client';

interface Props {
  interestId: string;
  /** Hide the button when EOI has already been sent / signed - at that
   *  point the supplemental step is past its window. Caller passes the
   *  current eoiStatus so we can render contextually. */
  eoiStatus?: string | null;
}

interface IssueResponse {
  data: {
    link: string;
    expiresAt: string;
    emailSent: boolean;
    resent?: boolean;
  };
}

interface TokenHistoryRow {
  id: string;
  token: string;
  createdAt: string;
  expiresAt: string;
  consumedAt: string | null;
  issuedBy: string | null;
  expired: boolean;
}

/**
 * One-click "Request more info" action. Fires the supplemental-info-
 * request endpoint, which emails the client a public form pre-filled
 * with what's on file. On success we display the generated link + a
 * copy-to-clipboard button in case the rep needs to share it through
 * another channel.
 *
 * Hidden once the EOI is `signed` - the supplemental step only makes
 * sense before the signed EOI freezes the data into the contract path.
 */
export function SupplementalInfoRequestButton({ interestId, eoiStatus }: Props) {
  const qc = useQueryClient();
  const [link, setLink] = useState<string | null>(null);

  // History query - the latest 20 issuances. Refetched after every
  // mutation so the rep sees the just-generated row appear immediately.
  const history = useQuery({
    queryKey: ['supplemental-info', interestId, 'history'],
    queryFn: () =>
      apiFetch<{ data: TokenHistoryRow[] }>(
        `/api/v1/interests/${interestId}/supplemental-info-request`,
      ),
    enabled: eoiStatus !== 'signed',
    staleTime: 30_000,
  });

  const mutation = useMutation({
    mutationFn: (vars: { sendEmail: boolean; tokenId?: string }) =>
      apiFetch<IssueResponse>(`/api/v1/interests/${interestId}/supplemental-info-request`, {
        method: 'POST',
        body: vars,
      }),
    onSuccess: (res) => {
      setLink(res.data.link);
      if (res.data.resent) {
        toast.success('Email re-sent using the existing link.');
      } else if (res.data.emailSent) {
        toast.success('Email sent. Link also shown below for sharing manually.');
      } else {
        toast.message(
          'Link generated. Click "Send by email" to mail it, or copy it to share manually.',
        );
      }
      void qc.invalidateQueries({ queryKey: ['supplemental-info', interestId, 'history'] });
    },
    onError: (err) =>
      toast.error(err instanceof Error ? err.message : 'Failed to generate the form link.'),
  });

  if (eoiStatus === 'signed') return null;

  // Pick the latest unconsumed + unexpired token, if any. That's the
  // candidate for "Resend" - the rep wants the same link to land in the
  // client's inbox again. Older or consumed tokens stay in history but
  // can't be resent (consumed = form already submitted; expired = link
  // dead).
  const tokens = history.data?.data ?? [];
  const resendableToken = tokens.find((t) => !t.consumedAt && !t.expired) ?? null;

  return (
    <Card>
      {/* shadcn's default CardContent ships with `pt-0 sm:pt-0` because it
          assumes a CardHeader sits above. This card is intentionally
          header-less, so we restore symmetric padding (`pt-` matches `p-`)
          at both base and `sm:` breakpoints. */}
      <CardContent className="space-y-3 p-4 pt-4 sm:p-6 sm:pt-6">
        <div className="space-y-1">
          <h3 className="text-sm font-semibold">Need more info before drafting the EOI?</h3>
          <p className="text-xs text-muted-foreground">
            Email the client a one-time link to a public form pre-filled with what we have on file.
            Submissions auto-update this client + interest record.
          </p>
        </div>
        <div className="flex flex-wrap items-center gap-2">
          <Button
            type="button"
            size="sm"
            variant={link ? 'outline' : 'default'}
            onClick={() => mutation.mutate({ sendEmail: false })}
            disabled={mutation.isPending}
          >
            {mutation.isPending
              ? 'Generating…'
              : resendableToken
                ? 'Regenerate link'
                : 'Generate link'}
          </Button>
          <Button
            type="button"
            size="sm"
            variant={resendableToken ? 'outline' : 'default'}
            onClick={() => mutation.mutate({ sendEmail: true })}
            disabled={mutation.isPending}
          >
            <Mail className="mr-1.5 size-3.5" aria-hidden />
            {resendableToken ? 'New link + email' : 'Generate + email'}
          </Button>
          {resendableToken ? (
            <Button
              type="button"
              size="sm"
              variant="default"
              onClick={() => mutation.mutate({ sendEmail: true, tokenId: resendableToken.id })}
              disabled={mutation.isPending}
              title="Re-email the existing active link to the client. No new token is created."
            >
              <Send className="mr-1.5 size-3.5" aria-hidden />
              Resend current
            </Button>
          ) : null}
          {link ? (
            <>
              <Input value={link} readOnly className="h-8 text-xs font-mono flex-1 min-w-[260px]" />
              <Button
                type="button"
                size="sm"
                variant="outline"
                onClick={() => {
                  void navigator.clipboard.writeText(link);
                  toast.success('Link copied');
                }}
              >
                <ClipboardCopy className="mr-1.5 size-3.5" aria-hidden />
                Copy
              </Button>
            </>
          ) : null}
        </div>

        {/* Issuance history - every past supplemental link for this
            interest, newest first. Lets the rep see whether a previous
            link is still outstanding (so they can Resend rather than
            mint a fresh one) and confirm whether the client ever
            submitted. Hidden when the list is empty. */}
        {tokens.length > 0 ? (
          <div className="space-y-1 border-t pt-2">
            <div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
              Issuance history
            </div>
            <ul className="divide-y">
              {tokens.map((t) => {
                const created = new Date(t.createdAt);
                const status = t.consumedAt
                  ? { label: 'Submitted', tone: 'text-emerald-700', icon: CheckCircle2 }
                  : t.expired
                    ? { label: 'Expired', tone: 'text-muted-foreground', icon: Clock }
                    : { label: 'Active', tone: 'text-amber-700', icon: Clock };
                const StatusIcon = status.icon;
                return (
                  <li key={t.id} className="flex items-center justify-between gap-2 py-1.5 text-xs">
                    <div className="flex items-center gap-1.5">
                      <StatusIcon className={`size-3 ${status.tone}`} aria-hidden />
                      <span className={`font-medium ${status.tone}`}>{status.label}</span>
                      <span className="text-muted-foreground">
                        {formatDistanceToNowStrict(created, { addSuffix: true })}
                      </span>
                    </div>
                  </li>
                );
              })}
            </ul>
          </div>
        ) : null}
      </CardContent>
    </Card>
  );
}
