'use client';

import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import Link from 'next/link';
import { ArrowLeft, Eye, Plus, Trash2 } from 'lucide-react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { PageHeader } from '@/components/shared/page-header';
import { ClientPicker } from '@/components/shared/client-picker';
import { CompanyPicker } from '@/components/companies/company-picker';
import { YachtPicker } from '@/components/yachts/yacht-picker';
import { InterestPicker } from '@/components/interests/interest-picker';
import { DocumentTemplatePicker } from '@/components/documents/document-template-picker';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { DOCUMENT_TYPES, DOCUMENT_TYPE_LABELS } from '@/lib/constants';

// Display labels for SIGNER_ROLES - internal values stay lowercase, UI shows
// capitalized. Falls back to capitalize-first-letter for any value not in the
// explicit map.
const SIGNER_ROLE_LABELS: Record<string, string> = {
  client: 'Client',
  sales: 'Sales',
  approver: 'Approver',
  developer: 'Developer',
  other: 'Other',
};
function formatSignerRole(r: string): string {
  return SIGNER_ROLE_LABELS[r] ?? r.charAt(0).toUpperCase() + r.slice(1);
}

const SIGNER_ROLES = ['client', 'sales', 'approver', 'developer', 'other'] as const;

const SUBJECT_TYPES = [
  { key: 'interest', label: 'Interest', field: 'interestId' as const },
  { key: 'tenancy', label: 'Tenancy', field: 'tenancyId' as const },
  { key: 'client', label: 'Client', field: 'clientId' as const },
  { key: 'company', label: 'Company', field: 'companyId' as const },
  { key: 'yacht', label: 'Yacht', field: 'yachtId' as const },
] as const;

interface SignerRow {
  signerName: string;
  signerEmail: string;
  signerRole: (typeof SIGNER_ROLES)[number];
  signingOrder: number;
}

interface CreateDocumentWizardProps {
  portSlug: string;
}

