'use client';

import { useEffect } from 'react';
import { useForm, useFieldArray } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Plus, Trash2, Loader2 } from 'lucide-react';

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 { TimezoneCombobox } from '@/components/shared/timezone-combobox';
import { PhoneInput } from '@/components/shared/phone-input';
import { apiFetch } from '@/lib/api/client';
import { createClientSchema, type CreateClientInput } from '@/lib/validators/clients';
import type { CountryCode } from '@/lib/i18n/countries';

interface ClientFormProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  /** 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 }: ClientFormProps) {
  const queryClient = useQueryClient();
  const isEdit = !!client;

  const {
    register,
    handleSubmit,
    control,
    watch,
    setValue,
    reset,
    formState: { errors, isSubmitting },
  } = useForm<CreateClientInput>({
    resolver: zodResolver(createClientSchema),
    defaultValues: {
      fullName: '',
      contacts: [{ channel: 'email', value: '', isPrimary: true }],
      tagIds: [],
    },
  });

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

  // 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) {
      reset({
        fullName: '',
        contacts: [{ channel: 'email', value: '', isPrimary: true }],
        tagIds: [],
      });
    }
  }, [client, open, reset]);

  const mutation = useMutation({
    mutationFn: async (data: CreateClientInput) => {
      if (isEdit) {
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        const { contacts, tagIds: tIds, ...rest } = data;
        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 },
          });
        }
      } else {
        await apiFetch('/api/v1/clients', { method: 'POST', body: data });
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['clients'] });
      onOpenChange(false);
    },
  });

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

        <form onSubmit={handleSubmit((data) => mutation.mutate(data))} className="space-y-6 py-6">
          {/* Basic Info */}
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-muted-foreground uppercase tracking-wide">
              Basic Information
            </h3>

            <div className="grid grid-cols-2 gap-4">
              <div className="col-span-2 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 className="space-y-1">
                <Label>Nationality</Label>
                <CountryCombobox
                  value={watch('nationalityIso')}
                  onChange={(iso) => setValue('nationalityIso', iso ?? undefined)}
                  data-testid="client-nationality"
                />
              </div>
            </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" />
                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="grid grid-cols-12 gap-2 items-end p-3 rounded-lg border bg-muted/30"
                >
                  <div className="col-span-3 space-y-1">
                    <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-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="col-span-5 space-y-1">
                    <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-8"
                          placeholder={channel === 'email' ? 'email@example.com' : 'value'}
                        />
                      );
                    })()}
                  </div>

                  <div className="col-span-2 space-y-1">
                    <Label className="text-xs">Label</Label>
                    <Input
                      {...register(`contacts.${index}.label`)}
                      className="h-8"
                      placeholder="work"
                    />
                  </div>

                  <div className="col-span-1 flex items-center gap-1 pb-1">
                    <Checkbox
                      checked={watch(`contacts.${index}.isPrimary`)}
                      onCheckedChange={(v) => setValue(`contacts.${index}.isPrimary`, !!v)}
                    />
                    <Label className="text-xs">Primary</Label>
                  </div>

                  <div className="col-span-1 flex justify-end pb-1">
                    {fields.length > 1 && (
                      <Button
                        type="button"
                        variant="ghost"
                        size="icon"
                        className="h-7 w-7 text-destructive"
                        onClick={() => remove(index)}
                      >
                        <Trash2 className="h-3.5 w-3.5" />
                      </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-2 gap-4">
              <div className="space-y-1">
                <Label>Source</Label>
                <Select
                  value={watch('source') ?? ''}
                  onValueChange={(v) =>
                    setValue('source', v as 'website' | 'manual' | 'referral' | 'broker')
                  }
                >
                  <SelectTrigger>
                    <SelectValue placeholder="Select source" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="website">Website</SelectItem>
                    <SelectItem value="manual">Manual</SelectItem>
                    <SelectItem value="referral">Referral</SelectItem>
                    <SelectItem value="broker">Broker</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>Preferred Language</Label>
                <Input {...register('preferredLanguage')} placeholder="English" />
              </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="col-span-2 space-y-1">
                <Label>Source Details</Label>
                <Input {...register('sourceDetails')} placeholder="Referred by John Doe" />
              </div>
            </div>
          </div>

          <Separator />

          {/* 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" />
              )}
              {isEdit ? 'Save Changes' : 'Create Client'}
            </Button>
          </SheetFooter>
        </form>
      </SheetContent>
    </Sheet>
  );
}
