/**
 * Copyright (c) 2023-present Plane Software, Inc. and contributors
 * SPDX-License-Identifier: AGPL-3.0-only
 * See the LICENSE file for details.
 */

import type { ReactNode } from "react";
import Link from "next/link";

export enum EPageTypes {
  PUBLIC = "PUBLIC",
  NON_AUTHENTICATED = "NON_AUTHENTICATED",
  SET_PASSWORD = "SET_PASSWORD",
  ONBOARDING = "ONBOARDING",
  AUTHENTICATED = "AUTHENTICATED",
}

export enum EAuthModes {
  SIGN_IN = "SIGN_IN",
  SIGN_UP = "SIGN_UP",
}

export enum EAuthSteps {
  EMAIL = "EMAIL",
  PASSWORD = "PASSWORD",
  UNIQUE_CODE = "UNIQUE_CODE",
}

export enum EErrorAlertType {
  BANNER_ALERT = "BANNER_ALERT",
  INLINE_FIRST_NAME = "INLINE_FIRST_NAME",
  INLINE_EMAIL = "INLINE_EMAIL",
  INLINE_PASSWORD = "INLINE_PASSWORD",
  INLINE_EMAIL_CODE = "INLINE_EMAIL_CODE",
}

export enum EAuthenticationErrorCodes {
  INSTANCE_NOT_CONFIGURED = "5000",
  INVALID_EMAIL = "5005",
  EMAIL_REQUIRED = "5010",
  SIGNUP_DISABLED = "5015",
  MAGIC_LINK_LOGIN_DISABLED = "5016",
  PASSWORD_LOGIN_DISABLED = "5018",
  USER_ACCOUNT_DEACTIVATED = "5019",
  INVALID_PASSWORD = "5020",
  PASSWORD_TOO_WEAK = "5021",
  SMTP_NOT_CONFIGURED = "5025",
  USER_ALREADY_EXIST = "5030",
  AUTHENTICATION_FAILED_SIGN_UP = "5035",
  REQUIRED_EMAIL_PASSWORD_SIGN_UP = "5040",
  INVALID_EMAIL_SIGN_UP = "5045",
  INVALID_EMAIL_MAGIC_SIGN_UP = "5050",
  MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED = "5055",
  USER_DOES_NOT_EXIST = "5060",
  AUTHENTICATION_FAILED_SIGN_IN = "5065",
  REQUIRED_EMAIL_PASSWORD_SIGN_IN = "5070",
  INVALID_EMAIL_SIGN_IN = "5075",
  INVALID_EMAIL_MAGIC_SIGN_IN = "5080",
  MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED = "5085",
  INVALID_MAGIC_CODE_SIGN_IN = "5090",
  INVALID_MAGIC_CODE_SIGN_UP = "5092",
  EXPIRED_MAGIC_CODE_SIGN_IN = "5095",
  EXPIRED_MAGIC_CODE_SIGN_UP = "5097",
  EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_IN = "5100",
  EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP = "5102",
  OAUTH_NOT_CONFIGURED = "5104",
  GOOGLE_NOT_CONFIGURED = "5105",
  GITHUB_NOT_CONFIGURED = "5110",
  GITLAB_NOT_CONFIGURED = "5111",
  GOOGLE_OAUTH_PROVIDER_ERROR = "5115",
  GITHUB_OAUTH_PROVIDER_ERROR = "5120",
  GITLAB_OAUTH_PROVIDER_ERROR = "5121",
  INVALID_PASSWORD_TOKEN = "5125",
  EXPIRED_PASSWORD_TOKEN = "5130",
  INCORRECT_OLD_PASSWORD = "5135",
  MISSING_PASSWORD = "5138",
  INVALID_NEW_PASSWORD = "5140",
  PASSWORD_ALREADY_SET = "5145",
  ADMIN_ALREADY_EXIST = "5150",
  REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME = "5155",
  INVALID_ADMIN_EMAIL = "5160",
  INVALID_ADMIN_PASSWORD = "5165",
  REQUIRED_ADMIN_EMAIL_PASSWORD = "5170",
  ADMIN_AUTHENTICATION_FAILED = "5175",
  ADMIN_USER_ALREADY_EXIST = "5180",
  ADMIN_USER_DOES_NOT_EXIST = "5185",
  ADMIN_USER_DEACTIVATED = "5190",
  RATE_LIMIT_EXCEEDED = "5900",
}

