'use client';

import { useEffect, useState } from 'react';
import { useForm, useFieldArray } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useFormScrollToError } from '@/hooks/use-form-scroll-to-error';
import { FormErrorSummary } from '@/components/forms/form-error-summary';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Plus, Trash2, Loader2 } 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 { Sheet, SheetContent, SheetHeader, SheetTitle, SheetFooter } from '@/components/ui/sheet';
import { Checkbox } from '@/components/ui/checkbox';
import { Separator } from '@/components/ui/separator';
import { TagPicker } from '@/components/shared/tag-picker';
import { CountryCombobox } from '@/components/shared/country-combobox';
import { SubdivisionCombobox } from '@/components/shared/subdivision-combobox';
import { TimezoneCombobox } from '@/components/shared/timezone-combobox';
import { PhoneInput } from '@/components/shared/phone-input';
import { DedupSuggestionPanel } from '@/components/clients/dedup-suggestion-panel';
import { apiFetch } from '@/lib/api/client';
import type { z } from 'zod';
import { createClientSchema, type CreateClientInput } from '@/lib/validators/clients';
import { SOURCES } from '@/lib/constants';
import type { CountryCode } from '@/lib/i18n/countries';
import { primaryTimezoneFor } from '@/lib/i18n/timezones';

interface ClientFormProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  /** Optional callback fired when the dedup suggestion panel reports
   *  the user picked an existing client. The form closes; parent is
   *  responsible for navigating to the existing client's detail page
   *  or opening the create-interest dialog pre-filled with that
   *  clientId. Skipped in edit mode. */
  onUseExistingClient?: (clientId: string) => void;
  /** Optional callback fired with the newly-created client's id after a
   *  successful create. Lets a parent flow (e.g. the new-interest drawer)
   *  chain a "use the client I just created" follow-up without making the
   *  rep re-select. Not called in edit mode. */
  onCreated?: (clientId: string) => void;
  /** Optional initial values for the create flow - used by the
   *  inquiry-inbox "Convert to client" triage step (P-4.5) so the rep
   *  doesn't retype values they just read in the inbox. The
   *  `sourceInquiryId` is persisted to `clients.source_inquiry_id` on
   *  save, preserving the inquiry → client lineage for reporting. */
  prefill?: {
    fullName?: string;
    email?: string;
    phone?: string;
    source?: 'website' | 'manual' | 'referral' | 'broker' | 'other';
    sourceInquiryId?: string;
  };
  /** If provided, form is in edit mode */
  client?: {
    id: string;
    fullName: string;
    nationalityIso?: string | null;
    preferredContactMethod?: string | null;
    preferredLanguage?: string | null;
    timezone?: string | null;
    source?: string | null;
    sourceDetails?: string | null;
    contacts?: Array<{
      channel: string;
      value: string;
      valueE164?: string | null;
      valueCountry?: string | null;
      label?: string | null;
      isPrimary?: boolean;
      notes?: string | null;
    }>;
    tags?: Array<{ id: string }>;
  };
}

