'use client';

import { useState } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';

import { useFormScrollToError } from '@/hooks/use-form-scroll-to-error';
import { FormErrorSummary } from '@/components/forms/form-error-summary';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { DatePicker } from '@/components/ui/date-picker';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetFooter } from '@/components/ui/sheet';
import { Separator } from '@/components/ui/separator';
import { Switch } from '@/components/ui/switch';
import { TagPicker } from '@/components/shared/tag-picker';
import { CurrencyInput } from '@/components/shared/currency-input';
import { CurrencySelect } from '@/components/shared/currency-select';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import type { z } from 'zod';
import { updateBerthSchema, type UpdateBerthInput } from '@/lib/validators/berths';
import {
  BERTH_AREAS,
  BERTH_BOW_FACING_OPTIONS,
  BERTH_SIDE_PONTOON_OPTIONS,
  BERTH_MOORING_TYPES,
  BERTH_CLEAT_TYPES,
  BERTH_CLEAT_CAPACITIES,
  BERTH_BOLLARD_TYPES,
  BERTH_BOLLARD_CAPACITIES,
  BERTH_ACCESS_OPTIONS,
} from '@/lib/constants';

interface BerthFormProps {
  berth: {
    id: string;
    mooringNumber: string;
    area: string | null;
    status: string;
    lengthFt: string | null;
    lengthM: string | null;
    widthFt: string | null;
    widthM: string | null;
    draftFt: string | null;
    draftM: string | null;
    widthIsMinimum: boolean | null;
    nominalBoatSize: string | null;
    nominalBoatSizeM: string | null;
    waterDepth: string | null;
    waterDepthM: string | null;
    waterDepthIsMinimum: boolean | null;
    sidePontoon: string | null;
    powerCapacity: string | null;
    voltage: string | null;
    mooringType: string | null;
    cleatType: string | null;
    cleatCapacity: string | null;
    bollardType: string | null;
    bollardCapacity: string | null;
    access: string | null;
    bowFacing: string | null;
    price: string | null;
    priceCurrency: string;
    tenureType: string;
    tenureYears: number | null;
    tenureStartDate: string | null;
    tenureEndDate: string | null;
    berthApproved: boolean | null;
    tags: Array<{ id: string; name: string; color: string }>;
  };
  open: boolean;
  onOpenChange: (open: boolean) => void;
}

