'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,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} 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 { BerthPicker } from '@/components/shared/berth-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 = {
  berthId: string | null;
  clientId: string | null;
  yachtId: string | null;
  startDate: string;
  tenureType: TenureType;
  notes?: string;
};

interface TenancyCreateDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  /** Entry-point context — whichever of these is set pre-fills the
   *  corresponding picker. The other pickers stay enabled so the rep
   *  can pick the remaining fields. Exactly one is typically set:
   *  berthId from the Berth Tenancies tab, clientId from the Client
   *  Tenancies tab, yachtId from the Yacht Tenancies tab. */
  berthId?: string;
  clientId?: string;
  yachtId?: string;
}

/**
 * Generic create-tenancy dialog. Accepts optional pre-fills for berth /
 * client / yacht so it can be opened from any of the three entity tab
 * surfaces. POSTs to /api/v1/tenancies (the generic endpoint added in
 * the P6 follow-up).
 */
export function TenancyCreateDialog({
  open,
  onOpenChange,
  berthId: initialBerthId,
  clientId: initialClientId,
  yachtId: initialYachtId,
}: TenancyCreateDialogProps) {
  const queryClient = useQueryClient();
  const [formError, setFormError] = useState<string | null>(null);

  const {
    register,
    handleSubmit,
    watch,
    setValue,
    reset,
    control,
    formState: { errors, isSubmitting },
  } = useForm<FormValues>({
    defaultValues: {
      berthId: initialBerthId ?? null,
      clientId: initialClientId ?? null,
      yachtId: initialYachtId ?? null,
      startDate: new Date().toISOString().slice(0, 10),
      tenureType: 'permanent',
      notes: '',
    },
  });
  const submitWithScroll = useFormScrollToError(handleSubmit, errors);

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

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

  // When client changes, clear yacht (since yacht-picker is filtered by
  // owner). Stays unwired when the dialog opened from the yacht tab
  // (initialYachtId pre-fills both yacht + the implicit client).
  useEffect(() => {
    if (!initialYachtId) setValue('yachtId', null);
  }, [clientId, setValue, initialYachtId]);

  function validate(data: FormValues): string | null {
    if (!data.berthId) return 'Please select a berth';
    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/tenancies', {
      method: 'POST',
      body: {
        berthId: data.berthId!,
        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: ['tenancies'] });
      queryClient.invalidateQueries({ queryKey: ['berths', berthId, 'tenancies'] });
      if (initialClientId)
        queryClient.invalidateQueries({ queryKey: ['clients', initialClientId] });
      if (initialYachtId)
        queryClient.invalidateQueries({ queryKey: ['tenancies', 'by-yacht', initialYachtId] });
      toast.success('Tenancy created');
      onOpenChange(false);
    },
    onError: (err: unknown) => {
      const msg = err instanceof Error ? err.message : 'Failed to create tenancy';
      setFormError(msg);
    },
  });

  const createAndActivateMutation = useMutation({
    mutationFn: async (data: FormValues) => {
      const err = validate(data);
      if (err) throw new Error(err);
      const pending = await createPending(data);
      await apiFetch(`/api/v1/tenancies/${pending.id}`, {
        method: 'PATCH',
        body: { action: 'activate' },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['tenancies'] });
      queryClient.invalidateQueries({ queryKey: ['berths', berthId, 'tenancies'] });
      if (initialClientId)
        queryClient.invalidateQueries({ queryKey: ['clients', initialClientId] });
      if (initialYachtId)
        queryClient.invalidateQueries({ queryKey: ['tenancies', 'by-yacht', initialYachtId] });
      toast.success('Tenancy created and activated');
      onOpenChange(false);
    },
    onError: (err: unknown) => {
      const msg = err instanceof Error ? err.message : 'Failed to activate';
      if (/active tenancy|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>Create tenancy</DialogTitle>
          <DialogDescription>
            Create a pending tenancy or activate it immediately.
          </DialogDescription>
        </DialogHeader>

        <form className="space-y-4">
          <FormErrorSummary
            errors={errors}
            labels={{
              berthId: 'Berth',
              clientId: 'Client',
              yachtId: 'Yacht',
              startDate: 'Start date',
            }}
          />

          {!initialBerthId ? (
            <div className="space-y-2">
              <Label>Berth</Label>
              <BerthPicker value={berthId} onChange={(id) => setValue('berthId', id)} />
            </div>
          ) : null}

          {!initialClientId ? (
            <div className="space-y-2">
              <Label>Client</Label>
              <ClientPicker value={clientId} onChange={(id) => setValue('clientId', id)} />
            </div>
          ) : null}

          {!initialYachtId ? (
            <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 && !initialClientId}
                placeholder={
                  clientId || initialClientId ? 'Select yacht...' : 'Select a client first'
                }
              />
            </div>
          ) : null}

          <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 tenancy
            </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>
  );
}
