import { zodResolver } from "@hookform/resolvers/zod";
import { Button, Input, useNavigate } from "@tailor-platform/app-shell";
import { useForm } from "react-hook-form";
import { useMutation, useQuery } from "urql";
import { z } from "zod";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import { graphql, type FragmentOf, readFragment } from "@/graphql";
import { useToast } from "@/hooks/use-toast";

const UnitsQuery = graphql(`
  query UnitsForEditProductForm {
    units {
      edges {
        node {
          id
          name
          symbol
        }
      }
    }
  }
`);

const UpdateProductMutation = graphql(`
  mutation UpdateProduct($id: ID!, $name: String, $description: String, $unitId: ID) {
    updateProduct(id: $id, name: $name, description: $description, unitId: $unitId) {
      id
      name
    }
  }
`);

export const EditProductFormFragment = graphql(`
  fragment EditProductForm on Product {
    id
    name
    description
    unitId
    status
  }
`);

const formSchema = z.object({
  name: z.string().min(1, "Name is required"),
  description: z.string().optional(),
  unitId: z.string().min(1, "Unit is required"),
});

type FormValues = z.infer<typeof formSchema>;

interface EditProductFormProps {
  product: FragmentOf<typeof EditProductFormFragment>;
}

export const EditProductForm = ({ product: productFragment }: EditProductFormProps) => {
  const product = readFragment(EditProductFormFragment, productFragment);
  const navigate = useNavigate();
  const toast = useToast();
  const [, updateProduct] = useMutation(UpdateProductMutation);
  const [{ data: unitsData }] = useQuery({ query: UnitsQuery });

  const units =
    unitsData?.units?.edges?.map((edge) => {
      const node = edge.node;
      return { id: node.id, label: `${node.name} (${node.symbol})` };
    }) ?? [];

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      name: product.name,
      description: product.description ?? "",
      unitId: product.unitId,
    },
  });

  const isDraft = product.status === "DRAFT";

  const onSubmit = (values: FormValues) => {
    void updateProduct(
      {
        id: product.id,
        name: values.name,
        description: values.description || undefined,
        // UoM can only be changed in DRAFT status
        unitId: isDraft && values.unitId !== product.unitId ? values.unitId : undefined,
      },
      { additionalTypenames: ["Product"] },
    ).then((result) => {
      if (result.error) {
        toast.error(result.error);
        return;
      }
      toast.success("Product updated successfully");
      void navigate("..");
    });
  };

  const onCancel = () => {
    void navigate("..");
  };

  return (
    <Form {...form}>
      <form onSubmit={(e) => void form.handleSubmit(onSubmit)(e)} className="max-w-md space-y-4">
        <FormField
          control={form.control}
          name="name"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Name</FormLabel>
              <FormControl>
                <Input placeholder="Enter product name" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="description"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Description</FormLabel>
              <FormControl>
                <Input placeholder="Enter product description (optional)" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="unitId"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Unit</FormLabel>
              <FormControl>
                <select
                  className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:opacity-50"
                  disabled={!isDraft}
                  {...field}
                >
                  <option value="">Select a unit</option>
                  {units.map((unit) => (
                    <option key={unit.id} value={unit.id}>
                      {unit.label}
                    </option>
                  ))}
                </select>
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <div className="flex gap-2">
          <Button type="submit">Save</Button>
          <Button type="button" variant="outline" onClick={onCancel}>
            Cancel
          </Button>
        </div>
      </form>
    </Form>
  );
};
