import { LoaderCircle, X } from "lucide-react";
import { useEffect, useState } from "react";
import { useI18n } from "../i18n";
import { walletDeepLink, walletDownloadUrl } from "./deepLinks";
import {
  connectInjectedWallet,
  getInjectedWallet,
  type WalletKind,
} from "./injected";
import { useWallet } from "./WalletProvider";
import { WalletBrandIcon } from "./WalletBrandIcon";

const AUTO_LOGIN_PARAM = "autologin";

function supportsDirectPull(kind: WalletKind): boolean {
  return kind === "tokenPocket" || kind === "imToken";
}

function supportsDesktopExtension(kind: WalletKind): boolean {
  return kind === "tokenPocket";
}

function buildAutoLoginDappUrl(kind: WalletKind): string {
  const url = new URL(window.location.href);
  url.searchParams.set(AUTO_LOGIN_PARAM, kind);
  return url.toString();
}

const wallets: WalletKind[] = ["tokenPocket", "imToken"];

type LoginState = "idle" | "connecting";

type PendingLogin = {
  kind: WalletKind;
  address: string;
};

type Translate = (key: string) => string;

function walletErrorMessage(error: unknown, t: Translate): string {
  if (!(error instanceof Error)) return t("walletLoginFailed");
  return t(error.message) || t("walletLoginFailed");
}

function isMobileDevice(): boolean {
  if (typeof navigator === "undefined") return false;
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile/i.test(
    navigator.userAgent || "",
  );
}