export function CreateDocumentWizard({ portSlug }: CreateDocumentWizardProps) {
  const router = useRouter();

  // Wizard is generation-only — the upload branch was removed per the
  // 2026-05-26 wizard-refactor decision. Reps who want to upload a
  // finished PDF go through the New-document dropdown → "Upload & send
  // for signature" (UploadForSigningDialog) or → "Mark as signed
  // offline" (ExternalEoiUploadDialog) instead. The `pathway` state is
  // also gone: `inapp` was a dead CRM-rendered branch that no UI ever
  // surfaced as a deliberate choice; everything flows through Documenso.
  const [templateId, setTemplateId] = useState('');
  const [documentType, setDocumentType] = useState<(typeof DOCUMENT_TYPES)[number]>('eoi');
  const [title, setTitle] = useState('');
  const [notes, setNotes] = useState('');

  const [subjectType, setSubjectType] = useState<(typeof SUBJECT_TYPES)[number]['key']>('interest');
  const [subjectId, setSubjectId] = useState('');

  // Per-port template defaults keyed by documentType. Loaded once on
  // mount; whenever documentType changes (or this map lands after the
  // first paint) we auto-populate templateId so the rep doesn't have to
  // know "which template did the admin set for EOI on this port?". The
  // rep can still override via the picker — auto-fill only writes when
  // templateId is currently empty OR matches a different doc-type's
  // default (so they don't get stuck on the wrong template after
  // switching doc types).
  const [templateDefaults, setTemplateDefaults] = useState<Record<string, number | null>>({});
  useEffect(() => {
    void apiFetch<{
      data: { eoi: number | null; contract: number | null; reservation_agreement: number | null };
    }>('/api/v1/documents/template-defaults')
      .then((res) => setTemplateDefaults(res.data ?? {}))
      .catch(() => setTemplateDefaults({}));
  }, []);
  useEffect(() => {
    const fallbackId = templateDefaults[documentType];
    if (fallbackId == null) return;
    const allTemplateDefaultIds = new Set(
      Object.values(templateDefaults).filter((v): v is number => v != null),
    );
    // Set when picker is empty OR when current pick is a different
    // doc-type's default (rep switched doc types — auto-realign). This
    // is the canonical controlled-state-sync pattern: external input
    // (doc-type selection) drives a dependent field (template id)
    // whose default the rep can still override via the picker. Pure
    // useMemo derivation isn't an option because the picker also writes
    // templateId on explicit user input.

    if (!templateId || allTemplateDefaultIds.has(Number(templateId))) {
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setTemplateId(String(fallbackId));
    }
  }, [documentType, templateDefaults, templateId]);

  // Watchers picked at create-time. Each selected user gets an in-app
  // notification on every signing event (opened, signed, declined,
  // completed) once the document is created. Same surface the
  // post-creation WatchersCard exposes, but lets the rep wire it
  // upfront instead of digging into the detail page afterwards.
  const [watcherUserIds, setWatcherUserIds] = useState<string[]>([]);
  const [watcherUsers, setWatcherUsers] = useState<
    Array<{ id: string; name: string | null; email: string | null }>
  >([]);
  useEffect(() => {
    void apiFetch<{
      data: Array<{ id: string; name: string | null; email: string | null }>;
    }>('/api/v1/admin/users/picker')
      .then((res) => setWatcherUsers(res.data ?? []))
      .catch(() => setWatcherUsers([]));
  }, []);

  const [signers, setSigners] = useState<SignerRow[]>([
    { signerName: '', signerEmail: '', signerRole: 'client', signingOrder: 1 },
  ]);
  const [signingMode, setSigningMode] = useState<'sequential' | 'parallel'>('sequential');

  const [reminderMode, setReminderMode] = useState<'default' | 'override' | 'disabled'>('default');
  const [reminderDays, setReminderDays] = useState(7);

  const [submitting, setSubmitting] = useState(false);

  const subjectField = SUBJECT_TYPES.find((s) => s.key === subjectType)!.field;

  const updateSigner = (idx: number, patch: Partial<SignerRow>): void => {
    setSigners((current) => current.map((s, i) => (i === idx ? { ...s, ...patch } : s)));
  };

  const addSigner = (): void => {
    setSigners((current) => [
      ...current,
      {
        signerName: '',
        signerEmail: '',
        signerRole: 'other',
        signingOrder: current.length + 1,
      },
    ]);
  };

  const removeSigner = (idx: number): void => {
    setSigners((current) =>
      current.filter((_, i) => i !== idx).map((s, i) => ({ ...s, signingOrder: i + 1 })),
    );
  };

  const handleSubmit = async (): Promise<void> => {
    if (!title.trim()) {
      toast.error('Title is required');
      return;
    }
    if (!subjectId.trim()) {
      toast.error(`Provide a ${subjectType} id`);
      return;
    }
    if (!templateId.trim()) {
      toast.error('Pick a template');
      return;
    }
    const cleanSigners = signers.filter((s) => s.signerEmail.trim() && s.signerName.trim());

    setSubmitting(true);
    try {
      // Wizard is generation-only: source is always 'template', pathway
      // is always 'documenso-template'. The upload branch + inapp
      // pathway were removed per the 2026-05-26 wizard-refactor
      // decision. The server-side wizard route still accepts both
      // fields for backcompat with older clients; we pass the fixed
      // values explicitly so the API contract stays stable while the
      // UI surface narrows.
      const body: Record<string, unknown> = {
        source: 'template',
        pathway: 'documenso-template',
        documentType,
        title: title.trim(),
        notes: notes.trim() || undefined,
        [subjectField]: subjectId.trim(),
        signingMode,
        watchers: watcherUserIds,
        autoPlaceFields: true,
        sendImmediately: false,
        remindersDisabled: reminderMode === 'disabled',
        templateId: templateId.trim(),
      };

      if (cleanSigners.length > 0) {
        body.signers = cleanSigners;
      }

      if (reminderMode === 'override') {
        body.reminderCadenceOverride = reminderDays;
      }

      const res = await apiFetch<{ data: { id: string } }>('/api/v1/documents/wizard', {
        method: 'POST',
        body,
      });
      toast.success('Document created');
      router.push(`/${portSlug}/documents/${res.data.id}`);
    } catch (err) {
      toastError(err);
      setSubmitting(false);
    }
  };

  return (
    <div className="flex flex-col gap-4">
      <PageHeader
        title="New document"
        description="Generate, attach, and send a document for signing."
        actions={
          <Button asChild variant="outline">
            <Link href={`/${portSlug}/documents`}>
              <ArrowLeft className="mr-1.5 h-4 w-4" aria-hidden /> Back
            </Link>
          </Button>
        }
      />

      <div className="grid gap-4 lg:grid-cols-2">
        <section className="rounded-md border bg-white p-4">
          <h2 className="mb-3 text-sm font-semibold uppercase tracking-wide text-muted-foreground">
            Template
          </h2>
          <div className="flex flex-col gap-3 text-sm">
            <p className="text-xs text-muted-foreground">
              Generates a Documenso envelope from a stored template. To upload a finished PDF and
              place fields yourself, use <strong>New document</strong> -&gt; Upload &amp; send for
              signature instead. To record a paper-signed document, use{' '}
              <strong>New document</strong> -&gt; Mark as signed offline.
            </p>
            <div className="flex flex-col gap-2">
              <Label className="text-xs">Template</Label>
              <DocumentTemplatePicker
                value={templateId || null}
                onChange={(id) => setTemplateId(id ?? '')}
              />
            </div>
          </div>
        </section>

        <section className="rounded-md border bg-white p-4">
          <h2 className="mb-3 text-sm font-semibold uppercase tracking-wide text-muted-foreground">
            Document
          </h2>
          <div className="flex flex-col gap-3 text-sm">
            <div className="flex flex-col gap-2">
              <Label className="text-xs">Type</Label>
              <Select
                value={documentType}
                onValueChange={(v) => setDocumentType(v as typeof documentType)}
              >
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {DOCUMENT_TYPES.map((t) => (
                    <SelectItem key={t} value={t}>
                      {DOCUMENT_TYPE_LABELS[t]}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              {documentType === 'other' ? (
                <p className="text-xs text-muted-foreground">
                  Use the Title below to describe the document - that&apos;s how it&apos;ll appear
                  everywhere it&apos;s referenced.
                </p>
              ) : null}
            </div>
            <div className="flex flex-col gap-2">
              <Label className="text-xs">Title</Label>
              <Input value={title} onChange={(e) => setTitle(e.target.value)} />
            </div>
            <div className="flex flex-col gap-2">
              <Label className="text-xs">Internal notes</Label>
              <Input value={notes} onChange={(e) => setNotes(e.target.value)} />
            </div>
            <div className="flex flex-col gap-2">
              <Label className="text-xs">Subject</Label>
              {/* Segmented type picker — all 5 types visible at once so
                  the rep can scan and click rather than open a dropdown.
                  Picker below adapts to the chosen type. */}
              <div
                role="tablist"
                aria-label="Subject type"
                className="inline-flex flex-wrap gap-1 rounded-md border bg-muted/30 p-0.5"
              >
                {SUBJECT_TYPES.map((s) => {
                  const active = s.key === subjectType;
                  return (
                    <button
                      key={s.key}
                      type="button"
                      role="tab"
                      aria-selected={active}
                      onClick={() => {
                        setSubjectType(s.key);
                        // Reset subject id when the type changes — pickers
                        // are type-specific and old ids belong to the
                        // wrong table.
                        setSubjectId('');
                      }}
                      className={`rounded-sm px-2.5 py-1 text-xs font-medium transition-colors ${
                        active
                          ? 'bg-white text-foreground shadow-sm'
                          : 'text-muted-foreground hover:text-foreground'
                      }`}
                    >
                      {s.label}
                    </button>
                  );
                })}
              </div>
              {subjectType === 'client' ? (
                <ClientPicker value={subjectId || null} onChange={(id) => setSubjectId(id ?? '')} />
              ) : subjectType === 'company' ? (
                <CompanyPicker
                  value={subjectId || null}
                  onChange={(id) => setSubjectId(id ?? '')}
                />
              ) : subjectType === 'yacht' ? (
                <YachtPicker value={subjectId || null} onChange={(id) => setSubjectId(id ?? '')} />
              ) : subjectType === 'interest' ? (
                <InterestPicker
                  value={subjectId || null}
                  onChange={(id) => setSubjectId(id ?? '')}
                />
              ) : (
                <Input
                  value={subjectId}
                  onChange={(e) => setSubjectId(e.target.value)}
                  placeholder="Tenancy id"
                />
              )}
            </div>
          </div>
        </section>

        <section className="rounded-md border bg-white p-4 lg:col-span-2">
          <div className="mb-3 flex items-center justify-between">
            <h2 className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
              Signers
            </h2>
            <Button size="sm" variant="outline" onClick={addSigner}>
              <Plus className="mr-1.5 h-3.5 w-3.5" aria-hidden /> Add signer
            </Button>
          </div>
          <ul className="space-y-2">
            {signers.map((s, idx) => (
              <li
                key={idx}
                className="grid grid-cols-[2.5rem_1fr_1fr_8rem_2rem] items-center gap-2 text-sm"
              >
                <span className="text-xs tabular-nums text-muted-foreground">
                  #{s.signingOrder}
                </span>
                <Input
                  value={s.signerName}
                  onChange={(e) => updateSigner(idx, { signerName: e.target.value })}
                  placeholder="Name"
                />
                <Input
                  value={s.signerEmail}
                  onChange={(e) => updateSigner(idx, { signerEmail: e.target.value })}
                  placeholder="Email"
                />
                <Select
                  value={s.signerRole}
                  onValueChange={(v) =>
                    updateSigner(idx, { signerRole: v as SignerRow['signerRole'] })
                  }
                >
                  <SelectTrigger className="h-9">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    {SIGNER_ROLES.map((r) => (
                      <SelectItem key={r} value={r}>
                        {formatSignerRole(r)}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <button
                  type="button"
                  aria-label="Remove signer"
                  onClick={() => removeSigner(idx)}
                  className="text-muted-foreground hover:text-destructive"
                >
                  <Trash2 className="h-3.5 w-3.5" aria-hidden />
                </button>
              </li>
            ))}
          </ul>
          <div className="mt-3 flex items-center gap-3 text-xs text-muted-foreground">
            <Label className="text-xs">Signing mode</Label>
            <Select
              value={signingMode}
              onValueChange={(v) => setSigningMode(v as typeof signingMode)}
            >
              <SelectTrigger className="w-40">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="sequential">Sequential</SelectItem>
                <SelectItem value="parallel">Parallel</SelectItem>
              </SelectContent>
            </Select>
          </div>
        </section>

        <section className="rounded-md border bg-white p-4 lg:col-span-2">
          <h2 className="mb-3 flex items-center gap-1.5 text-sm font-semibold uppercase tracking-wide text-muted-foreground">
            <Eye className="size-3.5" aria-hidden />
            Watchers
          </h2>
          <p className="mb-2 text-xs text-muted-foreground">
            Selected users receive an in-app notification on every signing event (opened, signed,
            declined, completed). Can be edited from the document detail page after creation.
          </p>
          {watcherUsers.length === 0 ? (
            <p className="text-xs italic text-muted-foreground">No users available to add.</p>
          ) : (
            <div className="grid grid-cols-1 gap-1 sm:grid-cols-2">
              {watcherUsers.map((u) => {
                const checked = watcherUserIds.includes(u.id);
                return (
                  <label
                    key={u.id}
                    className="flex cursor-pointer items-center gap-2 rounded-sm px-1 py-0.5 text-sm hover:bg-muted/50"
                  >
                    <input
                      type="checkbox"
                      checked={checked}
                      onChange={() =>
                        setWatcherUserIds((prev) =>
                          checked ? prev.filter((id) => id !== u.id) : [...prev, u.id],
                        )
                      }
                    />
                    <span className="truncate">
                      {u.name ?? u.email ?? `User ${u.id.slice(0, 8)}…`}
                    </span>
                  </label>
                );
              })}
            </div>
          )}
        </section>

        <section className="rounded-md border bg-white p-4 lg:col-span-2">
          <h2 className="mb-3 text-sm font-semibold uppercase tracking-wide text-muted-foreground">
            Reminders
          </h2>
          <div className="flex flex-col gap-2 text-sm">
            <label className="flex items-center gap-2">
              <input
                type="radio"
                checked={reminderMode === 'default'}
                onChange={() => setReminderMode('default')}
              />
              Use template default
            </label>
            <label className="flex items-center gap-2">
              <input
                type="radio"
                checked={reminderMode === 'override'}
                onChange={() => setReminderMode('override')}
              />
              Override:
              <Input
                type="number"
                className="ml-1 w-20"
                min={1}
                max={365}
                value={reminderDays}
                onChange={(e) => setReminderDays(Number(e.target.value))}
                onFocus={() => setReminderMode('override')}
              />
              days
            </label>
            <label className="flex items-center gap-2">
              <input
                type="radio"
                checked={reminderMode === 'disabled'}
                onChange={() => setReminderMode('disabled')}
              />
              Disable reminders for this document
            </label>
          </div>
        </section>
      </div>

      <div className="flex items-center justify-end gap-2">
        <Button variant="outline" asChild>
          <Link href={`/${portSlug}/documents`}>Cancel</Link>
        </Button>
        <Button onClick={handleSubmit} disabled={submitting}>
          {submitting ? 'Creating…' : 'Create document'}
        </Button>
      </div>
    </div>
  );
}
