import { BaseAdapterConfig, IWalletConnectExtensionAdapter, log, WALLET_ADAPTERS } from "@web3auth/base";
import bowser from "bowser";
import { useEffect, useMemo, useState } from "react";

import { MODAL_STATUS, ModalStatusType, WALLET_CONNECT_LOGO } from "../interfaces";
import Image from "./Image";

interface ExternalWalletsProps {
  handleExternalWalletClick: (params: { adapter: string }) => void;
  config: Record<string, BaseAdapterConfig>;
  walletConnectUri: string | undefined;
  modalStatus: ModalStatusType;
  wcAdapters: IWalletConnectExtensionAdapter[];
}

type ExternalButton = {
  formatName: string;
  name: string;
  href?: string;
  logo?: string;
  isLink: boolean;
  block: boolean;
  adapter: string;
};

interface IMobileRegistryEntry {
  name: string;
  logo: string;
  universalLink: string;
  deepLink: string;
  href: string;
}

type os = "iOS" | "Android";

type platform = "mobile" | "desktop" | "tablet";

function formatIOSMobile(params: { uri: string; universalLink?: string; deepLink?: string }) {
  const encodedUri: string = encodeURIComponent(params.uri);
  if (params.universalLink) {
    return `${params.universalLink}/wc?uri=${encodedUri}`;
  }
  if (params.deepLink) {
    return `${params.deepLink}${params.deepLink.endsWith(":") ? "//" : "/"}wc?uri=${encodedUri}`;
  }
  return "";
}

function formatMobileRegistryEntry(
  entry: IWalletConnectExtensionAdapter,
  walletConnectUri: string,
  os: os,
  platform: platform = "mobile"
): IMobileRegistryEntry {
  const universalLink = entry[platform].universal || "";
  const deepLink = entry[platform].native || "";
  return {
    name: entry.name || "",
    logo: entry.logo || "",
    universalLink,
    deepLink,
    href: os === bowser.OS_MAP.iOS ? formatIOSMobile({ uri: walletConnectUri, universalLink, deepLink }) : walletConnectUri,
  };
}

function formatMobileRegistry(
  registry: IWalletConnectExtensionAdapter[],
  walletConnectUri: string,
  os: os,
  platform: platform = "mobile"
): IMobileRegistryEntry[] {
  return Object.values<IWalletConnectExtensionAdapter>(registry)
    .filter((entry) => !!entry[platform].universal || !!entry[platform].native)
    .map((entry) => formatMobileRegistryEntry(entry, walletConnectUri, os, platform));
}

