'use client';

import { useMemo, useState } from 'react';
import Link from 'next/link';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  AlertTriangle,
  CheckCircle2,
  ExternalLink,
  FileSignature,
  Loader2,
  RefreshCw,
  Upload,
  XCircle,
} from 'lucide-react';
import { toast } from 'sonner';

import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Skeleton } from '@/components/ui/skeleton';
import { PermissionGate } from '@/components/shared/permission-gate';
import { ExternalEoiUploadDialog } from '@/components/interests/external-eoi-upload-dialog';
import { MarkExternallySignedDialog } from '@/components/interests/mark-externally-signed-dialog';
import { SigningProgress } from '@/components/documents/signing-progress';
import { UploadForSigningDialog } from '@/components/documents/upload-for-signing-dialog';
import {
  CancelDocumentDialog,
  type CancelMode,
} from '@/components/documents/cancel-document-dialog';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { useConfirmation } from '@/hooks/use-confirmation';
import {
  DOCUMENT_STATUS_ACTIVE,
  DOCUMENT_STATUS_LABELS,
  type DocumentStatus,
} from '@/lib/labels/document-status';
import { cn } from '@/lib/utils';
import { useUIStore } from '@/stores/ui-store';

interface InterestReservationTabProps {
  interestId: string;
  clientId: string | null;
}

interface DocumentRow {
  id: string;
  documentType: string;
  title: string;
  status: DocumentStatus;
  createdAt: string;
  signers?: Array<{ status: string }>;
}

interface DocumentSigner {
  id: string;
  signerName: string;
  signerEmail: string;
  signerRole: string;
  signingOrder: number;
  status: string;
  signedAt?: string | null;
  invitedAt?: string | null;
  signingUrl?: string | null;
}

const STATUS_LABELS = DOCUMENT_STATUS_LABELS;

const STATUS_TONES: Record<DocumentStatus, string> = {
  draft: 'bg-slate-100 text-slate-700',
  sent: 'bg-blue-100 text-blue-700',
  partially_signed: 'bg-amber-100 text-amber-800',
  completed: 'bg-emerald-100 text-emerald-700',
  expired: 'bg-rose-100 text-rose-700',
  cancelled: 'bg-slate-200 text-slate-600',
  rejected: 'bg-rose-100 text-rose-700',
  declined: 'bg-rose-100 text-rose-700',
};

const ACTIVE_STATUSES = DOCUMENT_STATUS_ACTIVE;

/**
 * Dedicated Reservation workspace tab. Mirrors the EOI tab pattern but
 * for reservation agreements. Contracts differ from EOIs in that there's no
 * standard Documenso template - each reservation is drafted custom per
 * deal. So the active flows are:
 *
 *   1. **Upload paper-signed copy** - the signed reservation was handled
 *      outside the system; rep uploads the PDF for the record.
 *
 *   2. **Upload draft for Documenso signing** - rep uploads the PDF
 *      draft, configures signers + signing order + signature field
 *      placement, then sends via Documenso. (Recipient configurator
 *      and field-placement UI are the bigger pieces; for v1 a default
 *      footer-anchored signature layout is used.)
 *
 * The Documents tab still shows every reservation document (signed or
 * drafted) as a permanent history.
 */
