import React, { useEffect } from "react";
import { AUTHEN_TYPES, DOMAIN_TYPE } from "@/lib/appConstant";
import AppButton from "./button";
import { useTranslations } from "use-intl";
import StorageHelper from "@/lib/storeHelper";
import { STORAGE_KEYS } from "@/types/common";
import { useAppSelector } from "@/lib/redux/hooks";
import {
  getServicePath,
  getViewSettings,
} from "@/lib/redux/features/serviceAdmin";
import { useRouter, useSearchParams } from "next/navigation";
import { useMounted } from "@/hooks/useMounted";
import { showToast } from "@/components/toast/showToast";
import { generateRandomString } from "@/lib/utils";
import CryptoJS from "crypto-js";
export default function MicrosoftLoginButton(props: any) {
  const {
    clientId,
    onSubmit,
    isShowViewBook,
    contentDetailId,
    searchRequest,
    activeTab,
    isSubscriptionDetail,
  } = props;

  const t = useTranslations("");
  const params = useSearchParams();
  const router = useRouter();
  const mounted = useMounted();

  const servicePath = useAppSelector(getServicePath);
  const viewSettings = useAppSelector(getViewSettings);
  const search = window.location.search;
  const pathname = window.location.pathname;
  const location = window.location;

  const isFullDomain = viewSettings.domainType === DOMAIN_TYPE.FULL_DOMAIN;

  const redirectUrl = isFullDomain
    ? `${window.location.origin}/login`
    : `${window.location.origin}/${servicePath}/login`;

  const challengeFromVerifier = async (v) => {
    const encoder = new TextEncoder();
    const data = encoder.encode(v);
    // const hash = crypto.createHash("sha256").update(data).digest();
    // const base64String = hash
    //   .toString("base64")
    //   .replace(/\+/g, "-")
    //   .replace(/\//g, "_")
    //   .replace(/=+$/, "");

    // return base64String;
    
    const hashBuffer = await crypto.subtle.digest("SHA-256", data);
    // Change ArrayBuffer to Base64 string
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    const base64String = btoa(
      hashArray.map((byte) => String.fromCharCode(byte)).join("")
    )
      .replace(/\+/g, "-")
      .replace(/\//g, "_")
      .replace(/=+$/, "");

    return base64String;
  };

  const generateClientRequestId = () => {
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
      const r = (Math.random() * 16) | 0;
      const v = c === "x" ? r : (r & 0x3) | 0x8;
      return v.toString(16);
    });
  };

  const generateVerifier = () => {
    const randomString = CryptoJS.lib.WordArray.random(43);
    const base64String = CryptoJS.enc.Base64.stringify(randomString);
    const verifierCode = base64String
      .toString()
      .replace(/\+/g, "-")
      .replace(/\//g, "_")
      .replace(/=/g, "");
    return verifierCode;
  };

  const generateNonce = () => {
    return generateRandomString(16);
  };

  const generateState = () => {
    return generateRandomString(16);
  };

  const doLoginMicrosoftOnline = async ({
    clientRequestId,
    nonce,
    state,
    redirectUrl,
    clientId,
    verifier,
  }) => {
    if (!verifier) {
      return;
    }
    const codeChallenge = await challengeFromVerifier(verifier);
    if (
      codeChallenge &&
      clientRequestId &&
      nonce &&
      state &&
      redirectUrl &&
      clientId
    ) {
      // save verifier code and login Type
      StorageHelper.setSessionItem(STORAGE_KEYS.microsoftVerifier, verifier);
      StorageHelper.setSessionItem(
        STORAGE_KEYS.loginType,
        AUTHEN_TYPES.MICROSOFT_LOGIN
      );
      // &response_mode=fragment => it specifies the return url to use '#' and not '?'
      window.open(
        `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=${clientId}&scope=User.Read%20openid%20email%20profile%20offline_access&redirect_uri=${redirectUrl}&client-request-id=${clientRequestId}&prompt=select_account&response_mode=fragment&response_type=code&x-client-SKU=msal.js.browser&x-client-VER=3.7.0&client_info=1&code_challenge=${codeChallenge}&code_challenge_method=S256&nonce=${nonce}&state=${state}%3D`,
        "_self"
      );
    }
  };

  const handleOAuth2 = () => {
    // generate params
    const nonce = generateNonce();
    const state = generateState();
    const clientRequestId = generateClientRequestId();
    const verifier = generateVerifier();

    const data = {
      cacheRoute: window.location.pathname,
      isShowViewBook: isShowViewBook,
      contentId: contentDetailId,
      searchRequest: searchRequest,
      activeTab: activeTab,
    };
    StorageHelper.setSessionObject(STORAGE_KEYS.cacheStorage, data);
    if (isSubscriptionDetail) {
      StorageHelper.setSessionItem(
        STORAGE_KEYS.urlSubscDetail,
        window.location.href
      );
    }
    doLoginMicrosoftOnline({
      clientRequestId,
      nonce,
      state,
      redirectUrl,
      clientId,
      verifier,
    });
  };

  // // Handle when success
  useEffect(() => {
    const microsoftVerifier = StorageHelper.getSessionItem(
      STORAGE_KEYS.microsoftVerifier
    );
    const loginType = StorageHelper.getSessionItem(STORAGE_KEYS.loginType);
    if (
      location.hash &&
      location.hash.includes("#code=") &&
      microsoftVerifier &&
      loginType === AUTHEN_TYPES.MICROSOFT_LOGIN
    ) {
      const code = location.hash.split("&")[0].replace("#code=", "");
      if (code) {
        const params = {
          authorizeCode: code,
          codeVerifier: CryptoJS.enc.Base64.stringify(
            CryptoJS.enc.Utf8.parse(microsoftVerifier)
          ),
          loginType: AUTHEN_TYPES.MICROSOFT_LOGIN,
          redirectUrl: redirectUrl,
        };
        StorageHelper.setSessionItem(STORAGE_KEYS.loginType, null);
        StorageHelper.setSessionItem(STORAGE_KEYS.microsoftVerifier, null);
        onSubmit(params, AUTHEN_TYPES.MICROSOFT_LOGIN);
        // history.push("/login");
        router.push(`${servicePath ? '/'+servicePath : ''}/login`);
      } else {
        console.log("code is null");
      }
    }
  }, []);

  // // Handle when Error
  useEffect(() => {
    if (location.hash && location.hash.includes("#error=")) {
      const error = location.hash.split("&")[0].replace("#error=", "");
      if (error) {
        showToast("error", t("toast.error.loginFailed"));
        StorageHelper.setSessionItem(STORAGE_KEYS.loginType, null);
        StorageHelper.setSessionItem(STORAGE_KEYS.microsoftVerifier, null);
        router.push(`${servicePath ? '/'+servicePath : ''}/login`);
      } else {
        console.log("error is null");
      }
    }
  }, []);

  // // Handle when 'login page' has param 'microsoft=true&fl=true'
  useEffect(() => {
    if (
      search &&
      (search === "?microsoft=true" || search === "?microsoft=true&fl=true") &&
      pathname &&
      pathname.includes("/login")
    ) {
      handleOAuth2();
    }
  }, []);

  return (
    <div>
      <AppButton
        type="primary"
        color="danger"
        customColor="#fff"
        // htmlType="submit"
        // loading={isLoading}
        onClick={handleOAuth2}
        style={{ border: "1px solid #6c757d", color: "#000" }}
        className="w-full"
      >
        <img
          src={"/assets/icons/microsoft.svg"}
          style={{ width: "20px", height: "20px" }}
        />
        {t("menu.loginMicrosoft")}
      </AppButton>
    </div>
  );
}
