import { AppDispatch } from "app/store";
import React, { useCallback, useEffect, useState } from "react";
import Header from "components/header";
import Footer from "components/footer";
import styles from "styles/app.module.scss";
import { useDispatch, useSelector } from "react-redux";
import {
  listUsersAsync,
  selectUserViews,
  selectIsLoading,
  deallocateLicenseAsync,
  deleteUserAsync,
  confirmUserForceAsync,
} from "features/user";
import { useTranslation } from "react-i18next";
import { getTranslationID } from "translation";
import { UserView } from "features/user/types";
import { LICENSE_STATUS } from "features/user/constants";
import { isApproveTier } from "features/auth";
import { TIERS, USER_ROLES } from "components/auth/constants";
import {
  changeUpdateUser,
  changeLicenseAllocateUser,
} from "features/user/userSlice";
import { DelegationBar } from "components/delegate";
import { selectDelegationAccessToken } from "features/auth/selectors";
import personAdd from "../../assets/images/person_add.svg";
import checkFill from "../../assets/images/check_fill.svg";
import checkOutline from "../../assets/images/check_outline.svg";
import progress_activit from "../../assets/images/progress_activit.svg";
import upload from "../../assets/images/upload.svg";
import searchIcon from "../../assets/images/search.svg";
import { UserAddPopup } from "./popup";
import { UserUpdatePopup } from "./updatePopup";
import { AllocateLicensePopup } from "./allocateLicensePopup";
import { ImportPopup } from "./importPopup";