export function InterestReservationTab({
  interestId,
  clientId: _clientId,
}: InterestReservationTabProps) {
  const portSlug = useUIStore((s) => s.currentPortSlug);
  const [uploadSignedOpen, setUploadSignedOpen] = useState(false);
  const [uploadForSigningOpen, setUploadForSigningOpen] = useState(false);
  const [markExternalOpen, setMarkExternalOpen] = useState(false);

  const { data: docsRes, isLoading: docsLoading } = useQuery<{ data: DocumentRow[] }>({
    queryKey: ['documents', { interestId, documentType: 'reservation_agreement' }],
    queryFn: () =>
      apiFetch<{ data: DocumentRow[] }>(
        `/api/v1/documents?interestId=${interestId}&documentType=reservation_agreement`,
      ),
  });

  const docs = docsRes?.data ?? [];
  const activeDoc = useMemo(() => docs.find((d) => ACTIVE_STATUSES.has(d.status)) ?? null, [docs]);
  const completedDocs = useMemo(() => docs.filter((d) => !ACTIVE_STATUSES.has(d.status)), [docs]);

  return (
    <div className="space-y-5">
      {docsLoading ? (
        <Skeleton className="h-44 w-full rounded-lg" aria-hidden />
      ) : activeDoc ? (
        <ActiveReservationCard
          doc={activeDoc}
          portSlug={portSlug ?? null}
          onUploadSigned={() => setUploadSignedOpen(true)}
        />
      ) : (
        <EmptyReservationState
          onMarkExternal={() => setMarkExternalOpen(true)}
          onUploadSigned={() => setUploadSignedOpen(true)}
          onUploadForSigning={() => setUploadForSigningOpen(true)}
        />
      )}

      {completedDocs.length > 0 && (
        <section className="rounded-lg border bg-background">
          <header className="flex items-center justify-between border-b px-4 py-2.5">
            <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
              Reservation history
            </h3>
            <span className="text-xs text-muted-foreground">
              {completedDocs.length} {completedDocs.length === 1 ? 'document' : 'documents'}
            </span>
          </header>
          <ul className="divide-y">
            {completedDocs.map((d) => (
              <li key={d.id} className="flex items-center gap-3 px-4 py-2.5 text-sm">
                <StatusBadge status={d.status} />
                <span className="flex-1 truncate font-medium">{d.title}</span>
                <span className="text-xs text-muted-foreground">
                  {new Date(d.createdAt).toLocaleDateString()}
                </span>
                {portSlug && (
                  <Link
                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
                    href={`/${portSlug}/documents/${d.id}` as any}
                    className="text-xs text-primary hover:underline inline-flex items-center gap-1"
                  >
                    Open
                    <ExternalLink className="size-3" aria-hidden />
                  </Link>
                )}
              </li>
            ))}
          </ul>
        </section>
      )}

      {/* Shared upload dialog, parameterised by docType. With
          docType="reservation" the service files the PDF as a
          reservation_agreement, sets reservationDocStatus='signed' +
          reservationSignedAt, and advances the stage to `reservation`
          (no EOI-specific banner / public-map flip). */}
      {uploadSignedOpen && (
        <ExternalEoiUploadDialog
          open={uploadSignedOpen}
          onOpenChange={setUploadSignedOpen}
          interestId={interestId}
          docType="reservation"
        />
      )}

      {/* Phase 4  -  upload-for-Documenso-signing dialog. */}
      {uploadForSigningOpen && (
        <UploadForSigningDialog
          open={uploadForSigningOpen}
          onOpenChange={setUploadForSigningOpen}
          interestId={interestId}
          documentType="reservation_agreement"
        />
      )}

      <MarkExternallySignedDialog
        open={markExternalOpen}
        onOpenChange={setMarkExternalOpen}
        interestId={interestId}
        docType="reservation"
      />
    </div>
  );
}

// ─── Active reservation hero ────────────────────────────────────────────────────

