'use client';

import { useEffect, useState } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Loader2 } from 'lucide-react';
import { toast } from 'sonner';

import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
  DialogDescription,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { DatePicker } from '@/components/ui/date-picker';
import { Textarea } from '@/components/ui/textarea';
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 { FormErrorSummary } from '@/components/forms/form-error-summary';
import { useFormScrollToError } from '@/hooks/use-form-scroll-to-error';
import { apiFetch } from '@/lib/api/client';

type TenureType = 'permanent' | 'fixed_term' | 'seasonal';

type FormValues = {
  clientId: string | null;
  yachtId: string | null;
  startDate: string; // YYYY-MM-DD
  tenureType: TenureType;
  notes?: string;
};

interface BerthReserveDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  berthId: string;
}

export function BerthReserveDialog({ open, onOpenChange, berthId }: BerthReserveDialogProps) {
  const queryClient = useQueryClient();
  const [formError, setFormError] = useState<string | null>(null);

  const {
    register,
    handleSubmit,
    watch,
    setValue,
    reset,
    control,
    formState: { errors, isSubmitting },
  } = useForm<FormValues>({
    defaultValues: {
      clientId: null,
      yachtId: null,
      startDate: new Date().toISOString().slice(0, 10),
      tenureType: 'permanent',
      notes: '',
    },
  });
  // Wraps handleSubmit so validation failures scroll the first errored
  // field into view + focus it; matters in this Dialog because the body
  // can grow past the viewport when long client/yacht lists render.
  const submitWithScroll = useFormScrollToError(handleSubmit, errors);

  useEffect(() => {
    if (open) {
      setFormError(null);
      reset({
        clientId: null,
        yachtId: null,
        startDate: new Date().toISOString().slice(0, 10),
        tenureType: 'permanent',
        notes: '',
      });
    }
  }, [open, reset]);

  const clientId = watch('clientId');
  const yachtId = watch('yachtId');
  const tenureType = watch('tenureType');

  // When client changes, clear yacht (since yacht-picker is filtered to owner=client)
  useEffect(() => {
    setValue('yachtId', null);
  }, [clientId, setValue]);

  function validate(data: FormValues): string | null {
    if (!data.clientId) return 'Please select a client';
    if (!data.yachtId) return 'Please select a yacht';
    return null;
  }

  async function createPending(data: FormValues): Promise<{ id: string }> {
    const res = await apiFetch<{ data: { id: string } }>(`/api/v1/berths/${berthId}/tenancies`, {
      method: 'POST',
      body: {
        clientId: data.clientId!,
        yachtId: data.yachtId!,
        startDate: data.startDate,
        tenureType: data.tenureType,
        notes: data.notes?.trim() || undefined,
      },
    });
    return res.data;
  }

  const createMutation = useMutation({
    mutationFn: async (data: FormValues) => {
      const err = validate(data);
      if (err) throw new Error(err);
      await createPending(data);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['berths', berthId, 'tenancies'] });
      queryClient.invalidateQueries({ queryKey: ['tenancies'] });
      toast.success('Tenancy created');
      onOpenChange(false);
    },
    onError: (err: unknown) => {
      const msg = err instanceof Error ? err.message : 'Failed to create reservation';
      setFormError(msg);
    },
  });

  const createAndActivateMutation = useMutation({
    mutationFn: async (data: FormValues) => {
      const err = validate(data);
      if (err) throw new Error(err);
      const pending = await createPending(data);
      // Immediately activate
      await apiFetch(`/api/v1/tenancies/${pending.id}`, {
        method: 'PATCH',
        body: { action: 'activate' },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['berths', berthId, 'tenancies'] });
      queryClient.invalidateQueries({ queryKey: ['tenancies'] });
      toast.success('Tenancy created and activated');
      onOpenChange(false);
    },
    onError: (err: unknown) => {
      const msg = err instanceof Error ? err.message : 'Failed to activate';
      if (/active tenancy|active reservation|conflict|409/i.test(msg)) {
        setFormError(
          'This berth already has an active tenancy. The pending record was created - activate it manually once the other tenancy ends.',
        );
      } else {
        setFormError(msg);
      }
    },
  });

  const isPending = isSubmitting || createMutation.isPending || createAndActivateMutation.isPending;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-md">
        <DialogHeader>
          <DialogTitle>Reserve this berth</DialogTitle>
          <DialogDescription>
            Create a pending reservation or activate it immediately.
          </DialogDescription>
        </DialogHeader>

        <form className="space-y-4">
          <FormErrorSummary
            errors={errors}
            labels={{ clientId: 'Client', yachtId: 'Yacht', startDate: 'Start date' }}
          />
          <div className="space-y-2">
            <Label>Client</Label>
            <ClientPicker value={clientId} onChange={(id) => setValue('clientId', id)} />
          </div>

          <div className="space-y-2">
            <Label>Yacht</Label>
            <YachtPicker
              value={yachtId}
              onChange={(id) => setValue('yachtId', id)}
              ownerFilter={clientId ? { type: 'client', id: clientId } : undefined}
              disabled={!clientId}
              placeholder={clientId ? 'Select yacht...' : 'Select a client first'}
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="startDate">Start date</Label>
            <Controller
              control={control}
              name="startDate"
              rules={{ required: true }}
              render={({ field }) => (
                <DatePicker id="startDate" value={field.value ?? ''} onChange={field.onChange} />
              )}
            />
            {errors.startDate && <p className="text-xs text-destructive">Required</p>}
          </div>

          <div className="space-y-2">
            <Label>Tenure</Label>
            <Select
              value={tenureType}
              onValueChange={(v) => setValue('tenureType', v as TenureType)}
            >
              <SelectTrigger>
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="permanent">Permanent</SelectItem>
                <SelectItem value="fixed_term">Fixed term</SelectItem>
                <SelectItem value="seasonal">Seasonal</SelectItem>
              </SelectContent>
            </Select>
          </div>

          <div className="space-y-2">
            <Label htmlFor="notes">Notes (optional)</Label>
            <Textarea id="notes" rows={2} {...register('notes')} />
          </div>

          {formError && <p className="text-sm text-destructive">{formError}</p>}

          <DialogFooter className="flex-col-reverse sm:flex-row gap-2">
            <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
              Cancel
            </Button>
            <Button
              type="button"
              variant="outline"
              disabled={isPending}
              onClick={submitWithScroll((data) => {
                setFormError(null);
                createMutation.mutate(data);
              })}
            >
              {createMutation.isPending && (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" aria-hidden />
              )}
              Create reservation
            </Button>
            <Button
              type="button"
              disabled={isPending}
              onClick={submitWithScroll((data) => {
                setFormError(null);
                createAndActivateMutation.mutate(data);
              })}
            >
              {createAndActivateMutation.isPending && (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" aria-hidden />
              )}
              Create and activate
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