export default function ExternalWallet(props: ExternalWalletsProps) {
  const { handleExternalWalletClick, config = {}, walletConnectUri, modalStatus, wcAdapters } = props;
  const [adapterVisibilityMap, setAdapterVisibilityMap] = useState<Record<string, boolean>>({});
  const [externalButtons, setExternalButtons] = useState<ExternalButton[]>([]);

  const deviceType = useMemo<platform>(() => {
    const browser = bowser.getParser(window.navigator.userAgent);
    return browser.getPlatformType() as platform;
  }, []);
  const deviceDetails = useMemo<{ platform: platform; os: os }>(() => {
    const browser = bowser.getParser(window.navigator.userAgent);
    return { platform: browser.getPlatformType() as platform, os: browser.getOSName() as os };
  }, []);

  useEffect(() => {
    log.debug("loaded external wallets", config, walletConnectUri, deviceType);
    const canShowMap: Record<string, boolean> = {};
    Object.keys(config).forEach((adapter) => {
      const adapterConfig = config[adapter];
      if (!adapterConfig.showOnModal) {
        canShowMap[adapter] = false;
        return;
      }
      if (deviceType === "desktop" && adapterConfig.showOnDesktop) {
        canShowMap[adapter] = true;
        return;
      }
      if ((deviceType === "mobile" || deviceType === "tablet") && adapterConfig.showOnMobile) {
        canShowMap[adapter] = true;
        return;
      }
      canShowMap[adapter] = false;
    });
    setAdapterVisibilityMap(canShowMap);
  }, [config, walletConnectUri, deviceType]);

  useEffect(() => {
    const buttons: ExternalButton[] = [];
    // add wallet connect links
    if (deviceDetails.platform === bowser.PLATFORMS_MAP.mobile) {
      const mobileLinks = formatMobileRegistry(wcAdapters, walletConnectUri, deviceDetails.os, deviceDetails.platform);
      if (deviceDetails.os === bowser.OS_MAP.iOS) {
        buttons.push(
          ...mobileLinks.map((link) => ({
            name: link.name,
            adapter: link.name,
            href: link.href,
            logo: link.logo,
            isLink: true,
            block: false,
            formatName: link.name,
          }))
        );
      } else if (mobileLinks.length > 0) {
        buttons.push({
          name: "WalletConnect",
          adapter: "WalletConnect",
          href: mobileLinks[0].href,
          logo: WALLET_CONNECT_LOGO,
          isLink: true,
          block: true,
          formatName: "WalletConnect",
        });
      }
    }

    const adapterBtns = Object.keys(config).map((adapter) => {
      const name = adapter === WALLET_ADAPTERS.WALLET_CONNECT_V1 || adapter === WALLET_ADAPTERS.WALLET_CONNECT_V2 ? "wallet-connect" : adapter;
      const formatName = {
        metamask: "MetaMask",
        "wallet-connect": "WalletConnect",
      };
      return {
        name,
        adapter,
        isLink: false,
        block: false,
        formatName: formatName[name] ?? name,
      };
    });

    if (adapterBtns.length === 1 && deviceDetails.os !== bowser.OS_MAP.iOS) adapterBtns[0].block = true;

    buttons.push(...adapterBtns);
    setExternalButtons(buttons);
  }, [wcAdapters, config, deviceDetails.os, deviceDetails.platform, walletConnectUri, adapterVisibilityMap]);

  return (
    <div className="w3ajs-external-wallet w3a-group">
      <div className="w3a-external-container w3ajs-external-container">
        {/* <!-- Other Wallet --> */}
        {/* {Object.keys(config).map((adapter) => { */}
        {/*  if ( */}
        {/*    walletConnectUri && */}
        {/*    deviceDetails.platform === bowser.PLATFORMS_MAP.desktop && */}
        {/*    [WALLET_ADAPTERS.WALLET_CONNECT_V1, WALLET_ADAPTERS.WALLET_CONNECT_V2].includes(adapter) */}
        {/*  ) { */}
        {/*    return <WalletConnect key={adapter} walletConnectUri={walletConnectUri} />; */}
        {/*  } */}
        {/*  return null; */}
        {/* })} */}
        {modalStatus === MODAL_STATUS.INITIALIZED && (
          <ul className={`w3a-adapter-list w3ajs-wallet-adapters ${externalButtons.length === 1 ? "w3a-list-one" : ""}`}>
            {externalButtons.map((button) => {
              const providerIcon = button.isLink ? (
                <img src={button.logo} height="auto" width="auto" alt={`login-${button.name}`} />
              ) : (
                <Image imageId={`login-${button.name}`} hoverImageId={`login-${button.name}`} isButton />
              );
              return (
                <li className="w3a-adapter-item w3a-adapter-item-span" key={button.name}>
                  {button.isLink ? (
                    <a key={button.name} href={button.href} rel="noopener noreferrer" target="_blank">
                      {deviceType !== "mobile" && button.formatName}
                      <button type="button" className="w-full w3a-button w3a-button--login">
                        {providerIcon}
                      </button>
                    </a>
                  ) : (
                    <button
                      type="button"
                      onClick={() => handleExternalWalletClick({ adapter: button.adapter })}
                      className="w-full w3a-button w3a-button--login"
                      title={config[button.name]?.label || button.name}
                    >
                      {deviceType !== "mobile" && button.formatName}
                      {providerIcon}
                    </button>
                  )}
                </li>
              );
            })}
          </ul>
        )}
      </div>
    </div>
  );
}