const UserListPage: React.FC = (): JSX.Element => {
  const dispatch: AppDispatch = useDispatch();
  const [t] = useTranslation();
  // 代行操作用のトークンを取得する
  const delegationAccessToken = useSelector(selectDelegationAccessToken);

  const [isPopupOpen, setIsPopupOpen] = useState(false);
  const [isUpdatePopupOpen, setIsUpdatePopupOpen] = useState(false);
  const [isAllocateLicensePopupOpen, setIsAllocateLicensePopupOpen] =
    useState(false);
  const [isImportPopupOpen, setIsImportPopupOpen] = useState(false);
  const [searchEmail, setSearchEmail] = useState("");
  const [searchUserName, setSearchUserName] = useState("");

  const onOpen = useCallback(() => {
    setIsPopupOpen(true);
  }, [setIsPopupOpen]);

  const onUpdateOpen = useCallback(
    (id: number) => {
      setIsUpdatePopupOpen(true);
      dispatch(changeUpdateUser({ id }));
    },
    [setIsUpdatePopupOpen, dispatch]
  );

  const onAllocateLicensePopupOpen = useCallback(
    (selectedUser: UserView) => {
      setIsAllocateLicensePopupOpen(true);
      dispatch(changeLicenseAllocateUser({ selectedUser }));
    },
    [setIsAllocateLicensePopupOpen, dispatch]
  );
  const onImportPopupOpen = useCallback(() => {
    setIsImportPopupOpen(true);
  }, [setIsImportPopupOpen]);

  const onLicenseDeallocation = useCallback(
    async (userId: number) => {
      // ダイアログ確認
      if (
        /* eslint-disable-next-line no-alert */
        !window.confirm(t(getTranslationID("common.message.dialogConfirm")))
      ) {
        return;
      }

      const { meta } = await dispatch(deallocateLicenseAsync({ userId }));
      if (meta.requestStatus === "fulfilled") {
        clearUserSearchInputs();
        dispatch(listUsersAsync());
      }
    },
    [dispatch, t]
  );

  const onDeleteUser = useCallback(
    async (userId: number) => {
      // ダイアログ確認
      if (
        /* eslint-disable-next-line no-alert */
        !window.confirm(t(getTranslationID("common.message.dialogConfirm")))
      ) {
        return;
      }

      const { meta } = await dispatch(deleteUserAsync({ userId }));
      if (meta.requestStatus === "fulfilled") {
        clearUserSearchInputs();
        dispatch(listUsersAsync());
      }
    },
    [dispatch, t]
  );

  const onForceEmailVerification = useCallback(
    async (userId: number) => {
      // ダイアログ確認
      if (
        /* eslint-disable-next-line no-alert */
        !window.confirm(
          t(
            getTranslationID(
              "userListPage.message.forceEmailVerificationConfirm"
            )
          )
        )
      ) {
        return;
      }

      const { meta } = await dispatch(confirmUserForceAsync({ userId }));
      if (meta.requestStatus === "fulfilled") {
        clearUserSearchInputs();
        dispatch(listUsersAsync());
      }
    },
    [dispatch, t]
  );

  const requestSearch = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    dispatch(
      listUsersAsync({
        userInputUserName: searchUserName,
        userInputEmail: searchEmail,
      })
    );
  };

  const clearUserSearchInputs = useCallback(() => {
    setSearchEmail("");
    setSearchUserName("");
  }, [setSearchEmail, setSearchUserName]);

  useEffect(() => {
    // ユーザ一覧取得処理を呼び出す
    dispatch(listUsersAsync());
  }, [dispatch]);

  const users = useSelector(selectUserViews);
  const isLoading = useSelector(selectIsLoading);
  // ユーザーが第5階層であるかどうかを判定する（代行操作中は第5階層として扱う）
  const isTier5 =
    isApproveTier([TIERS.TIER5]) || delegationAccessToken !== null;

  const getUserRole = (userRole: string): string => {
    switch (userRole) {
      case USER_ROLES.AUTHOR:
        return t(getTranslationID("userListPage.label.author"));
      case USER_ROLES.TYPIST:
        return t(getTranslationID("userListPage.label.transcriptionist"));
      default:
        return t(getTranslationID("userListPage.label.none"));
    }
  };

  // ライセンスステータスに応じて、ライセンスステータスの文字列を返す
  const getLicenseStatus = (licenseStatus: string): string => {
    switch (licenseStatus) {
      case LICENSE_STATUS.NOLICENSE:
        return t(getTranslationID("userListPage.label.notAllocated"));
      case LICENSE_STATUS.ALERT:
        return t(getTranslationID("userListPage.label.alert"));
      case LICENSE_STATUS.RENEW:
        return t(getTranslationID("userListPage.label.renew"));
      case LICENSE_STATUS.NORMAL:
        return t(getTranslationID("userListPage.label.allocated"));
      default:
        return licenseStatus;
    }
  };

  return (
    <>
      <UserUpdatePopup
        isOpen={isUpdatePopupOpen}
        onClose={() => {
          setIsUpdatePopupOpen(false);
        }}
        clearUserSearchInputs={clearUserSearchInputs}
      />
      <UserAddPopup
        isOpen={isPopupOpen}
        onClose={() => {
          setIsPopupOpen(false);
        }}
        clearUserSearchInputs={clearUserSearchInputs}
      />
      <AllocateLicensePopup
        isOpen={isAllocateLicensePopupOpen}
        onClose={() => {
          setIsAllocateLicensePopupOpen(false);
        }}
        clearUserSearchInputs={clearUserSearchInputs}
      />
      <ImportPopup
        isOpen={isImportPopupOpen}
        onClose={() => {
          setIsImportPopupOpen(false);
        }}
      />
      <div
        className={`${styles.wrap} ${
          delegationAccessToken ? styles.manage : ""
        }`}
      >
        {delegationAccessToken && <DelegationBar />}
        <Header />
        <main className={styles.main}>
          <div className="">
            <div className={styles.pageHeader}>
              <h1 className={styles.pageTitle}>
                {t(getTranslationID("userListPage.label.title"))}
              </h1>
              <p className="pageTxt" />
            </div>
            <section className={styles.user}>
              <div>
                <ul className={styles.menuAction}>
                  <li>
                    {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
                    <a
                      className={`${styles.menuLink} ${
                        !isLoading ? styles.isActive : ""
                      }`}
                      onClick={onOpen}
                    >
                      <img src={personAdd} alt="" className={styles.menuIcon} />
                      {t(getTranslationID("userListPage.label.addUser"))}
                    </a>
                  </li>
                  <li>
                    {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
                    <a
                      className={`${styles.menuLink} ${styles.isActive}`}
                      onClick={onImportPopupOpen}
                    >
                      <img src={upload} alt="" className={styles.menuIcon} />
                      {t(getTranslationID("userListPage.label.bulkImport"))}
                    </a>
                  </li>
                  <li className={styles.floatRight}>
                    <form
                      className={styles.searchBar}
                      onSubmit={(e) => requestSearch(e)}
                    >
                      <input
                        type="text"
                        placeholder={t(
                          getTranslationID("userListPage.label.name")
                        )}
                        value={searchUserName}
                        onChange={(e) =>
                          setSearchUserName(e.target.value.trimStart())
                        }
                        className={styles.searchInput}
                      />
                      <input
                        type="text"
                        placeholder={t(
                          getTranslationID("userListPage.label.email")
                        )}
                        value={searchEmail}
                        onChange={(e) =>
                          setSearchEmail(e.target.value.trimStart())
                        }
                        className={styles.searchInput}
                      />
                      {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
                      <button
                        className={`${styles.menuLink} ${
                          !isLoading ? styles.isActive : ""
                        }`}
                        type="submit"
                        disabled={isLoading}
                      >
                        <img
                          src={searchIcon}
                          alt="search"
                          className={styles.menuIcon}
                        />
                        {t(getTranslationID("userListPage.label.search"))}
                      </button>
                    </form>
                  </li>
                </ul>
                <div className={styles.tableWrap}>
                  <table className={`${styles.table} ${styles.user}`}>
                    <tbody>
                      <tr className={styles.tableHeader}>
                        <th className={styles.clm0}>{/** th is empty */}</th>
                        <th>
                          {t(getTranslationID("userListPage.label.name"))}
                        </th>
                        <th>
                          {t(getTranslationID("userListPage.label.role"))}
                        </th>
                        <th>
                          {t(getTranslationID("userListPage.label.authorID"))}
                        </th>
                        <th>
                          {t(getTranslationID("userListPage.label.encryption"))}
                        </th>
                        <th>
                          {t(getTranslationID("userListPage.label.prompt"))}
                        </th>
                        <th>
                          {t(
                            getTranslationID("userListPage.label.typistGroup")
                          )}
                        </th>
                        <th>
                          {t(getTranslationID("userListPage.label.email"))}
                        </th>
                        <th>
                          {t(getTranslationID("userListPage.label.status"))}
                        </th>
                        <th>
                          {t(getTranslationID("userListPage.label.expiration"))}
                        </th>
                        <th>
                          {t(getTranslationID("userListPage.label.remaining"))}
                        </th>
                        <th>
                          {t(getTranslationID("userListPage.label.autoRenew"))}
                        </th>
                        <th>
                          {t(
                            getTranslationID("userListPage.label.notification")
                          )}
                        </th>
                        <th>
                          {t(
                            getTranslationID("userListPage.label.emailVerified")
                          )}
                        </th>
                      </tr>
                      {!isLoading &&
                        users.map((user) => (
                          <tr key={user.email}>
                            <td className={styles.clm0}>
                              <ul className={styles.menuInTable}>
                                <li>
                                  {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
                                  <a
                                    onClick={() => {
                                      onUpdateOpen(user.id);
                                    }}
                                  >
                                    {t(
                                      getTranslationID(
                                        "userListPage.label.editUser"
                                      )
                                    )}
                                  </a>
                                </li>
                                {isTier5 && (
                                  <>
                                    <li>
                                      {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
                                      <a
                                        onClick={() => {
                                          onAllocateLicensePopupOpen(user);
                                        }}
                                      >
                                        {t(
                                          getTranslationID(
                                            "userListPage.label.licenseAllocation"
                                          )
                                        )}
                                      </a>
                                    </li>
                                    <li>
                                      {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
                                      <a
                                        className={
                                          user.licenseStatus ===
                                          LICENSE_STATUS.NOLICENSE
                                            ? styles.isDisable
                                            : ""
                                        }
                                        onClick={() => {
                                          onLicenseDeallocation(user.id);
                                        }}
                                      >
                                        {t(
                                          getTranslationID(
                                            "userListPage.label.licenseDeallocation"
                                          )
                                        )}
                                      </a>
                                    </li>
                                  </>
                                )}
                                <li>
                                  {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
                                  <a
                                    onClick={() => {
                                      onDeleteUser(user.id);
                                    }}
                                  >
                                    {t(
                                      getTranslationID(
                                        "userListPage.label.deleteUser"
                                      )
                                    )}
                                  </a>
                                </li>
                                {/* 第五階層の管理者が、メール認証済みではないユーザーの行をマウスオーバーしている場合のみ */}
                                {isTier5 && !user.emailVerified && (
                                  <li>
                                    {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
                                    <a
                                      onClick={() => {
                                        onForceEmailVerification(user.id);
                                      }}
                                    >
                                      {t(
                                        getTranslationID(
                                          "userListPage.label.forceEmailVerification"
                                        )
                                      )}
                                    </a>
                                  </li>
                                )}
                              </ul>
                            </td>
                            <td> {user.name}</td>
                            <td>{getUserRole(user.role)}</td>
                            <td>{user.authorId}</td>
                            <td>{boolToElement(user.encryption)}</td>
                            <td>{boolToElement(user.prompt)}</td>
                            <td>{arrayToElement(user.typistGroupName)}</td>
                            <td>{user.email}</td>
                            <td>
                              <span
                                className={
                                  user.licenseStatus ===
                                    LICENSE_STATUS.NOLICENSE ||
                                  user.licenseStatus === LICENSE_STATUS.ALERT
                                    ? styles.isAlert
                                    : ""
                                }
                              >
                                {getLicenseStatus(user.licenseStatus)}
                              </span>
                            </td>
                            <td>
                              <span
                                className={
                                  user.licenseStatus === LICENSE_STATUS.ALERT
                                    ? styles.isAlert
                                    : ""
                                }
                              >
                                {user.expiration ?? "-"}
                              </span>
                            </td>
                            <td>
                              <span
                                className={
                                  user.licenseStatus === LICENSE_STATUS.ALERT
                                    ? styles.isAlert
                                    : ""
                                }
                              >
                                {user.remaining ?? "-"}
                              </span>
                            </td>
                            <td>{boolToElement(user.autoRenew)}</td>
                            <td>{boolToElement(user.notification)}</td>
                            <td>{boolToElement(user.emailVerified)}</td>
                          </tr>
                        ))}
                    </tbody>
                  </table>
                </div>
                {!isLoading && users.length === 0 && (
                  <p
                    style={{
                      margin: "10px",
                      textAlign: "center",
                    }}
                  >
                    {t(getTranslationID("common.message.listEmpty"))}
                  </p>
                )}
                {isLoading && (
                  <img
                    src={progress_activit}
                    className={styles.icLoading}
                    alt="Loading"
                  />
                )}
              </div>
            </section>
          </div>
        </main>
        <Footer />
      </div>
    </>
  );
};

// boolかstringを受け取って、stringの場合はそのまま返し、boolの場合はチェックマークON/OFFを返す
const boolToElement = (value: boolean | string): JSX.Element | string => {
  if (typeof value === "string") {
    return value;
  }
  return value ? (
    <img src={checkFill} alt="" className={styles.menuIcon} />
  ) : (
    <img src={checkOutline} alt="" className={styles.menuIcon} />
  );
};

// 文字列の配列または文字列を受け取って、文字列の場合はそのまま返し、配列の場合は最後の要素以外に<br>をつけて返す
const arrayToElement = (
  typistGroupNames: string[] | string
): JSX.Element[] | string => {
  if (typeof typistGroupNames === "string") {
    return typistGroupNames;
  }
  return typistGroupNames.map((v, i) => (
    <span key={v}>
      {v}
      {i !== typistGroupNames.length - 1 && <br />}
    </span>
  ));
};

export default UserListPage;