function ActiveReservationCard({
  doc,
  portSlug,
  onUploadSigned,
}: {
  doc: DocumentRow;
  portSlug: string | null;
  onUploadSigned: () => void;
}) {
  const queryClient = useQueryClient();
  const { dialog: confirmDialog } = useConfirmation();

  const { data: signersRes, isLoading: signersLoading } = useQuery<{ data: DocumentSigner[] }>({
    queryKey: ['documents', doc.id, 'signers'],
    queryFn: () => apiFetch<{ data: DocumentSigner[] }>(`/api/v1/documents/${doc.id}/signers`),
    refetchInterval: 30_000,
  });

  const signers = signersRes?.data ?? [];
  const signedCount = signers.filter((s) => s.status === 'signed').length;
  const totalCount = signers.length;
  const allSigned = totalCount > 0 && signedCount === totalCount;

  const [cancelDialogOpen, setCancelDialogOpen] = useState(false);
  const cancelMutation = useMutation({
    mutationFn: (params: { cancelMode: CancelMode; reason: string }) =>
      apiFetch(`/api/v1/documents/${doc.id}/cancel`, {
        method: 'POST',
        body: {
          cancelMode: params.cancelMode,
          ...(params.reason ? { reason: params.reason } : {}),
        },
      }),
    onSuccess: (_data, vars) => {
      queryClient.invalidateQueries({ predicate: (q) => q.queryKey[0] === 'documents' });
      toast.success(
        vars.cancelMode === 'keep_remote'
          ? 'Reservation cancelled. Envelope kept on Documenso for audit.'
          : 'Reservation cancelled.',
      );
      setCancelDialogOpen(false);
    },
    onError: (err) => toastError(err),
  });

  const remindAllMutation = useMutation({
    mutationFn: () => apiFetch(`/api/v1/documents/${doc.id}/remind`, { method: 'POST', body: {} }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['documents', doc.id, 'signers'] });
      toast.success('Reminder sent.');
    },
    onError: (err) => toastError(err),
  });

  return (
    <section className="rounded-xl border bg-gradient-brand-soft p-5 shadow-xs">
      <header className="flex items-start justify-between gap-3">
        <div className="min-w-0 flex-1 space-y-1">
          <div className="flex items-center gap-2 flex-wrap">
            <FileSignature className="size-4 text-foreground" aria-hidden />
            <h2 className="truncate text-base font-semibold text-foreground">{doc.title}</h2>
            <StatusBadge status={doc.status} />
          </div>
          <p className="text-xs text-muted-foreground">
            Created {new Date(doc.createdAt).toLocaleDateString()} ·{' '}
            {totalCount > 0 ? `${signedCount} of ${totalCount} signed` : 'No signers loaded'}
          </p>
        </div>
        <div className="flex shrink-0 items-center gap-1">
          {portSlug && (
            <Button asChild variant="outline" size="sm" className="gap-1.5 [&_svg]:size-3.5">
              <Link
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                href={`/${portSlug}/documents/${doc.id}` as any}
              >
                Open
                <ExternalLink />
              </Link>
            </Button>
          )}
          {!allSigned && (
            <Button
              variant="outline"
              size="sm"
              disabled={remindAllMutation.isPending}
              onClick={() => remindAllMutation.mutate()}
              className="gap-1.5 [&_svg]:size-3.5"
            >
              {remindAllMutation.isPending ? (
                <Loader2 className="animate-spin" aria-hidden />
              ) : (
                <RefreshCw />
              )}
              Remind all
            </Button>
          )}
        </div>
      </header>

      <div className="mt-4 rounded-lg border bg-background p-4">
        <h3 className="mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground">
          Signing progress
        </h3>
        {signersLoading ? (
          <div className="flex items-center gap-2 text-sm text-muted-foreground">
            <Loader2 className="size-3.5 animate-spin" aria-hidden /> Loading signers…
          </div>
        ) : signers.length === 0 ? (
          <p className="text-sm text-muted-foreground italic">
            The signing service hasn&apos;t reported signers yet - check back in a moment.
          </p>
        ) : (
          <SigningProgress documentId={doc.id} signers={signers} />
        )}
      </div>

      <footer className="mt-3 flex flex-wrap items-center justify-between gap-2 text-xs text-muted-foreground">
        <p className="flex items-center gap-1.5">
          <AlertTriangle className="size-3 text-amber-600" aria-hidden />
          Manual reminders are rate-limited by Documenso (max once per 7 days per signer). Automatic
          follow-ups run on the configured cadence and are not throttled by us.
        </p>
        <div className="flex items-center gap-1">
          <Button
            type="button"
            variant="ghost"
            size="sm"
            onClick={onUploadSigned}
            className="h-7 gap-1.5 text-xs [&_svg]:size-3"
          >
            <Upload />
            Upload paper-signed copy
          </Button>
          <PermissionGate resource="documents" action="edit">
            <Button
              type="button"
              variant="ghost"
              size="sm"
              disabled={cancelMutation.isPending}
              onClick={() => setCancelDialogOpen(true)}
              className="h-7 gap-1.5 text-xs text-destructive hover:text-destructive [&_svg]:size-3"
            >
              <XCircle />
              Cancel reservation
            </Button>
          </PermissionGate>
        </div>
      </footer>
      <CancelDocumentDialog
        open={cancelDialogOpen}
        onOpenChange={setCancelDialogOpen}
        documentLabel="Reservation"
        isSubmitting={cancelMutation.isPending}
        onConfirm={(params) => cancelMutation.mutate(params)}
      />
      {confirmDialog}
    </section>
  );
}

// ─── Empty state ─────────────────────────────────────────────────────────────

function EmptyReservationState({
  onUploadSigned,
  onUploadForSigning,
  onMarkExternal,
}: {
  onUploadSigned: () => void;
  onUploadForSigning: () => void;
  onMarkExternal: () => void;
}) {
  return (
    <section className="rounded-xl border border-dashed bg-muted/20 p-8 text-center">
      <div className="mx-auto flex size-14 items-center justify-center rounded-full bg-background text-muted-foreground">
        <FileSignature className="size-6" aria-hidden />
      </div>
      <h2 className="mt-4 text-base font-semibold text-foreground">
        No reservation in flight for this interest
      </h2>
      <p className="mt-1 text-sm text-muted-foreground">
        reservation agreements are drafted custom per deal. Either upload a paper-signed copy you
        handled externally, or upload the draft PDF and send for e-signing.
      </p>
      <div className="mt-5 flex flex-wrap items-center justify-center gap-2">
        <Button onClick={onUploadForSigning} size="sm" className="gap-1.5">
          <FileSignature className="size-4" aria-hidden />
          Upload draft for signing
        </Button>
        <Button onClick={onUploadSigned} variant="outline" size="sm" className="gap-1.5">
          <Upload className="size-4" aria-hidden />
          Upload paper-signed copy
        </Button>
        <Button onClick={onMarkExternal} variant="ghost" size="sm" className="gap-1.5">
          Mark as signed without file
        </Button>
      </div>
    </section>
  );
}

// ─── Helpers ─────────────────────────────────────────────────────────────────

function StatusBadge({ status }: { status: DocumentRow['status'] }) {
  return (
    <Badge
      variant="outline"
      className={cn(
        'border-transparent text-xs font-semibold uppercase tracking-wide',
        STATUS_TONES[status],
      )}
    >
      {status === 'completed' && <CheckCircle2 className="mr-1 size-3" aria-hidden />}
      {STATUS_LABELS[status]}
    </Badge>
  );
}
