'use client';

/**
 * Shared send-document dialog (Phase 7).
 *
 * Used by:
 *   - {@link SendBerthPdfDialog} (berths/) — single berth, recipient picker.
 *   - {@link SendBrochureDialog}    (clients/, interests/) — brochure picker.
 *   - The interest "send from interest" pattern reuses both via a wrapper.
 *
 * §14.7 mitigations enforced client-side:
 *   - Recipient email is shown verbatim in the confirm step (no quick-send).
 *   - Pre-send dry-run calls /preview first; the Send button is disabled
 *     until the unresolved-tokens list is empty.
 *   - Body length capped at 50KB; char count visible.
 */

import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQuery } from '@tanstack/react-query';
import { Loader2 } from 'lucide-react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Input } from '@/components/ui/input';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';

const BODY_MAX = 50_000;

export type DocumentKind = 'berth_pdf' | 'brochure';

interface SendDocumentDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  documentKind: DocumentKind;
  /** Pre-filled recipient. Leave both blank to let the rep type one. */
  recipient: { clientId?: string; email?: string; interestId?: string };
  /** Either a berthId (for berth_pdf) or brochureId (for brochure). */
  context: { berthId?: string; brochureId?: string };
  /** Title displayed in the dialog header. */
  title: string;
  /** Short context line under the title (e.g. "Berth A1 — primary version"). */
  subtitle?: string;
  onSent?: () => void;
}

interface PreviewResponse {
  data: { html: string; markdown: string; unresolved: string[] };
}