export function ClientForm({
  open,
  onOpenChange,
  client,
  onUseExistingClient,
  onCreated,
  prefill,
}: ClientFormProps) {
  const queryClient = useQueryClient();
  const isEdit = !!client;

  const {
    register,
    handleSubmit,
    control,
    watch,
    setValue,
    getValues,
    reset,
    formState: { errors, isSubmitting },
  } = useForm<z.input<typeof createClientSchema>, unknown, CreateClientInput>({
    resolver: zodResolver(createClientSchema),
    defaultValues: {
      fullName: '',
      contacts: [{ channel: 'email', value: '', isPrimary: true }],
      tagIds: [],
    },
  });
  // Scroll to / focus the first errored field on submit failure + show a
  // top-of-form summary banner when there are ≥2 errors. Critical on tall
  // drawers where the failing field is below the fold.
  const scrollOnError = useFormScrollToError(handleSubmit, errors);

  const { fields, append, remove } = useFieldArray({ control, name: 'contacts' });
  const tagIds = watch('tagIds') ?? [];

  // Primary-address fields. Live outside RHF because the API splits
  // client creation (`POST /api/v1/clients`) from address creation
  // (`POST /api/v1/clients/{id}/addresses`) - the address gets chained
  // after the client POST returns the new id. Edit mode uses the
  // dedicated Addresses tab; the form here is create-only.
  const [addressOpen, setAddressOpen] = useState(false);
  const [addrStreet, setAddrStreet] = useState('');
  const [addrCity, setAddrCity] = useState('');
  const [addrSubdivisionIso, setAddrSubdivisionIso] = useState<string | null>(null);
  const [addrPostal, setAddrPostal] = useState('');
  const [addrCountryIso, setAddrCountryIso] = useState<string | null>(null);

  // When the rep picks a country and no timezone is set yet, pre-fill the
  // timezone with the country's primary IANA zone. Skips when the user has
  // already chosen a zone explicitly so we never clobber a deliberate pick.
  const watchedNationality = watch('nationalityIso');
  const watchedTimezone = watch('timezone');
  useEffect(() => {
    if (!watchedNationality || watchedTimezone) return;
    const primary = primaryTimezoneFor(watchedNationality as CountryCode);
    if (primary) setValue('timezone', primary);
  }, [watchedNationality, watchedTimezone, setValue]);

  // Populate form when editing
  useEffect(() => {
    if (client && open) {
      reset({
        fullName: client.fullName,
        nationalityIso: client.nationalityIso ?? undefined,
        preferredContactMethod:
          (client.preferredContactMethod as CreateClientInput['preferredContactMethod']) ??
          undefined,
        preferredLanguage: client.preferredLanguage ?? undefined,
        timezone: client.timezone ?? undefined,
        source: (client.source as CreateClientInput['source']) ?? undefined,
        sourceDetails: client.sourceDetails ?? undefined,
        contacts:
          client.contacts && client.contacts.length > 0
            ? client.contacts.map((c) => ({
                channel: c.channel as 'email' | 'phone' | 'whatsapp' | 'other',
                value: c.value,
                valueE164: c.valueE164 ?? undefined,
                valueCountry: c.valueCountry ?? undefined,
                label: c.label ?? undefined,
                isPrimary: c.isPrimary ?? false,
                notes: c.notes ?? undefined,
              }))
            : [{ channel: 'email', value: '', isPrimary: true }],
        tagIds: client.tags?.map((t) => t.id) ?? [],
      });
    } else if (!client && open) {
      // P-4.5: when the inquiry-inbox triage flow opens the form via
      // `?create=1&prefill_*`, hydrate the initial values so the rep
      // doesn't retype data they just reviewed. `sourceInquiryId`
      // gets persisted on save (clients.source_inquiry_id column) so
      // the inquiry → client lineage survives for the conversion-
      // funnel chart.
      const contacts: CreateClientInput['contacts'] = [];
      if (prefill?.email) {
        contacts.push({ channel: 'email', value: prefill.email, isPrimary: true });
      }
      if (prefill?.phone) {
        contacts.push({
          channel: 'phone',
          value: prefill.phone,
          isPrimary: contacts.length === 0,
        });
      }
      if (contacts.length === 0) {
        contacts.push({ channel: 'email', value: '', isPrimary: true });
      }
      reset({
        fullName: prefill?.fullName ?? '',
        contacts,
        // Default a manually-created client to `source='manual'` so reps
        // don't have to remember to pick it. The inquiry-inbox triage
        // flow overrides this via `prefill.source='website'`; the global
        // command-search quick-create has no `prefill.source` and
        // therefore correctly lands on 'manual'.
        source: prefill?.source ?? 'manual',
        sourceInquiryId: prefill?.sourceInquiryId,
        tagIds: [],
      });
      setAddressOpen(false);
      setAddrStreet('');
      setAddrCity('');
      setAddrSubdivisionIso(null);
      setAddrPostal('');
      setAddrCountryIso(null);
    }
  }, [client, open, reset, prefill]);

  const mutation = useMutation({
    mutationFn: async (data: CreateClientInput) => {
      // F19: drop contact rows whose value is empty/whitespace before
      // submitting. The form pre-adds an "empty primary" contact row
      // for convenience; reps who only want to record a name shouldn't
      // be forced to either fill it or delete it.
      const cleanedContacts = (data.contacts ?? []).filter(
        (c) => typeof c.value === 'string' && c.value.trim().length > 0,
      );
      if (cleanedContacts.length === 0) {
        // The API still requires ≥1 contact. The form-level required
        // marker on the email input also fires HTML5 validation; this
        // is the fall-back if the rep wiped the value after focus.
        throw Object.assign(new Error('At least one contact is required.'), { status: 400 });
      }
      // Primary is per-channel (DB has a partial unique index on
      // (client_id, channel) WHERE is_primary). For every channel present
      // in the cleaned set, ensure exactly one row is flagged primary -
      // promote the first row of that channel if none was explicitly
      // marked, and clear duplicates so the API doesn't 409.
      const seenPrimaryByChannel = new Set<string>();
      for (const c of cleanedContacts) {
        if (c.isPrimary && !seenPrimaryByChannel.has(c.channel)) {
          seenPrimaryByChannel.add(c.channel);
        } else if (c.isPrimary) {
          // duplicate primary within the channel - clear
          c.isPrimary = false;
        }
      }
      const seenChannels = new Set<string>(cleanedContacts.map((c) => c.channel));
      for (const channel of seenChannels) {
        if (seenPrimaryByChannel.has(channel)) continue;
        const first = cleanedContacts.find((c) => c.channel === channel);
        if (first) first.isPrimary = true;
      }
      const payload: CreateClientInput = { ...data, contacts: cleanedContacts };

      if (isEdit) {
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        const { contacts, tagIds: tIds, ...rest } = payload;
        await apiFetch(`/api/v1/clients/${client!.id}`, { method: 'PATCH', body: rest });
        if (tIds) {
          await apiFetch(`/api/v1/clients/${client!.id}/tags`, {
            method: 'PUT',
            body: { tagIds: tIds },
          });
        }
        return null;
      } else {
        const res = await apiFetch<{ data: { id: string } }>('/api/v1/clients', {
          method: 'POST',
          body: payload,
        });
        // Chain the address POST when any field is filled. Address errors
        // don't unwind the client create - surface a toast warning and
        // leave the client in place so the rep can finish in the
        // Addresses tab.
        const hasAddress =
          addrStreet.trim() ||
          addrCity.trim() ||
          addrPostal.trim() ||
          addrSubdivisionIso ||
          addrCountryIso;
        if (hasAddress) {
          try {
            await apiFetch(`/api/v1/clients/${res.data.id}/addresses`, {
              method: 'POST',
              body: {
                streetAddress: addrStreet.trim() || null,
                city: addrCity.trim() || null,
                subdivisionIso: addrSubdivisionIso ?? undefined,
                postalCode: addrPostal.trim() || null,
                countryIso: addrCountryIso ?? undefined,
                isPrimary: true,
              },
            });
          } catch {
            toast.error(
              'Client created but the address could not be saved. Add it from the Addresses tab.',
            );
          }
        }
        return { id: res.data.id };
      }
    },
    onSuccess: (result) => {
      queryClient.invalidateQueries({ queryKey: ['clients'] });
      // M-U10: confirm the write landed. Without this the rep closes
      // the sheet not sure whether the create/edit actually saved.
      toast.success(isEdit ? 'Client updated' : 'Client created');
      // Parent flow gets a chance to chain off the new id (e.g. the
      // new-interest drawer auto-selects the freshly-created client).
      if (result && 'id' in result && result.id && onCreated) {
        onCreated(result.id);
      }
      onOpenChange(false);
    },
  });

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="w-full sm:max-w-2xl lg:max-w-4xl overflow-y-auto">
        <SheetHeader>
          <SheetTitle>{isEdit ? 'Edit Client' : 'New Client'}</SheetTitle>
        </SheetHeader>

        <form
          onSubmit={(e) => {
            // A4: prune empty contact rows BEFORE handleSubmit/zod runs.
            // The schema requires `value: z.string().min(1)`, so an empty
            // row (the form pre-adds one for convenience) silently fails
            // form validation with no visible error. Strip them first so
            // the rest of the validation sees only real rows.
            const current = getValues('contacts') ?? [];
            const cleaned = current.filter(
              (c) => typeof c?.value === 'string' && c.value.trim().length > 0,
            );
            if (cleaned.length !== current.length) {
              setValue('contacts', cleaned, { shouldValidate: false });
            }
            return scrollOnError((data) => mutation.mutate(data))(e);
          }}
          className="space-y-6 py-6"
        >
          <FormErrorSummary errors={errors} />
          {/* Dedup suggestion - only on the create path. Watches the
              live form values for email / phone / name and surfaces
              an existing client when one matches. The user can
              attach the new interest to that client instead of
              creating a duplicate. */}
          {!isEdit ? (
            <DedupSuggestionPanel
              email={watch('contacts')?.find((c) => c?.channel === 'email')?.value ?? null}
              phone={
                watch('contacts')?.find((c) => c?.channel === 'phone' || c?.channel === 'whatsapp')
                  ?.valueE164 ?? null
              }
              name={watch('fullName') ?? null}
              onUseExisting={(match) => {
                onUseExistingClient?.(match.clientId);
                onOpenChange(false);
              }}
            />
          ) : null}

          {/* Basic Info */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wide">
              Basic Information
            </h3>

            <div className="space-y-1">
              <Label>Full Name *</Label>
              <Input {...register('fullName')} placeholder="John Smith" />
              {errors.fullName && (
                <p className="text-xs text-destructive">{errors.fullName.message}</p>
              )}
            </div>
          </div>

          <Separator />

          {/* Contacts */}
          <div className="space-y-4">
            <div className="flex items-center justify-between">
              <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wide">
                Contacts
              </h3>
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={() => append({ channel: 'email', value: '', isPrimary: false })}
              >
                <Plus className="mr-1 h-3.5 w-3.5" aria-hidden />
                Add Contact
              </Button>
            </div>

            {errors.contacts?.root && (
              <p className="text-xs text-destructive">{errors.contacts.root.message}</p>
            )}

            <div className="space-y-3">
              {fields.map((field, index) => (
                <div key={field.id} className="space-y-3 p-3 rounded-lg border bg-muted/30">
                  <div className="grid grid-cols-1 gap-3 sm:grid-cols-12 sm:items-start sm:gap-2">
                    <div className="space-y-1 sm:col-span-3">
                      <Label className="text-xs">Channel</Label>
                      <Select
                        value={watch(`contacts.${index}.channel`)}
                        onValueChange={(v) =>
                          setValue(
                            `contacts.${index}.channel`,
                            v as 'email' | 'phone' | 'whatsapp' | 'other',
                          )
                        }
                      >
                        <SelectTrigger className="h-9 sm:h-8">
                          <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                          <SelectItem value="email">Email</SelectItem>
                          <SelectItem value="phone">Phone</SelectItem>
                          <SelectItem value="whatsapp">WhatsApp</SelectItem>
                          <SelectItem value="other">Other</SelectItem>
                        </SelectContent>
                      </Select>
                    </div>

                    <div className="space-y-1 sm:col-span-5">
                      <Label className="text-xs">Value</Label>
                      {(() => {
                        const channel = watch(`contacts.${index}.channel`);
                        if (channel === 'phone' || channel === 'whatsapp') {
                          const e164 = watch(`contacts.${index}.valueE164`) ?? null;
                          const country =
                            (watch(`contacts.${index}.valueCountry`) as CountryCode | undefined) ??
                            undefined;
                          return (
                            <PhoneInput
                              value={
                                e164 || country
                                  ? {
                                      e164: e164 ?? null,
                                      country: country ?? 'US',
                                    }
                                  : null
                              }
                              onChange={(v) => {
                                setValue(`contacts.${index}.value`, v.e164 ?? '');
                                setValue(`contacts.${index}.valueE164`, v.e164 ?? undefined);
                                setValue(`contacts.${index}.valueCountry`, v.country);
                              }}
                              data-testid={`contact-${index}-phone`}
                            />
                          );
                        }
                        return (
                          <Input
                            {...register(`contacts.${index}.value`)}
                            className="h-9 sm:h-8"
                            placeholder={channel === 'email' ? 'email@example.com' : 'value'}
                          />
                        );
                      })()}
                    </div>

                    <div className="space-y-1 sm:col-span-4">
                      <Label className="text-xs">
                        {watch(`contacts.${index}.channel`) === 'other' ? 'Specify' : 'Label'}
                      </Label>
                      <Input
                        {...register(`contacts.${index}.label`)}
                        className="h-9 sm:h-8"
                        placeholder={
                          watch(`contacts.${index}.channel`) === 'other'
                            ? 'e.g. Telegram, Signal'
                            : 'work'
                        }
                      />
                    </div>
                  </div>

                  {/* Bottom strip: Primary toggle left, delete right. Sits on
                      its own row on every breakpoint so neither control gets
                      squashed by the field columns above. */}
                  <div className="flex items-center justify-between gap-3">
                    <label className="flex items-center gap-2 text-sm cursor-pointer select-none">
                      <Checkbox
                        checked={watch(`contacts.${index}.isPrimary`)}
                        onCheckedChange={(v) => {
                          const checked = !!v;
                          const thisChannel = watch(`contacts.${index}.channel`);
                          if (checked) {
                            // Primary is per-channel - flipping this one on
                            // clears the flag on every other row sharing the
                            // same channel. (DB enforces uniqueness via a
                            // partial index, but doing it client-side avoids
                            // a surprising 409 mid-save.)
                            const all = getValues('contacts') ?? [];
                            const next = all.map((c, i) => ({
                              ...c,
                              isPrimary:
                                i === index
                                  ? true
                                  : c.channel === thisChannel
                                    ? false
                                    : !!c.isPrimary,
                            }));
                            setValue('contacts', next, { shouldDirty: true });
                          } else {
                            setValue(`contacts.${index}.isPrimary`, false, { shouldDirty: true });
                          }
                        }}
                      />
                      <span className="font-medium">
                        Primary{' '}
                        {watch(`contacts.${index}.channel`) === 'email'
                          ? 'email'
                          : watch(`contacts.${index}.channel`) === 'phone'
                            ? 'phone'
                            : watch(`contacts.${index}.channel`) === 'whatsapp'
                              ? 'WhatsApp'
                              : 'contact'}
                      </span>
                    </label>
                    {fields.length > 1 && (
                      <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        className="h-8 text-destructive hover:text-destructive"
                        onClick={() => remove(index)}
                      >
                        <Trash2 className="mr-1 h-3.5 w-3.5" aria-hidden />
                        Remove
                      </Button>
                    )}
                  </div>
                </div>
              ))}
            </div>
          </div>

          <Separator />

          {/* Source & Preferences */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wide">
              Source & Preferences
            </h3>
            <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
              <div className="space-y-1">
                <Label>Source</Label>
                <Select
                  value={watch('source') ?? ''}
                  onValueChange={(v) =>
                    setValue('source', v as 'website' | 'manual' | 'referral' | 'broker' | 'other')
                  }
                >
                  <SelectTrigger>
                    <SelectValue placeholder="Select source" />
                  </SelectTrigger>
                  <SelectContent>
                    {SOURCES.map((s) => (
                      <SelectItem key={s.value} value={s.value}>
                        {s.label}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-1">
                <Label>Preferred Contact Method</Label>
                <Select
                  value={watch('preferredContactMethod') ?? ''}
                  onValueChange={(v) =>
                    setValue('preferredContactMethod', v as 'email' | 'phone' | 'whatsapp')
                  }
                >
                  <SelectTrigger>
                    <SelectValue placeholder="Select method" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="email">Email</SelectItem>
                    <SelectItem value="phone">Phone</SelectItem>
                    <SelectItem value="whatsapp">WhatsApp</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-1">
                <Label>Country</Label>
                <CountryCombobox
                  value={watch('nationalityIso')}
                  onChange={(iso) => setValue('nationalityIso', iso ?? undefined)}
                  data-testid="client-nationality"
                />
              </div>
              <div className="space-y-1">
                <Label>Timezone</Label>
                <TimezoneCombobox
                  value={watch('timezone')}
                  onChange={(tz) => setValue('timezone', tz ?? undefined)}
                  countryHint={(watch('nationalityIso') as CountryCode | undefined) ?? undefined}
                  data-testid="client-timezone"
                />
              </div>
              <div className="sm:col-span-2 space-y-1">
                <Label>Source Details</Label>
                <Input {...register('sourceDetails')} placeholder="Referred by John Doe" />
              </div>
            </div>
          </div>

          <Separator />

          {/* Primary Address - create-only. Editing happens in the
              client detail page's Addresses tab. */}
          {!isEdit ? (
            <div className="space-y-3">
              <div className="flex items-center justify-between">
                <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wide">
                  Primary Address
                </h3>
                {!addressOpen ? (
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    onClick={() => setAddressOpen(true)}
                  >
                    <Plus className="mr-1.5 h-3.5 w-3.5" aria-hidden />
                    Add address
                  </Button>
                ) : (
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    onClick={() => {
                      setAddressOpen(false);
                      setAddrStreet('');
                      setAddrCity('');
                      setAddrSubdivisionIso(null);
                      setAddrPostal('');
                      setAddrCountryIso(null);
                    }}
                  >
                    Remove
                  </Button>
                )}
              </div>
              {addressOpen ? (
                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                  <div className="sm:col-span-2 space-y-1">
                    <Label>Street address</Label>
                    <Input
                      value={addrStreet}
                      onChange={(e) => setAddrStreet(e.target.value)}
                      placeholder="123 Marina Way, Suite 4"
                    />
                  </div>
                  <div className="space-y-1">
                    <Label>City</Label>
                    <Input
                      value={addrCity}
                      onChange={(e) => setAddrCity(e.target.value)}
                      placeholder="Anguilla"
                    />
                  </div>
                  <div className="space-y-1">
                    <Label>Postal code</Label>
                    <Input
                      value={addrPostal}
                      onChange={(e) => setAddrPostal(e.target.value)}
                      placeholder="AI-2640"
                    />
                  </div>
                  <div className="space-y-1">
                    <Label>Country</Label>
                    <CountryCombobox
                      value={addrCountryIso}
                      onChange={(iso) => {
                        setAddrCountryIso(iso ?? null);
                        // Clear region if country changes - keeps the
                        // subdivision picker consistent with its country.
                        setAddrSubdivisionIso(null);
                      }}
                    />
                  </div>
                  <div className="space-y-1">
                    <Label>Region / State</Label>
                    <SubdivisionCombobox
                      country={addrCountryIso as CountryCode | null}
                      value={addrSubdivisionIso}
                      onChange={(iso) => setAddrSubdivisionIso(iso)}
                    />
                  </div>
                </div>
              ) : null}
            </div>
          ) : null}

          {!isEdit ? <Separator /> : null}

          {/* Tags */}
          <div className="space-y-2">
            <Label>Tags</Label>
            <TagPicker selectedIds={tagIds} onChange={(ids) => setValue('tagIds', ids)} />
          </div>

          <SheetFooter>
            <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
              Cancel
            </Button>
            <Button type="submit" disabled={isSubmitting || mutation.isPending}>
              {(isSubmitting || mutation.isPending) && (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" aria-hidden />
              )}
              {isEdit ? 'Save changes' : 'Create Client'}
            </Button>
          </SheetFooter>
        </form>
      </SheetContent>
    </Sheet>
  );
}
