import React, { useEffect, useState } from 'react';
import _ from 'lodash';
import { TrashIcon } from '@heroicons/react/outline';
import { useFieldArray, useForm, useWatch } from 'react-hook-form';
import { Banner, Modal, ConfirmationModal } from 'src/components';
import { Input, Select } from 'src/components/Form';
import { User, UserRole, useUsers } from 'src/services/users';
import { useAuth } from 'src/services/auth';
import { appAccessList, initialUserForm } from './consts';
import { UserModalProps } from './types';

export const UserModal = ({ open, onClose, userId, setUserId }: UserModalProps) => {
  const [deleteModal, setDeleteModal] = useState(false);
  const [isAdminRoleSelected, setAdminRoleSelected] = useState(true);
  const [isPersonalModal, setPersonalModal] = useState(false);
  const {
    user,
    loadUser,
    loadPersonalInfo,
    editUserById,
    editPersonalInfo,
    createNewUser,
    userModalLoading,
    deleteUserById,
    clearSelectedUser,
  } = useUsers();
  const { currentUser, isAdmin } = useAuth();

  const { control, reset, handleSubmit } = useForm<User>({
    defaultValues: initialUserForm,
  });

  const { fields, update } = useFieldArray({
    control,
    name: 'app_roles',
  });

  useEffect(() => {
    if (userId) {
      const currentUserId = currentUser?.id;
      if (currentUserId === userId) {
        setPersonalModal(true);
        loadPersonalInfo();
      } else {
        loadUser(userId);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [userId, open]);

  useEffect(() => {
    if (!_.isEmpty(user)) {
      reset(user);
    }

    return () => {
      reset(initialUserForm);
    };
  }, [user, reset, open]);

  const dashboardRole = useWatch({
    control,
    name: 'app_roles.0.role',
  });

  useEffect(() => {
    const isAdminDashboardRoleSelected = dashboardRole === UserRole.Admin;
    setAdminRoleSelected(isAdminDashboardRoleSelected);
    if (isAdminDashboardRoleSelected) {
      fields.forEach((field, index) => update(index, { name: field.name, role: UserRole.Admin }));
    } else {
      fields.forEach((field, index) => update(index, { name: field.name, role: UserRole.User }));
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [dashboardRole]);

  const handleSave = async () => {
    try {
      if (isPersonalModal) {
        await handleSubmit((data) => editPersonalInfo(data))();
      } else if (userId) {
        await handleSubmit((data) => editUserById(data))();
      } else {
        await handleSubmit((data) => createNewUser(data))();
      }
    } catch (e: any) {
      // Continue
    }

    onClose();
    clearSelectedUser();
    setUserId(null);
  };

  const handleKeyPress = (e: any) => {
    if (e.key === 'Enter' || e.key === 'NumpadEnter') {
      handleSave();
    }
  };

  const handleClose = () => {
    onClose();
    clearSelectedUser();
    setUserId(null);
  };

  const deleteModalOpen = () => setDeleteModal(true);
  const deleteModalClose = () => setDeleteModal(false);

  const handleDelete = () => {
    if (userId) {
      deleteUserById(userId);
    }

    clearSelectedUser();
    setUserId(null);
    handleClose();
    deleteModalClose();
  };

  return (
    <>
      <Modal
        onClose={handleClose}
        open={open}
        onSave={handleSave}
        isLoading={userModalLoading}
        leftActions={
          userId &&
          user.email !== currentUser?.email && (
            <button
              onClick={deleteModalOpen}
              type="button"
              className="mb-4 sm:mb-0 inline-flex items-center px-4 py-2 text-sm font-medium rounded-md text-red-700 bg-red-50 hover:bg-red-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
            >
              <TrashIcon className="-ml-0.5 mr-2 h-4 w-4" aria-hidden="true" />
              Delete
            </button>
          )
        }
        useCancelButton
      >
        <div className="bg-white px-4">
          <div className="space-y-10 divide-y divide-gray-200">
            <div>
              <div>
                <h3 className="text-lg leading-6 font-medium text-gray-900">{userId ? 'Edit user' : 'Add new user'}</h3>
              </div>

              <div className="mt-6 grid grid-cols-1 gap-y-6 gap-x-4 sm:grid-cols-6">
                <div className="sm:col-span-3">
                  <Input control={control} name="name" label="Name" onKeyPress={handleKeyPress} required={false} />
                </div>

                <div className="sm:col-span-3">
                  <Input
                    control={control}
                    name="email"
                    label="Email"
                    type="email"
                    onKeyPress={handleKeyPress}
                    required
                  />
                </div>
                {isAdmin && (
                  <>
                    <div className="sm:col-span-3">
                      {fields
                        .filter((field) => field.name === 'dashboard')
                        .map((item, index) => (
                          <Select
                            key={item.name}
                            control={control}
                            name={`app_roles.${index}.role`}
                            label="Role"
                            options={[
                              { value: UserRole.User, name: 'User' },
                              { value: UserRole.Admin, name: 'Admin' },
                            ]}
                          />
                        ))}
                    </div>
                    <div className="sm:col-span-3 opacity-40 cursor-default pointer-events-none select-none">
                      <label htmlFor="status" className="block text-sm font-medium text-gray-700">
                        Status
                      </label>
                      <div className="mt-1">
                        <select
                          id="status"
                          name="status"
                          className="shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-300 rounded-md"
                        >
                          <option>Active</option>
                          <option>Inactive</option>
                          <option>Banned</option>
                        </select>
                      </div>
                    </div>
                  </>
                )}
              </div>
            </div>

            {isAdmin && !userModalLoading && (
              <div>
                <div className="mt-8">
                  <h3 className="text-lg leading-6 font-medium text-gray-900">App Access</h3>
                </div>

                {isAdminRoleSelected && (
                  <div className="sm:col-span-6">
                    <Banner
                      title="Admin users automatically have admin-level access to all apps."
                      titleSm="Admin user"
                    />
                  </div>
                )}

                {!isAdminRoleSelected && (
                  <div>
                    <div className="flow-root mt-6">
                      <ul className="-my-5 divide-y divide-gray-200">
                        {fields.map((item, index) => {
                          if (item.name === 'dashboard') {
                            return null;
                          }

                          return (
                            <li className="py-4" key={item.name}>
                              <div className="flex items-center space-x-4">
                                <div className="flex-shrink-0 flex-1 flex items-center">
                                  <img
                                    className="h-10 w-10 rounded-md overflow-hidden"
                                    src={_.find(appAccessList, ['name', item.name!])?.image}
                                    alt={item.name ?? 'Image'}
                                  />
                                  <h3 className="ml-4 text-md leading-6 font-medium text-gray-900">
                                    {_.find(appAccessList, ['name', item.name!])?.label}
                                  </h3>
                                </div>
                                <div>
                                  <Select
                                    key={item.id}
                                    control={control}
                                    name={`app_roles.${index}.role`}
                                    disabled={isAdminRoleSelected}
                                    options={[
                                      { value: UserRole.NoAccess, name: 'No Access' },
                                      { value: UserRole.User, name: 'User' },
                                      { value: UserRole.Admin, name: 'Admin' },
                                    ]}
                                  />
                                </div>
                              </div>
                            </li>
                          );
                        })}
                      </ul>
                    </div>
                  </div>
                )}
              </div>
            )}
          </div>
        </div>
      </Modal>

      <ConfirmationModal
        onDeleteAction={handleDelete}
        open={deleteModal}
        onClose={deleteModalClose}
        title="Delete user"
        body="Are you sure you want to delete this user? All of the user data will be permanently removed. This action cannot be undone."
      />
    </>
  );
};