export function WalletLoginModal() {
  const { t } = useI18n();
  const { closeLoginModal, loginAddress, loginModalOpen } = useWallet();
  const [selected, setSelected] = useState<WalletKind | null>(null);
  const [mobileDevice, setMobileDevice] = useState(() => isMobileDevice());
  const [state, setState] = useState<LoginState>("idle");
  const [error, setError] = useState("");
  const [pendingLogin, setPendingLogin] = useState<PendingLogin | null>(null);

  useEffect(() => {
    if (!loginModalOpen) return;
    setMobileDevice(isMobileDevice());
    setSelected(null);
    setState("idle");
    setError("");
    setPendingLogin(null);
  }, [loginModalOpen]);

  if (!loginModalOpen) return null;

  const walletName = (kind: WalletKind) => t(walletNameKey(kind));
  const walletText = (key: string, kind: WalletKind) =>
    t(key).replaceAll("{wallet}", walletName(kind));
  const walletHint = () =>
    mobileDevice ? t("walletChooseMobile") : t("walletDesktopHint");
  const visibleWallets = mobileDevice
    ? wallets
    : wallets.filter(supportsDesktopExtension);
  const busy = state !== "idle";

  const close = () => {
    closeLoginModal();
    setSelected(null);
    setState("idle");
    setError("");
    setPendingLogin(null);
  };

  const selectWallet = (kind: WalletKind) => {
    setSelected(kind);
    setError("");
    setPendingLogin(null);
  };

  const loginInjected = async (kind: WalletKind) => {
    setSelected(kind);
    setState("connecting");
    setError("");
    setPendingLogin(null);
    try {
      const address = await connectInjectedWallet(kind);
      if (mobileDevice) {
        await loginAddress(address);
        return;
      }
      setPendingLogin({ kind, address });
      setState("idle");
    } catch (err) {
      setState("idle");
      setError(walletErrorMessage(err, t));
    }
  };

  const confirmPendingLogin = async () => {
    if (!pendingLogin) return;
    setState("connecting");
    setError("");
    try {
      await loginAddress(pendingLogin.address);
    } catch (err) {
      setState("idle");
      setError(walletErrorMessage(err, t));
    }
  };

  const cancelPendingLogin = () => {
    setPendingLogin(null);
    setSelected(null);
    setState("idle");
    setError("");
  };

  const openWalletAppDirect = (kind: WalletKind) => {
    if (!mobileDevice && !supportsDesktopExtension(kind)) {
      setSelected(kind);
      setPendingLogin(null);
      setError("");
      return;
    }
    if (getInjectedWallet(kind)) {
      void loginInjected(kind);
      return;
    }
    if (mobileDevice && supportsDirectPull(kind)) {
      setSelected(kind);
      setError("");
      const deeplink = walletDeepLink(kind, buildAutoLoginDappUrl(kind));
      window.location.href = deeplink;
      return;
    }
    setSelected(kind);
    setPendingLogin(null);
    setError(walletText("walletInstallSelected", kind));
  };

  const openWalletInstall = (kind: WalletKind) => {
    window.open(walletDownloadUrl(kind), "_blank", "noopener,noreferrer");
  };

  return (
    <div
      className="fixed inset-0 z-[120] flex items-end justify-center bg-black/70 px-3 pb-3 pt-10 backdrop-blur-sm md:items-center md:p-6"
      role="dialog"
      aria-modal="true"
      aria-labelledby="wallet-login-title"
    >
      <div className="max-h-[92dvh] w-full max-w-[460px] overflow-y-auto rounded-3xl border border-white/10 bg-[#17171d] p-5 shadow-2xl shadow-black/70 md:p-6">
        <div className="flex items-start justify-between gap-3">
          <div className="min-w-0">
            <h2
              id="wallet-login-title"
              className="text-xl font-semibold text-white"
            >
              {t("walletLoginTitle")}
            </h2>
            <p className="mt-2 text-sm leading-6 text-neutral-400">
              {t("walletLoginDesc")}
            </p>
          </div>
          <button
            type="button"
            onClick={close}
            aria-label={t("close")}
            className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full border border-white/10 text-neutral-300 transition hover:border-ark-gold/50 hover:text-ark-gold"
          >
            <X size={18} />
          </button>
        </div>

        <div className="mt-5 grid gap-2">
          {visibleWallets.map((kind) => {
            const active = selected === kind;
            const connecting = active && state === "connecting";
            return (
              <div
                key={kind}
                className={`rounded-2xl border p-3 transition ${
                  active
                    ? "border-ark-gold/60 bg-ark-gold/10"
                    : "border-white/10 bg-[#20202a]"
                }`}
              >
                <button
                  type="button"
                  onClick={() =>
                    mobileDevice
                      ? selectWallet(kind)
                      : openWalletAppDirect(kind)
                  }
                  disabled={busy}
                  className="flex w-full items-center gap-3 text-left disabled:cursor-wait disabled:opacity-70"
                >
                  <WalletBrandIcon kind={kind} size={32} />
                  <span className="min-w-0 flex-1">
                    <span className="block text-base font-semibold text-neutral-100">
                      {walletName(kind)}
                    </span>
                    <span className="mt-1 block text-xs leading-5 text-neutral-400">
                      {connecting ? t("walletConnecting") : walletHint()}
                    </span>
                  </span>
                  {connecting ? (
                    <LoaderCircle className="h-4 w-4 animate-spin text-ark-gold" />
                  ) : null}
                </button>

                {mobileDevice && active ? (
                  <div className="mt-3">
                    <button
                      type="button"
                      onClick={() => openWalletAppDirect(kind)}
                      disabled={busy}
                      className="w-full rounded-full bg-ark-gold px-3 py-2 text-sm font-bold text-black transition hover:bg-ark-gold2 disabled:cursor-wait disabled:opacity-70"
                    >
                      {t("walletOpenWalletApp")}
                    </button>
                  </div>
                ) : null}

                {!mobileDevice && active ? (
                  <div className="mt-3 rounded-2xl border border-white/10 bg-black/20 p-3 text-sm text-neutral-300">
                    {pendingLogin?.kind === kind ? (
                      <>
                        <p className="font-semibold text-neutral-100">
                          {walletText("walletConfirmAddressTitle", kind)}
                        </p>
                        <p className="mt-2 text-xs leading-5 text-neutral-400">
                          {walletText("walletConfirmAddressDesc", kind)}
                        </p>
                        <p
                          className="mt-3 break-all rounded-xl border border-ark-gold/30 bg-ark-gold/10 px-3 py-2 font-mono text-sm text-ark-gold"
                          title={pendingLogin.address}
                        >
                          {pendingLogin.address}
                        </p>
                        <div className="mt-3 grid gap-2 sm:grid-cols-2">
                          <button
                            type="button"
                            onClick={confirmPendingLogin}
                            className="rounded-full bg-ark-gold px-3 py-2 text-sm font-bold text-black transition hover:bg-ark-gold2"
                          >
                            {t("walletConfirmLogin")}
                          </button>
                          <button
                            type="button"
                            onClick={cancelPendingLogin}
                            className="rounded-full border border-white/20 px-3 py-2 text-sm font-semibold text-neutral-200 transition hover:border-ark-gold/50 hover:text-ark-gold"
                          >
                            {t("walletCancelLogin")}
                          </button>
                        </div>
                      </>
                    ) : supportsDesktopExtension(kind) ? (
                      <>
                        <p className="font-semibold text-neutral-100">
                          {walletText("walletDesktopHelpTitle", kind)}
                        </p>
                        <ol className="mt-2 list-decimal space-y-1 pl-5 leading-6 text-neutral-400">
                          <li>{t("walletDesktopHelpUnlock")}</li>
                          <li>{t("walletDesktopHelpSelect")}</li>
                          <li>{walletText("walletDesktopHelpRetry", kind)}</li>
                        </ol>
                        <div className="mt-3 grid gap-2 sm:grid-cols-2">
                          <button
                            type="button"
                            onClick={() => openWalletAppDirect(kind)}
                            disabled={busy}
                            className="rounded-full bg-ark-gold px-3 py-2 text-sm font-bold text-black transition hover:bg-ark-gold2 disabled:cursor-wait disabled:opacity-70"
                          >
                            {walletText("walletReconnectWallet", kind)}
                          </button>
                          <button
                            type="button"
                            onClick={() => openWalletInstall(kind)}
                            className="rounded-full border border-ark-gold/50 px-3 py-2 text-sm font-semibold text-ark-gold transition hover:bg-ark-gold/10"
                          >
                            {walletText("walletInstallWallet", kind)}
                          </button>
                        </div>
                      </>
                    ) : (
                      <>
                        <p className="font-semibold text-neutral-100">
                          {walletText("walletDesktopImTokenTitle", kind)}
                        </p>
                        <p className="mt-2 text-sm leading-6 text-neutral-400">
                          {walletText("walletDesktopImTokenDesc", kind)}
                        </p>
                        <button
                          type="button"
                          onClick={() => openWalletInstall(kind)}
                          className="mt-3 w-full rounded-full border border-ark-gold/50 px-3 py-2 text-sm font-semibold text-ark-gold transition hover:bg-ark-gold/10"
                        >
                          {walletText("walletDownloadApp", kind)}
                        </button>
                      </>
                    )}
                  </div>
                ) : null}
              </div>
            );
          })}
        </div>

        {error ? (
          <p className="mt-4 rounded-2xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-200">
            {error}
          </p>
        ) : null}
      </div>
    </div>
  );
}

function walletNameKey(kind: WalletKind): string {
  return kind === "tokenPocket" ? "walletTokenPocket" : "walletImToken";
}