export function SendDocumentDialog({
  open,
  onOpenChange,
  documentKind,
  recipient,
  context,
  title,
  subtitle,
  onSent,
}: SendDocumentDialogProps) {
  const [step, setStep] = useState<'compose' | 'confirm'>('compose');
  const [emailOverride, setEmailOverride] = useState(recipient.email ?? '');
  const [customBody, setCustomBody] = useState('');

  useEffect(() => {
    if (open) {
      setStep('compose');
      setEmailOverride(recipient.email ?? '');
      setCustomBody('');
    }
  }, [open, recipient.email]);

  const recipientForApi = useMemo(
    () => ({
      clientId: recipient.clientId,
      email: emailOverride || recipient.email,
      interestId: recipient.interestId,
    }),
    [recipient.clientId, recipient.email, recipient.interestId, emailOverride],
  );

  // Live preview via /api/v1/document-sends/preview. Re-runs whenever the
  // body text or recipient changes (debounce-by-react-query for free).
  const previewQuery = useQuery<PreviewResponse>({
    queryKey: [
      'document-sends-preview',
      documentKind,
      context.berthId ?? null,
      context.brochureId ?? null,
      recipientForApi.clientId ?? null,
      recipientForApi.email ?? null,
      customBody,
    ],
    queryFn: () =>
      apiFetch('/api/v1/document-sends/preview', {
        method: 'POST',
        body: {
          documentKind,
          recipient: recipientForApi,
          berthId: context.berthId,
          brochureId: context.brochureId,
          customBodyMarkdown: customBody.trim() ? customBody : undefined,
        },
      }),
    enabled: open && Boolean(recipientForApi.clientId || recipientForApi.email),
  });

  type SendResp = { data: { error?: string; deliveredAsAttachment: boolean } };
  const sendMutation = useMutation<SendResp, Error, void>({
    mutationFn: async (): Promise<SendResp> => {
      const endpoint =
        documentKind === 'berth_pdf'
          ? '/api/v1/document-sends/berth-pdf'
          : '/api/v1/document-sends/brochure';
      const body =
        documentKind === 'berth_pdf'
          ? {
              berthId: context.berthId,
              recipient: recipientForApi,
              customBodyMarkdown: customBody.trim() ? customBody : undefined,
            }
          : {
              brochureId: context.brochureId,
              recipient: recipientForApi,
              customBodyMarkdown: customBody.trim() ? customBody : undefined,
            };
      return (await apiFetch<SendResp>(endpoint, { method: 'POST', body })) as SendResp;
    },
    onSuccess: (resp) => {
      if (resp.data.error) {
        toast.error(`Send failed: ${resp.data.error}`);
      } else {
        toast.success(
          resp.data.deliveredAsAttachment
            ? 'Sent as attachment'
            : 'Sent (large file delivered as download link)',
        );
        onSent?.();
        onOpenChange(false);
      }
    },
    onError: (err) => {
      toastError(err);
    },
  });

  const unresolved = previewQuery.data?.data.unresolved ?? [];
  const previewHtml = previewQuery.data?.data.html ?? '';

  const recipientResolved = Boolean(recipientForApi.clientId || recipientForApi.email);
  const canPreview = recipientResolved;
  const canSend = step === 'confirm' && unresolved.length === 0 && !sendMutation.isPending;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-2xl">
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
          {subtitle && <DialogDescription>{subtitle}</DialogDescription>}
        </DialogHeader>

        {step === 'compose' ? (
          <div className="space-y-4">
            <div className="space-y-1">
              <Label htmlFor="ds-email">Recipient email</Label>
              <Input
                id="ds-email"
                type="email"
                value={emailOverride}
                onChange={(e) => setEmailOverride(e.target.value)}
                placeholder={recipient.email ? '' : 'recipient@example.com'}
              />
              <p className="text-xs text-muted-foreground">
                {recipient.clientId
                  ? 'Defaults to the client primary email; override here if needed.'
                  : 'Type the address you want to send to.'}
              </p>
            </div>

            <div className="space-y-1">
              <Label htmlFor="ds-body">Message body</Label>
              <Textarea
                id="ds-body"
                rows={10}
                value={customBody}
                onChange={(e) => setCustomBody(e.target.value.slice(0, BODY_MAX))}
                placeholder="Leave blank to use the port template…"
                className="font-mono text-sm"
              />
              <div className="flex items-center justify-between text-xs text-muted-foreground">
                <span>Markdown supported. Tokens like {'{{client.fullName}}'} are expanded.</span>
                <span>
                  {customBody.length} / {BODY_MAX}
                </span>
              </div>
            </div>

            {canPreview && previewQuery.isSuccess && (
              <div className="rounded border bg-muted/30 p-3">
                <p className="mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                  Preview
                </p>
                <div
                  className="prose prose-sm max-w-none"
                  dangerouslySetInnerHTML={{ __html: previewHtml }}
                />
                {unresolved.length > 0 && (
                  <p className="mt-3 rounded border border-amber-300 bg-amber-50 p-2 text-xs text-amber-900">
                    Unresolved merge fields: {unresolved.join(', ')}. Replace these before sending.
                  </p>
                )}
              </div>
            )}
            {previewQuery.isLoading && canPreview && (
              <div className="flex items-center gap-2 text-sm text-muted-foreground">
                <Loader2 className="h-4 w-4 animate-spin" /> Rendering preview…
              </div>
            )}
          </div>
        ) : (
          <div className="space-y-3">
            <div className="rounded border bg-muted/30 p-3 text-sm">
              <p>
                Sending to: <span className="font-mono">{recipientForApi.email}</span>
              </p>
              {context.berthId && <p>Document: berth PDF</p>}
              {context.brochureId !== undefined && <p>Document: brochure</p>}
            </div>
            <div
              className="prose prose-sm max-w-none rounded border p-3"
              dangerouslySetInnerHTML={{ __html: previewHtml }}
            />
            <p className="text-xs text-muted-foreground">
              The PDF file is added by the system after the body — your text won&rsquo;t override
              it.
            </p>
          </div>
        )}

        <DialogFooter className="gap-2">
          {step === 'compose' ? (
            <>
              <Button variant="outline" onClick={() => onOpenChange(false)}>
                Cancel
              </Button>
              <Button
                onClick={() => setStep('confirm')}
                disabled={!recipientResolved || unresolved.length > 0 || previewQuery.isLoading}
              >
                Review & send
              </Button>
            </>
          ) : (
            <>
              <Button variant="outline" onClick={() => setStep('compose')}>
                Back
              </Button>
              <Button onClick={() => sendMutation.mutate()} disabled={!canSend}>
                {sendMutation.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
                Confirm and send
              </Button>
            </>
          )}
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