export type TAuthErrorInfo = {
  type: EErrorAlertType;
  code: EAuthenticationErrorCodes;
  title: string;
  message: ReactNode;
};

const authLinkClass = "nodedc-auth-link font-medium";

const errorCodeMessages: {
  [key in EAuthenticationErrorCodes]: { title: string; message: (email?: string) => ReactNode };
} = {
  [EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED]: {
    title: "Пространство не настроено",
    message: () => "Пространство не настроено. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.INVALID_EMAIL]: {
    title: "Некорректный e-mail",
    message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.EMAIL_REQUIRED]: {
    title: "Нужен e-mail",
    message: () => "Укажите e-mail и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.SIGNUP_DISABLED]: {
    title: "Регистрация отключена",
    message: () => "Регистрация отключена. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.MAGIC_LINK_LOGIN_DISABLED]: {
    title: "Вход по коду отключён",
    message: () => "Вход по коду отключён. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.PASSWORD_LOGIN_DISABLED]: {
    title: "Вход по паролю отключён",
    message: () => "Вход по паролю отключён. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.USER_ACCOUNT_DEACTIVATED]: {
    title: "Аккаунт деактивирован",
    message: () => "Аккаунт деактивирован. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.INVALID_PASSWORD]: {
    title: "Неверный пароль",
    message: () => "Неверный пароль. Попробуйте снова.",
  },
  [EAuthenticationErrorCodes.PASSWORD_TOO_WEAK]: {
    title: "Слишком простой пароль",
    message: () => "Пароль должен содержать строчные и заглавные буквы, цифру и специальный символ.",
  },
  [EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED]: {
    title: "Почта не настроена",
    message: () => "Почтовый сервис не настроен. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.USER_ALREADY_EXIST]: {
    title: "Аккаунт уже существует",
    message: (email = undefined) => (
      <div>
        Аккаунт уже зарегистрирован.&nbsp;
        <Link className={authLinkClass} href={`/sign-in${email ? `?email=${encodeURIComponent(email)}` : ``}`}>
          Войти
        </Link>
        &nbsp;сейчас.
      </div>
    ),
  },
  [EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP]: {
    title: "Не удалось выполнить вход",
    message: () => "Не удалось выполнить вход. Проверьте данные и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_UP]: {
    title: "Нужны e-mail и пароль",
    message: () => "Укажите e-mail и пароль, затем попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP]: {
    title: "Некорректный e-mail",
    message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP]: {
    title: "Некорректный e-mail",
    message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED]: {
    title: "Нужны e-mail и код",
    message: () => "Укажите e-mail и код подтверждения, затем попробуйте снова.",
  },
  [EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
    title: "Аккаунт не найден",
    message: (email = undefined) => (
      <div>
        Аккаунт не найден.&nbsp;
        <Link className={authLinkClass} href={`/${email ? `?email=${encodeURIComponent(email)}` : ``}`}>
          Создать аккаунт
        </Link>
        &nbsp;для начала работы.
      </div>
    ),
  },
  [EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN]: {
    title: "Не удалось выполнить вход",
    message: () => "Не удалось выполнить вход. Проверьте данные и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN]: {
    title: "Нужны e-mail и пароль",
    message: () => "Укажите e-mail и пароль, затем попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN]: {
    title: "Некорректный e-mail",
    message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN]: {
    title: "Некорректный e-mail",
    message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED]: {
    title: "Нужны e-mail и код",
    message: () => "Укажите e-mail и код подтверждения, затем попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_MAGIC_CODE_SIGN_IN]: {
    title: "Неверный код подтверждения",
    message: () => "Код подтверждения неверный. Попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_MAGIC_CODE_SIGN_UP]: {
    title: "Неверный код подтверждения",
    message: () => "Код подтверждения неверный. Попробуйте снова.",
  },
  [EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE_SIGN_IN]: {
    title: "Код подтверждения истёк",
    message: () => "Код подтверждения истёк. Запросите новый и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE_SIGN_UP]: {
    title: "Код подтверждения истёк",
    message: () => "Код подтверждения истёк. Запросите новый и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_IN]: {
    title: "Лимит попыток исчерпан",
    message: () => "Лимит попыток ввода кода исчерпан. Запросите новый код.",
  },
  [EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP]: {
    title: "Лимит попыток исчерпан",
    message: () => "Лимит попыток ввода кода исчерпан. Запросите новый код.",
  },
  [EAuthenticationErrorCodes.OAUTH_NOT_CONFIGURED]: {
    title: "OAuth не настроен",
    message: () => "OAuth не настроен. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED]: {
    title: "Google OAuth не настроен",
    message: () => "Google OAuth не настроен. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED]: {
    title: "GitHub OAuth не настроен",
    message: () => "GitHub OAuth не настроен. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.GITLAB_NOT_CONFIGURED]: {
    title: "GitLab OAuth не настроен",
    message: () => "GitLab OAuth не настроен. Обратитесь к администратору.",
  },
  [EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR]: {
    title: "Ошибка Google OAuth",
    message: () => "Не удалось авторизоваться через Google. Попробуйте снова.",
  },
  [EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR]: {
    title: "Ошибка GitHub OAuth",
    message: () => "Не удалось авторизоваться через GitHub. Попробуйте снова.",
  },
  [EAuthenticationErrorCodes.GITLAB_OAUTH_PROVIDER_ERROR]: {
    title: "Ошибка GitLab OAuth",
    message: () => "Не удалось авторизоваться через GitLab. Попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN]: {
    title: "Некорректный токен",
    message: () => "Токен сброса пароля некорректен.",
  },
  [EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN]: {
    title: "Токен истёк",
    message: () => "Токен сброса пароля истёк. Запросите новый.",
  },
  [EAuthenticationErrorCodes.MISSING_PASSWORD]: {
    title: "Нужен пароль",
    message: () => "Укажите пароль и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD]: {
    title: "Неверный старый пароль",
    message: () => "Неверный старый пароль. Попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_NEW_PASSWORD]: {
    title: "Некорректный новый пароль",
    message: () => "Некорректный новый пароль. Проверьте требования и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.PASSWORD_ALREADY_SET]: {
    title: "Пароль уже установлен",
    message: () => "Пароль уже установлен. Попробуйте войти в систему.",
  },
  [EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST]: {
    title: "Администратор уже существует",
    message: () => "Администратор уже существует. Проверьте данные и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME]: {
    title: "Нужны имя, e-mail и пароль",
    message: () => "Укажите имя, e-mail и пароль, затем попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL]: {
    title: "Некорректный e-mail администратора",
    message: () => "Некорректный e-mail администратора. Проверьте адрес и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD]: {
    title: "Некорректный пароль администратора",
    message: () => "Некорректный пароль администратора. Проверьте данные и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD]: {
    title: "Нужны e-mail и пароль",
    message: () => "Укажите e-mail и пароль, затем попробуйте снова.",
  },
  [EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED]: {
    title: "Не удалось выполнить вход",
    message: () => "Не удалось выполнить вход. Проверьте данные и попробуйте снова.",
  },
  [EAuthenticationErrorCodes.ADMIN_USER_ALREADY_EXIST]: {
    title: "Администратор уже существует",
    message: () => (
      <div>
        Администратор уже существует.&nbsp;
        <Link className={authLinkClass} href="/admin">
          Войти
        </Link>
        &nbsp;сейчас.
      </div>
    ),
  },
  [EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST]: {
    title: "Администратор не найден",
    message: () => (
      <div>
        Администратор не найден.&nbsp;
        <Link className={authLinkClass} href="/admin">
          Войти
        </Link>
        &nbsp;сейчас.
      </div>
    ),
  },
  [EAuthenticationErrorCodes.ADMIN_USER_DEACTIVATED]: {
    title: "Аккаунт администратора деактивирован",
    message: () => <div>Аккаунт администратора деактивирован.</div>,
  },
  [EAuthenticationErrorCodes.RATE_LIMIT_EXCEEDED]: {
    title: "",
    message: () => "Слишком много попыток. Повторите позже.",
  },
};