/** Optional select that allows clearing back to "no value". */
function SelectOrEmpty({
  value,
  onChange,
  options,
  placeholder = 'Select…',
}: {
  value: string | undefined;
  onChange: (next: string | undefined) => void;
  options: readonly string[];
  placeholder?: string;
}) {
  const NONE = '__none';
  return (
    <Select value={value ?? NONE} onValueChange={(v) => onChange(v === NONE ? undefined : v)}>
      <SelectTrigger>
        <SelectValue placeholder={placeholder} />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value={NONE}>-</SelectItem>
        {options.map((opt) => (
          <SelectItem key={opt} value={opt}>
            {opt}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
}

export function BerthForm({ berth, open, onOpenChange }: BerthFormProps) {
  const queryClient = useQueryClient();
  const [tagIds, setTagIds] = useState<string[]>(berth.tags.map((t) => t.id));

  const numOrUndef = (v: string | null) => (v != null && v !== '' ? Number(v) : undefined);

  const {
    register,
    handleSubmit,
    setValue,
    watch,
    control,
    formState: { errors, isSubmitting },
  } = useForm<z.input<typeof updateBerthSchema>, unknown, UpdateBerthInput>({
    resolver: zodResolver(updateBerthSchema),
    defaultValues: {
      area: berth.area ?? undefined,
      lengthFt: numOrUndef(berth.lengthFt),
      lengthM: numOrUndef(berth.lengthM),
      widthFt: numOrUndef(berth.widthFt),
      widthM: numOrUndef(berth.widthM),
      draftFt: numOrUndef(berth.draftFt),
      draftM: numOrUndef(berth.draftM),
      widthIsMinimum: berth.widthIsMinimum ?? false,
      nominalBoatSize: numOrUndef(berth.nominalBoatSize),
      nominalBoatSizeM: numOrUndef(berth.nominalBoatSizeM),
      waterDepth: numOrUndef(berth.waterDepth),
      waterDepthM: numOrUndef(berth.waterDepthM),
      waterDepthIsMinimum: berth.waterDepthIsMinimum ?? false,
      sidePontoon: berth.sidePontoon ?? undefined,
      powerCapacity: numOrUndef(berth.powerCapacity),
      voltage: numOrUndef(berth.voltage),
      mooringType: berth.mooringType ?? undefined,
      cleatType: berth.cleatType ?? undefined,
      cleatCapacity: berth.cleatCapacity ?? undefined,
      bollardType: berth.bollardType ?? undefined,
      bollardCapacity: berth.bollardCapacity ?? undefined,
      access: berth.access ?? undefined,
      bowFacing: berth.bowFacing ?? undefined,
      price: numOrUndef(berth.price),
      priceCurrency: berth.priceCurrency,
      tenureType: berth.tenureType as 'permanent' | 'fixed_term',
      tenureYears: berth.tenureYears ?? undefined,
      tenureStartDate: berth.tenureStartDate ?? undefined,
      tenureEndDate: berth.tenureEndDate ?? undefined,
      berthApproved: berth.berthApproved ?? false,
    },
  });

  const tagMutation = useMutation({
    mutationFn: (ids: string[]) =>
      apiFetch(`/api/v1/berths/${berth.id}/tags`, {
        method: 'PUT',
        body: { tagIds: ids },
      }),
  });

  const scrollOnError = useFormScrollToError(handleSubmit, errors);

  async function onSubmit(data: UpdateBerthInput) {
    try {
      await apiFetch(`/api/v1/berths/${berth.id}`, {
        method: 'PATCH',
        body: data,
      });
      await tagMutation.mutateAsync(tagIds);
      queryClient.invalidateQueries({ queryKey: ['berths'] });
      queryClient.invalidateQueries({ queryKey: ['berth', berth.id] });
      toast.success('Berth updated');
      onOpenChange(false);
    } catch (err: unknown) {
      toastError(err);
    }
  }

  const tenureType = watch('tenureType');
  const area = watch('area');
  const sidePontoon = watch('sidePontoon');
  const mooringType = watch('mooringType');
  const cleatType = watch('cleatType');
  const cleatCapacity = watch('cleatCapacity');
  const bollardType = watch('bollardType');
  const bollardCapacity = watch('bollardCapacity');
  const access = watch('access');

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="w-full sm:w-[540px] sm:max-w-none overflow-y-auto">
        <SheetHeader>
          <SheetTitle>Edit Berth {berth.mooringNumber}</SheetTitle>
        </SheetHeader>

        <form onSubmit={scrollOnError(onSubmit)} className="space-y-6 py-6">
          <FormErrorSummary errors={errors} />
          {/* Basic Info */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
              Basic Info
            </h3>
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-2">
                <Label>Area</Label>
                <SelectOrEmpty
                  value={area}
                  onChange={(v) => setValue('area', v)}
                  options={BERTH_AREAS}
                />
              </div>
              <div className="space-y-2">
                <Label htmlFor="bowFacing">Bow Facing</Label>
                <SelectOrEmpty
                  value={watch('bowFacing')}
                  onChange={(v) => setValue('bowFacing', v)}
                  options={BERTH_BOW_FACING_OPTIONS}
                />
              </div>
            </div>
            <div className="flex items-center gap-2">
              <Switch
                id="berthApproved"
                checked={watch('berthApproved') ?? false}
                onCheckedChange={(v) => setValue('berthApproved', v)}
              />
              <Label htmlFor="berthApproved">Berth Approved</Label>
            </div>
          </div>

          <Separator />

          {/* Dimensions */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
              Dimensions
            </h3>
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-2">
                <Label>Length (ft)</Label>
                <Input type="number" step="0.01" {...register('lengthFt')} />
              </div>
              <div className="space-y-2">
                <Label>Length (m)</Label>
                <Input type="number" step="0.01" {...register('lengthM')} />
              </div>
              <div className="space-y-2">
                <Label>Width (ft)</Label>
                <Input type="number" step="0.01" {...register('widthFt')} />
              </div>
              <div className="space-y-2">
                <Label>Width (m)</Label>
                <Input type="number" step="0.01" {...register('widthM')} />
              </div>
              <div className="space-y-2">
                <Label>Draft (ft)</Label>
                <Input type="number" step="0.01" {...register('draftFt')} />
              </div>
              <div className="space-y-2">
                <Label>Draft (m)</Label>
                <Input type="number" step="0.01" {...register('draftM')} />
              </div>
              <div className="space-y-2">
                <Label>Nominal Boat Size (ft)</Label>
                <Input type="number" step="1" {...register('nominalBoatSize')} />
              </div>
              <div className="space-y-2">
                <Label>Nominal Boat Size (m)</Label>
                <Input type="number" step="0.01" {...register('nominalBoatSizeM')} />
              </div>
              <div className="space-y-2">
                <Label>Water Depth (ft)</Label>
                <Input type="number" step="0.01" {...register('waterDepth')} />
              </div>
              <div className="space-y-2">
                <Label>Water Depth (m)</Label>
                <Input type="number" step="0.01" {...register('waterDepthM')} />
              </div>
            </div>
            <div className="flex flex-wrap items-center gap-x-6 gap-y-2">
              <div className="flex items-center gap-2">
                <Switch
                  id="widthIsMinimum"
                  checked={watch('widthIsMinimum') ?? false}
                  onCheckedChange={(v) => setValue('widthIsMinimum', v)}
                />
                <Label htmlFor="widthIsMinimum">Width is minimum</Label>
              </div>
              <div className="flex items-center gap-2">
                <Switch
                  id="waterDepthIsMinimum"
                  checked={watch('waterDepthIsMinimum') ?? false}
                  onCheckedChange={(v) => setValue('waterDepthIsMinimum', v)}
                />
                <Label htmlFor="waterDepthIsMinimum">Water depth is minimum</Label>
              </div>
            </div>
          </div>

          <Separator />

          {/* Mooring & Hardware */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
              Mooring &amp; Hardware
            </h3>
            <div className="space-y-2">
              <Label>Side Pontoon</Label>
              <SelectOrEmpty
                value={sidePontoon}
                onChange={(v) => setValue('sidePontoon', v)}
                options={BERTH_SIDE_PONTOON_OPTIONS}
              />
            </div>
            <div className="space-y-2">
              <Label>Mooring Type</Label>
              <SelectOrEmpty
                value={mooringType}
                onChange={(v) => setValue('mooringType', v)}
                options={BERTH_MOORING_TYPES}
              />
            </div>
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-2">
                <Label>Cleat Type</Label>
                <SelectOrEmpty
                  value={cleatType}
                  onChange={(v) => setValue('cleatType', v)}
                  options={BERTH_CLEAT_TYPES}
                />
              </div>
              <div className="space-y-2">
                <Label>Cleat Capacity</Label>
                <SelectOrEmpty
                  value={cleatCapacity}
                  onChange={(v) => setValue('cleatCapacity', v)}
                  options={BERTH_CLEAT_CAPACITIES}
                />
              </div>
              <div className="space-y-2">
                <Label>Bollard Type</Label>
                <SelectOrEmpty
                  value={bollardType}
                  onChange={(v) => setValue('bollardType', v)}
                  options={BERTH_BOLLARD_TYPES}
                />
              </div>
              <div className="space-y-2">
                <Label>Bollard Capacity</Label>
                <SelectOrEmpty
                  value={bollardCapacity}
                  onChange={(v) => setValue('bollardCapacity', v)}
                  options={BERTH_BOLLARD_CAPACITIES}
                />
              </div>
            </div>
          </div>

          <Separator />

          {/* Power */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
              Power
            </h3>
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-2">
                <Label>Power Capacity (kW)</Label>
                <Input type="number" step="1" {...register('powerCapacity')} />
              </div>
              <div className="space-y-2">
                <Label>Voltage (V at 60Hz)</Label>
                <Input type="number" step="1" {...register('voltage')} />
              </div>
            </div>
          </div>

          <Separator />

          {/* Access */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
              Access
            </h3>
            <SelectOrEmpty
              value={access}
              onChange={(v) => setValue('access', v)}
              options={BERTH_ACCESS_OPTIONS}
            />
          </div>

          <Separator />

          {/* Price */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
              Price
            </h3>
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-2">
                <Label>Price</Label>
                <CurrencyInput
                  value={(watch('price') as number | null | undefined) ?? ''}
                  currency={watch('priceCurrency') ?? 'USD'}
                  onChange={(v) => setValue('price', v ?? undefined, { shouldDirty: true })}
                />
              </div>
              <div className="space-y-2">
                <Label>Currency</Label>
                <CurrencySelect
                  value={watch('priceCurrency') ?? 'USD'}
                  onValueChange={(v) => setValue('priceCurrency', v, { shouldDirty: true })}
                />
              </div>
            </div>
          </div>

          <Separator />

          {/* Tenure */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
              Tenure
            </h3>
            <div className="space-y-2">
              <Label>Tenure Type</Label>
              <Select
                value={tenureType}
                onValueChange={(v) => setValue('tenureType', v as 'permanent' | 'fixed_term')}
              >
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="permanent">Permanent</SelectItem>
                  <SelectItem value="fixed_term">Fixed Term</SelectItem>
                </SelectContent>
              </Select>
            </div>
            {tenureType === 'fixed_term' && (
              <div className="grid grid-cols-3 gap-4">
                <div className="space-y-2">
                  <Label>Years</Label>
                  <Input type="number" {...register('tenureYears')} />
                </div>
                <div className="space-y-2">
                  <Label>Start Date</Label>
                  <Controller
                    control={control}
                    name="tenureStartDate"
                    render={({ field }) => (
                      <DatePicker
                        value={field.value ?? ''}
                        onChange={(v) => field.onChange(v || undefined)}
                      />
                    )}
                  />
                </div>
                <div className="space-y-2">
                  <Label>End Date</Label>
                  <Controller
                    control={control}
                    name="tenureEndDate"
                    render={({ field }) => (
                      <DatePicker
                        value={field.value ?? ''}
                        onChange={(v) => field.onChange(v || undefined)}
                      />
                    )}
                  />
                </div>
              </div>
            )}
          </div>

          <Separator />

          {/* Tags */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
              Tags
            </h3>
            <TagPicker selectedIds={tagIds} onChange={setTagIds} />
          </div>

          <SheetFooter>
            <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
              Cancel
            </Button>
            <Button type="submit" disabled={isSubmitting}>
              {isSubmitting ? 'Saving…' : 'Save changes'}
            </Button>
          </SheetFooter>
        </form>
      </SheetContent>
    </Sheet>
  );
}
