import { zodResolver } from "@hookform/resolvers/zod";
import { Button, Field, Form, useNavigate } from "@tailor-platform/app-shell";
import { Controller, useForm } from "react-hook-form";
import { useQuery, useMutation } from "urql";
import { z } from "zod";
import { ErrorFallback } from "@/components/composed/error-fallback";
import { Loading } from "@/components/composed/loading";
import { graphql } from "@/graphql";
import { useToast } from "@/hooks/use-toast";

const MeQuery = graphql(`
  query MeForEditProfile {
    me {
      id
      name
      email
    }
  }
`);

const UpdateOwnProfileMutation = graphql(`
  mutation UpdateOwnProfile($name: String!, $email: String!) {
    updateOwnProfile(name: $name, email: $email) {
      id
      name
      email
    }
  }
`);

const formSchema = z.object({
  name: z.string().min(1, "Name is required"),
  email: z.email("Invalid email address"),
});

type FormValues = z.infer<typeof formSchema>;

export const EditProfileForm = () => {
  const navigate = useNavigate();
  const toast = useToast();
  const [{ data, error, fetching }, reexecuteQuery] = useQuery({ query: MeQuery });
  const [, updateProfile] = useMutation(UpdateOwnProfileMutation);

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    values: {
      name: data?.me?.name ?? "",
      email: data?.me?.email ?? "",
    },
  });

  if (fetching) return <Loading />;

  if (error || !data?.me) {
    return (
      <ErrorFallback
        title="Failed to load profile"
        message="An error occurred while fetching your profile."
        onReset={() => reexecuteQuery({ requestPolicy: "network-only" })}
      />
    );
  }

  const onSubmit = (values: FormValues) => {
    void updateProfile(values, { additionalTypenames: ["User"] }).then((result) => {
      if (result.error) {
        toast.error(result.error);
        return;
      }
      toast.success("Profile updated successfully");
      void navigate("..");
    });
  };

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

  return (
    <Form
      noValidate
      onSubmit={(e) => void form.handleSubmit(onSubmit)(e)}
      className="max-w-md space-y-4"
    >
      <Controller
        control={form.control}
        name="name"
        render={({ field, fieldState }) => (
          <Field.Root name={field.name} invalid={fieldState.invalid}>
            <Field.Label>Name</Field.Label>
            <Field.Control placeholder="Enter name" {...field} />
            {fieldState.error && <Field.Error match>{fieldState.error.message}</Field.Error>}
          </Field.Root>
        )}
      />
      <Controller
        control={form.control}
        name="email"
        render={({ field, fieldState }) => (
          <Field.Root name={field.name} invalid={fieldState.invalid}>
            <Field.Label>Email</Field.Label>
            <Field.Control
              inputMode="email"
              autoComplete="email"
              placeholder="Enter email"
              {...field}
            />
            {fieldState.error && <Field.Error match>{fieldState.error.message}</Field.Error>}
          </Field.Root>
        )}
      />
      <div className="flex gap-2">
        <Button type="submit">Save</Button>
        <Button type="button" variant="outline" onClick={onCancel}>
          Cancel
        </Button>
      </div>
    </Form>
  );
};
