import { useCallback, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { graphql, useMutation } from "react-relay";

import {
  Alert,
  Button,
  Dialog,
  DialogCloseButton,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTitleExtra,
  FieldError,
  Flex,
  Form,
  Input,
  Label,
  Text,
  TextField,
  View,
} from "@phoenix/components";
import { useNotifySuccess } from "@phoenix/contexts";

import type { ResetPasswordDialogMutation } from "./__generated__/ResetPasswordDialogMutation.graphql";

const MIN_PASSWORD_LENGTH = 4;

export type ResetPasswordFormParams = {
  newPassword: string;
  confirmPassword: string;
};

export function ResetPasswordDialog({
  userId,
  onClose,
}: {
  userId: string;
  onClose: () => void;
}) {
  const notifySuccess = useNotifySuccess();
  const [error, setError] = useState<string | null>(null);
  const [commit, isCommitting] = useMutation<ResetPasswordDialogMutation>(
    graphql`
      mutation ResetPasswordDialogMutation($input: PatchUserInput!) {
        patchUser(input: $input) {
          __typename
        }
      }
    `
  );
  const {
    control,
    handleSubmit,
    formState: { isDirty },
  } = useForm<ResetPasswordFormParams>({
    defaultValues: {
      newPassword: "",
      confirmPassword: "",
    },
  });

  const onSubmit = useCallback(
    (data: ResetPasswordFormParams) => {
      commit({
        variables: {
          input: {
            userId,
            newPassword: data.newPassword,
          },
        },
        onCompleted: () => {
          notifySuccess({
            title: "Password reset",
            message: "Users password has been reset.",
          });
          onClose();
        },
        onError: (error) => {
          setError(error.message);
        },
      });
    },
    [commit, notifySuccess, onClose, userId]
  );

  return (
    <Dialog>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Reset Password</DialogTitle>
          <DialogTitleExtra>
            <DialogCloseButton onPress={onClose} slot="close" />
          </DialogTitleExtra>
        </DialogHeader>
        {error && <Alert variant="danger">{error}</Alert>}
        <Form>
          <View padding="size-200">
            <Flex direction="column" gap="size-100">
              <Controller
                name="newPassword"
                control={control}
                rules={{
                  required: "Password is required",
                  minLength: {
                    value: MIN_PASSWORD_LENGTH,
                    message: `Password must be at least ${MIN_PASSWORD_LENGTH} characters`,
                  },
                }}
                render={({
                  field: { name, onChange, onBlur, value },
                  fieldState: { invalid, error },
                }) => (
                  <TextField
                    isInvalid={invalid}
                    onChange={onChange}
                    name={name}
                    onBlur={onBlur}
                    value={value.toString()}
                    type="password"
                    id="new-password"
                    autoComplete="new-password"
                  >
                    <Label>New Password</Label>
                    <Input placeholder="New password" />
                    {error?.message ? (
                      <FieldError>{error.message}</FieldError>
                    ) : (
                      <Text slot="description">
                        Password must be at least {MIN_PASSWORD_LENGTH}{" "}
                        characters
                      </Text>
                    )}
                  </TextField>
                )}
              />
              <Controller
                name="confirmPassword"
                control={control}
                rules={{
                  required: "Password is required",
                  minLength: {
                    value: MIN_PASSWORD_LENGTH,
                    message: `Password must be at least ${MIN_PASSWORD_LENGTH} characters`,
                  },
                  validate: (value, formValues) =>
                    value === formValues.newPassword ||
                    "Passwords do not match",
                }}
                render={({
                  field: { name, onChange, onBlur, value },
                  fieldState: { invalid, error },
                }) => (
                  <TextField
                    isInvalid={invalid}
                    onChange={onChange}
                    name={name}
                    onBlur={onBlur}
                    value={value.toString()}
                    type="password"
                  >
                    <Label>Confirm Password</Label>
                    <Input placeholder="Repeat new password" />
                    {error?.message ? (
                      <FieldError>{error.message}</FieldError>
                    ) : (
                      <Text slot="description">
                        Repeat new password to confirm
                      </Text>
                    )}
                  </TextField>
                )}
              />
            </Flex>
            <View paddingTop="size-200">
              <Flex direction="row" gap="size-100" justifyContent="end">
                <Button
                  variant="default"
                  size="S"
                  onPress={onClose}
                  isDisabled={isCommitting}
                >
                  Cancel
                </Button>
                <Button
                  variant={isDirty ? "primary" : "default"}
                  type="submit"
                  isDisabled={isCommitting}
                  onPress={() => handleSubmit(onSubmit)()}
                >
                  {isCommitting ? "Resetting..." : "Reset Password"}
                </Button>
              </Flex>
            </View>
          </View>
        </Form>
      </DialogContent>
    </Dialog>
  );
}
