import React, { useEffect } from "react";

// swr
import { mutate } from "swr";
// react-hook-form
import { Controller, useFieldArray, useForm } from "react-hook-form";
// headless
import { Dialog, Transition } from "@headlessui/react";
// services
import workspaceService from "services/workspace.service";
// hooks
import useToast from "hooks/use-toast";
// ui
import { CustomSelect, Input, PrimaryButton, SecondaryButton } from "components/ui";
// icons
import { PlusIcon, XMarkIcon } from "@heroicons/react/24/outline";
// types
import { ICurrentUserResponse } from "types";
// constants
import { ROLE } from "constants/workspace";
import { WORKSPACE_INVITATIONS } from "constants/fetch-keys";

type Props = {
  isOpen: boolean;
  setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
  workspace_slug: string;
  user: ICurrentUserResponse | undefined;
  onSuccess: () => void;
};

type EmailRole = {
  email: string;
  role: 5 | 10 | 15 | 20;
};

type FormValues = {
  emails: EmailRole[];
};

const defaultValues: FormValues = {
  emails: [
    {
      email: "",
      role: 15,
    },
  ],
};

const SendWorkspaceInvitationModal: React.FC<Props> = (props) => {
  const { isOpen, setIsOpen, workspace_slug, user, onSuccess } = props;
  const {
    control,
    reset,
    handleSubmit,
    formState: { isSubmitting, errors },
  } = useForm<FormValues>();

  const { fields, append, remove } = useFieldArray({
    control,
    name: "emails",
  });

  const { setToastAlert } = useToast();

  const handleClose = () => {
    setIsOpen(false);
    const timeout = setTimeout(() => {
      reset(defaultValues);
      clearTimeout(timeout);
    }, 500);
  };

  const onSubmit = async (formData: FormValues) => {
    if (!workspace_slug) return;

    const payload = { ...formData };

    await workspaceService
      .inviteWorkspace(workspace_slug, payload, user)
      .then(async (res) => {
        setIsOpen(false);
        handleClose();
        setToastAlert({
          type: "success",
          title: "Success!",
          message: "Invitations sent successfully.",
        });
        onSuccess();
      })
      .catch((err) => {
        setToastAlert({
          type: "error",
          title: "Error!",
          message: `${err.error}`,
        });
        console.log(err);
      })
      .finally(() => {
        reset(defaultValues);
        mutate(WORKSPACE_INVITATIONS);
      });
  };

  const appendField = () => {
    append({ email: "", role: 15 });
  };

  useEffect(() => {
    if (fields.length === 0) {
      append([{ email: "", role: 15 }]);
    }
  }, [fields, append]);

  return (
    <Transition.Root show={isOpen} as={React.Fragment}>
      <Dialog as="div" className="relative z-20" onClose={handleClose}>
        <Transition.Child
          as={React.Fragment}
          enter="ease-out duration-300"
          enterFrom="opacity-0"
          enterTo="opacity-100"
          leave="ease-in duration-200"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
        >
          <div className="fixed inset-0 bg-custom-backdrop bg-opacity-50 transition-opacity" />
        </Transition.Child>

        <div className="fixed inset-0 z-20 overflow-y-auto">
          <div className="flex items-center justify-center min-h-full p-4 text-center">
            <Transition.Child
              as={React.Fragment}
              enter="ease-out duration-300"
              enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
              enterTo="opacity-100 translate-y-0 sm:scale-100"
              leave="ease-in duration-200"
              leaveFrom="opacity-100 translate-y-0 sm:scale-100"
              leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
            >
              <Dialog.Panel className="relative transform rounded-lg border border-custom-border-100 bg-custom-background-100 p-5 text-left shadow-xl transition-all sm:w-full sm:max-w-2xl opacity-100 translate-y-0 sm:scale-100">
                <form
                  onSubmit={handleSubmit(onSubmit)}
                  onKeyDown={(e) => {
                    if (e.code === "Enter") e.preventDefault();
                  }}
                >
                  <div className="space-y-5">
                    <Dialog.Title
                      as="h3"
                      className="text-lg font-medium leading-6 text-custom-text-100"
                    >
                      Invite people to collaborate
                    </Dialog.Title>
                    <div className="mt-2">
                      <p className="text-sm text-custom-text-200">
                        Invite members to work on your workspace.
                      </p>
                    </div>

                    <div className="space-y-4 mb-3">
                      {fields.map((field, index) => (
                        <div key={field.id} className="group relative grid grid-cols-11 gap-4">
                          <div className="col-span-7">
                            <Controller
                              control={control}
                              name={`emails.${index}.email`}
                              rules={{
                                required: "Email ID is required",
                                pattern: {
                                  value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                                  message: "Invalid Email ID",
                                },
                              }}
                              render={({ field }) => (
                                <>
                                  <Input
                                    {...field}
                                    className="text-xs sm:text-sm"
                                    placeholder="Enter their email..."
                                  />
                                  {errors.emails?.[index]?.email && (
                                    <span className="ml-1 text-red-500 text-xs">
                                      {errors.emails?.[index]?.email?.message}
                                    </span>
                                  )}
                                </>
                              )}
                            />
                          </div>
                          <div className="col-span-3">
                            <Controller
                              control={control}
                              name={`emails.${index}.role`}
                              rules={{ required: true }}
                              render={({ field: { value, onChange } }) => (
                                <CustomSelect
                                  value={value}
                                  label={<span className="text-xs sm:text-sm">{ROLE[value]}</span>}
                                  onChange={onChange}
                                  width="w-full"
                                  input
                                >
                                  {Object.entries(ROLE).map(([key, value]) => (
                                    <CustomSelect.Option key={key} value={parseInt(key)}>
                                      {value}
                                    </CustomSelect.Option>
                                  ))}
                                </CustomSelect>
                              )}
                            />
                          </div>
                          {fields.length > 1 && (
                            <button
                              type="button"
                              className="self-center place-items-center rounded -ml-3"
                              onClick={() => remove(index)}
                            >
                              <XMarkIcon className="h-3.5 w-3.5 text-custom-text-200" />
                            </button>
                          )}
                        </div>
                      ))}
                    </div>
                  </div>

                  <div className="mt-5 flex items-center justify-between gap-2">
                    <button
                      type="button"
                      className="flex items-center gap-2 outline-custom-primary bg-transparent text-custom-primary text-sm font-medium py-2 pr-3"
                      onClick={appendField}
                    >
                      <PlusIcon className="h-4 w-4" />
                      Add more
                    </button>
                    <div className="flex items-center gap-2">
                      <SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
                      <PrimaryButton type="submit" loading={isSubmitting}>
                        {isSubmitting ? "Sending Invitation..." : "Send Invitation"}
                      </PrimaryButton>
                    </div>
                  </div>
                </form>
              </Dialog.Panel>
            </Transition.Child>
          </div>
        </div>
      </Dialog>
    </Transition.Root>
  );
};

export default SendWorkspaceInvitationModal;