export const authErrorHandler = (errorCode: EAuthenticationErrorCodes, email?: string): TAuthErrorInfo | undefined => {
  const bannerAlertErrorCodes = [
    EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED,
    EAuthenticationErrorCodes.INVALID_EMAIL,
    EAuthenticationErrorCodes.EMAIL_REQUIRED,
    EAuthenticationErrorCodes.SIGNUP_DISABLED,
    EAuthenticationErrorCodes.MAGIC_LINK_LOGIN_DISABLED,
    EAuthenticationErrorCodes.PASSWORD_LOGIN_DISABLED,
    EAuthenticationErrorCodes.USER_ACCOUNT_DEACTIVATED,
    EAuthenticationErrorCodes.INVALID_PASSWORD,
    EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED,
    EAuthenticationErrorCodes.USER_ALREADY_EXIST,
    EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP,
    EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_UP,
    EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP,
    EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP,
    EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED,
    EAuthenticationErrorCodes.USER_DOES_NOT_EXIST,
    EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN,
    EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN,
    EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN,
    EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN,
    EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED,
    EAuthenticationErrorCodes.INVALID_MAGIC_CODE_SIGN_IN,
    EAuthenticationErrorCodes.INVALID_MAGIC_CODE_SIGN_UP,
    EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE_SIGN_IN,
    EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE_SIGN_UP,
    EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_IN,
    EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP,
    EAuthenticationErrorCodes.OAUTH_NOT_CONFIGURED,
    EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED,
    EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED,
    EAuthenticationErrorCodes.GITLAB_NOT_CONFIGURED,
    EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR,
    EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR,
    EAuthenticationErrorCodes.GITLAB_OAUTH_PROVIDER_ERROR,
    EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN,
    EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN,
    EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD,
    EAuthenticationErrorCodes.MISSING_PASSWORD,
    EAuthenticationErrorCodes.INVALID_NEW_PASSWORD,
    EAuthenticationErrorCodes.PASSWORD_ALREADY_SET,
    EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST,
    EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME,
    EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL,
    EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD,
    EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD,
    EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED,
    EAuthenticationErrorCodes.ADMIN_USER_ALREADY_EXIST,
    EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST,
    EAuthenticationErrorCodes.ADMIN_USER_DEACTIVATED,
    EAuthenticationErrorCodes.RATE_LIMIT_EXCEEDED,
    EAuthenticationErrorCodes.PASSWORD_TOO_WEAK,
  ];

  if (bannerAlertErrorCodes.includes(errorCode)) {
    return {
      type: EErrorAlertType.BANNER_ALERT,
      code: errorCode,
      title: errorCodeMessages[errorCode]?.title || "Ошибка",
      message: errorCodeMessages[errorCode]?.message(email) || "Что-то пошло не так. Попробуйте снова.",
    };
  }

  return undefined;
};

export const passwordErrors = [
  EAuthenticationErrorCodes.PASSWORD_TOO_WEAK,
  EAuthenticationErrorCodes.INVALID_NEW_PASSWORD,
];
