'use client';

import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter, useParams } from 'next/navigation';
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 { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { ClientPicker } from '@/components/shared/client-picker';
import { YachtPicker } from '@/components/yachts/yacht-picker';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { PIPELINE_STAGES, STAGE_LABELS } from '@/components/clients/pipeline-constants';

interface CatchUpWizardProps {
  berthId: string | null;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}

type ClientMode = 'existing' | 'new';

interface BerthSummary {
  id: string;
  mooringNumber: string;
  status: string;
}

const STATUS_TO_STAGES: Record<string, readonly string[]> = {
  under_offer: ['enquiry', 'qualified', 'nurturing', 'eoi', 'reservation'],
  sold: ['contract'],
  available: PIPELINE_STAGES,
};

/**
 * #67 Phase 4: catch-up wizard for manually-statused berths.
 *
 * MVP scope (intentionally tight):
 *   - Pick existing client OR quick-create with name + email/phone
 *   - Optional yacht link
 *   - Stage picker scoped to the current berth status (sold → contract+won,
 *     under_offer → enquiry...reservation, available → any)
 *
 * Doc upload + payment recording (Phases 4.4 / 4.5 of the spec) are
 * out of scope for the initial cut — once the interest exists, the rep
 * has the standard interest detail page to upload contracts and record
 * payments. The wizard's job is to get them from "manual berth, no
 * interest" to "interest exists, override cleared" in one round-trip.
 */
export function CatchUpWizard({ berthId, open, onOpenChange }: CatchUpWizardProps) {
  const router = useRouter();
  const params = useParams<{ portSlug: string }>();
  const portSlug = params?.portSlug ?? '';
  const queryClient = useQueryClient();

  const [clientMode, setClientMode] = useState<ClientMode>('existing');
  const [clientId, setClientId] = useState<string | null>(null);
  const [newClientName, setNewClientName] = useState('');
  const [newClientEmail, setNewClientEmail] = useState('');
  const [newClientPhone, setNewClientPhone] = useState('');
  const [yachtId, setYachtId] = useState<string | null>(null);
  const [pipelineStage, setPipelineStage] = useState<string>('enquiry');

  // Fetch the berth so the wizard can scope the stage options to what
  // makes sense for the current manual status. Disabled until open so
  // closed-state hover/preview doesn't fire the request.
  const { data: berth } = useQuery<{ data: BerthSummary }>({
    queryKey: ['berth', berthId, 'catch-up-summary'],
    queryFn: () => apiFetch(`/api/v1/berths/${berthId}`),
    enabled: open && !!berthId,
  });

  const allowedStages = berth ? (STATUS_TO_STAGES[berth.data.status] ?? PIPELINE_STAGES) : [];
  // Default the stage picker to the "right" default for each status —
  // sold defaults to contract (and we auto-set outcome=won server-side),
  // under_offer defaults to eoi since that's the most common pre-deal
  // status that reps mark manually.
  const defaultStage = berth?.data.status === 'sold' ? 'contract' : 'eoi';

  // Keep selected stage in sync with the loaded berth's allowed set.
  if (berth && pipelineStage !== defaultStage && !allowedStages.includes(pipelineStage)) {
    setPipelineStage(defaultStage);
  }

  const submit = useMutation({
    mutationFn: async () => {
      if (!berthId) throw new Error('berthId missing');
      const body: Record<string, unknown> = { pipelineStage };
      if (clientMode === 'existing') {
        if (!clientId) throw new Error('Pick a client to continue');
        body.clientId = clientId;
      } else {
        if (!newClientName.trim()) throw new Error('Enter the client name');
        body.newClient = {
          fullName: newClientName.trim(),
          email: newClientEmail.trim() || undefined,
          phone: newClientPhone.trim() || undefined,
        };
      }
      if (yachtId) body.yachtId = yachtId;
      if (pipelineStage === 'contract') body.outcome = 'won';
      return apiFetch<{ data: { interestId: string; clientId: string } }>(
        `/api/v1/berths/${berthId}/reconcile`,
        { method: 'POST', body },
      );
    },
    onSuccess: (res) => {
      toast.success('Berth reconciled — new interest created');
      queryClient.invalidateQueries({ queryKey: ['berths'] });
      queryClient.invalidateQueries({ queryKey: ['berths', 'reconcile-queue'] });
      queryClient.invalidateQueries({ queryKey: ['interests'] });
      onOpenChange(false);
      if (portSlug && res.data.interestId) {
        router.push(`/${portSlug}/interests/${res.data.interestId}` as never);
      }
    },
    onError: (err) => toastError(err),
  });

  function reset() {
    setClientMode('existing');
    setClientId(null);
    setNewClientName('');
    setNewClientEmail('');
    setNewClientPhone('');
    setYachtId(null);
    setPipelineStage('enquiry');
  }

  return (
    <Dialog
      open={open}
      onOpenChange={(o) => {
        if (submit.isPending) return;
        if (!o) reset();
        onOpenChange(o);
      }}
    >
      <DialogContent className="sm:max-w-lg">
        <DialogHeader>
          <DialogTitle>Catch up berth {berth?.data.mooringNumber ?? ''}</DialogTitle>
          <DialogDescription>
            Create the backing interest so this berth drops out of the reconciliation queue. You can
            attach documents and record payments from the new interest&apos;s detail page after
            submission.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4">
          <div className="space-y-2">
            <Label>Client</Label>
            <RadioGroup
              value={clientMode}
              onValueChange={(v) => setClientMode(v as ClientMode)}
              className="flex gap-4"
            >
              <div className="flex items-center gap-2">
                <RadioGroupItem id="cu-client-existing" value="existing" />
                <Label htmlFor="cu-client-existing" className="text-sm font-normal">
                  Pick existing
                </Label>
              </div>
              <div className="flex items-center gap-2">
                <RadioGroupItem id="cu-client-new" value="new" />
                <Label htmlFor="cu-client-new" className="text-sm font-normal">
                  Quick-create
                </Label>
              </div>
            </RadioGroup>
            {clientMode === 'existing' ? (
              <ClientPicker value={clientId} onChange={setClientId} />
            ) : (
              <div className="space-y-2 rounded-md border bg-muted/30 p-3">
                <div className="space-y-1">
                  <Label className="text-xs">Full name *</Label>
                  <Input
                    value={newClientName}
                    onChange={(e) => setNewClientName(e.target.value)}
                    placeholder="John Smith"
                  />
                </div>
                <div className="grid grid-cols-1 gap-2 sm:grid-cols-2">
                  <div className="space-y-1">
                    <Label className="text-xs">Email</Label>
                    <Input
                      type="email"
                      value={newClientEmail}
                      onChange={(e) => setNewClientEmail(e.target.value)}
                      placeholder="client@example.com"
                    />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">Phone</Label>
                    <Input
                      type="tel"
                      value={newClientPhone}
                      onChange={(e) => setNewClientPhone(e.target.value)}
                      placeholder="+1 555 0100"
                    />
                  </div>
                </div>
              </div>
            )}
          </div>

          <div className="space-y-1">
            <Label>Linked yacht (optional)</Label>
            <YachtPicker
              value={yachtId}
              onChange={setYachtId}
              ownerFilter={
                clientId && clientMode === 'existing' ? { type: 'client', id: clientId } : undefined
              }
            />
          </div>

          <div className="space-y-1">
            <Label>Pipeline stage</Label>
            <Select value={pipelineStage} onValueChange={setPipelineStage}>
              <SelectTrigger>
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {allowedStages.map((s) => (
                  <SelectItem key={s} value={s}>
                    {STAGE_LABELS[s as keyof typeof STAGE_LABELS] ?? s}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            {pipelineStage === 'contract' ? (
              <p className="text-xs text-muted-foreground">
                Stage <strong>Contract</strong> auto-marks the interest <strong>Won</strong> since
                the berth is already flipped to Sold.
              </p>
            ) : null}
          </div>
        </div>

        <DialogFooter>
          <Button
            type="button"
            variant="outline"
            onClick={() => onOpenChange(false)}
            disabled={submit.isPending}
          >
            Cancel
          </Button>
          <Button type="button" onClick={() => submit.mutate()} disabled={submit.isPending}>
            {submit.isPending && <Loader2 className="mr-1.5 size-3.5 animate-spin" aria-hidden />}
            Create interest & clear manual flag
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
