import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { z } from 'zod';
import { Loader2 } from 'lucide-react';
import { toast } from 'sonner';
import {
  Button,
  Checkbox,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
  Skeleton,
  Textarea,
} from '@vector/ui';
import { createFm } from '../../lib/api/fms.js';
import { listHosts, listHostDeployedParts } from '../../lib/api/hosts.js';
import { ApiRequestError } from '../../lib/api/client.js';
import { queryKeys } from '../../lib/queryKeys.js';
import type { Fm } from '../../lib/api/types.js';

const CreateSchema = z.object({
  hostId: z.string().uuid('Pick a host'),
  problem: z.string().trim().min(1, 'Describe the problem').max(2000),
  problemPartIds: z.array(z.string().uuid()).max(100),
});
type CreateValues = z.infer<typeof CreateSchema>;

interface FmFormDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  defaultHostId?: string;
  defaultProblemPartIds?: string[];
  onCreated?: (fm: Fm) => void;
}

export function FmFormDialog({
  open,
  onOpenChange,
  defaultHostId,
  defaultProblemPartIds,
  onCreated,
}: FmFormDialogProps) {
  const queryClient = useQueryClient();

  const hostsQuery = useQuery({
    queryKey: queryKeys.hosts.list({ pageSize: 100 }),
    queryFn: () => listHosts({ pageSize: 100 }),
    enabled: open,
  });

  const form = useForm<CreateValues>({
    resolver: zodResolver(CreateSchema),
    defaultValues: { hostId: '', problem: '', problemPartIds: [] },
  });

  useEffect(() => {
    if (!open) return;
    form.reset({
      hostId: defaultHostId ?? '',
      problem: '',
      problemPartIds: defaultProblemPartIds ?? [],
    });
  }, [open, defaultHostId, defaultProblemPartIds, form]);

  const hostId = form.watch('hostId');
  const selectedPartIds = form.watch('problemPartIds');
  const deployedQuery = useQuery({
    queryKey: queryKeys.hosts.deployedParts(hostId),
    queryFn: () => listHostDeployedParts(hostId),
    enabled: open && Boolean(hostId),
  });

  const createMutation = useMutation({
    mutationFn: async (values: CreateValues) =>
      createFm({
        hostId: values.hostId,
        problem: values.problem,
        problemPartIds:
          values.problemPartIds.length > 0 ? values.problemPartIds : undefined,
      }),
    onSuccess: (fm) => {
      toast.success('FM opened');
      queryClient.invalidateQueries({ queryKey: queryKeys.fms.all });
      queryClient.invalidateQueries({ queryKey: queryKeys.parts.all });
      onOpenChange(false);
      onCreated?.(fm);
    },
    onError: (err) =>
      toast.error(err instanceof ApiRequestError ? err.body.message : 'Save failed'),
  });

  const pending = createMutation.isPending;

  function togglePart(partId: string, checked: boolean) {
    const next = checked
      ? [...new Set([...selectedPartIds, partId])]
      : selectedPartIds.filter((id) => id !== partId);
    form.setValue('problemPartIds', next, { shouldValidate: true, shouldDirty: true });
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-lg">
        <DialogHeader>
          <DialogTitle>Open FM</DialogTitle>
          <DialogDescription>
            Open a Future Maintenance item against a host. Select deployed parts involved (optional).
          </DialogDescription>
        </DialogHeader>

        <Form {...form}>
          <form
            onSubmit={form.handleSubmit((v) => createMutation.mutate(v))}
            className="space-y-3"
          >
            <FormField
              control={form.control}
              name="hostId"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Host</FormLabel>
                  <Select
                    onValueChange={(v) => {
                      field.onChange(v);
                      form.setValue('problemPartIds', [], { shouldValidate: false });
                    }}
                    value={field.value}
                  >
                    <FormControl>
                      <SelectTrigger>
                        <SelectValue placeholder="Select host" />
                      </SelectTrigger>
                    </FormControl>
                    <SelectContent>
                      {hostsQuery.data?.data.map((h) => (
                        <SelectItem key={h.id} value={h.id}>
                          {h.assetId} — {h.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <FormMessage />
                </FormItem>
              )}
            />

            <FormField
              control={form.control}
              name="problem"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Problem</FormLabel>
                  <FormControl>
                    <Textarea
                      rows={3}
                      placeholder="Short description of what's wrong."
                      {...field}
                    />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />

            {hostId && (
              <FormField
                control={form.control}
                name="problemPartIds"
                render={() => (
                  <FormItem>
                    <FormLabel>Affected parts (optional)</FormLabel>
                    <FormDescription>
                      Select deployed parts involved in this problem.
                    </FormDescription>
                    <div className="max-h-40 overflow-y-auto rounded-md border border-border">
                      {deployedQuery.isPending ? (
                        <Skeleton className="m-2 h-12" />
                      ) : !deployedQuery.data || deployedQuery.data.length === 0 ? (
                        <p className="p-3 text-xs text-muted-foreground">
                          No deployed parts on this host.
                        </p>
                      ) : (
                        <ul className="divide-y divide-border">
                          {deployedQuery.data.map((part) => {
                            const checked = selectedPartIds.includes(part.id);
                            return (
                              <li
                                key={part.id}
                                className="flex items-center gap-2 px-3 py-2 text-sm"
                              >
                                <Checkbox
                                  id={`pp-${part.id}`}
                                  checked={checked}
                                  onCheckedChange={(v) => togglePart(part.id, v === true)}
                                />
                                <label
                                  htmlFor={`pp-${part.id}`}
                                  className="flex-1 cursor-pointer select-none"
                                >
                                  <span className="font-mono text-xs">{part.serialNumber}</span>{' '}
                                  <span className="text-xs text-muted-foreground">
                                    {part.partModel.mpn}
                                  </span>
                                </label>
                              </li>
                            );
                          })}
                        </ul>
                      )}
                    </div>
                    <FormMessage />
                  </FormItem>
                )}
              />
            )}

            <DialogFooter>
              <Button
                type="button"
                variant="outline"
                onClick={() => onOpenChange(false)}
                disabled={pending}
              >
                Cancel
              </Button>
              <Button type="submit" disabled={pending}>
                {pending && <Loader2 className="h-4 w-4 animate-spin" />}
                Open FM
              </Button>
            </DialogFooter>
          </form>
        </Form>
      </DialogContent>
    </Dialog>
  );
}
