import { useConnectModal } from "@rainbow-me/rainbowkit";
import { QRCodeSVG } from "qrcode.react";
import { useEffect, useRef, useState } from "react";
import { useAccount, useSignMessage } from "wagmi";
import { useToast } from "../components/Toast";
import { useI18n } from "../i18n";
import {
  createTokenPocketLoginRequest,
  fetchTokenPocketLoginResult,
  requestWalletNonce,
  verifyWalletSignature,
  type TokenPocketLoginRequest,
} from "./api";
import { openWalletDeepLink } from "./deepLinks";
import { useWallet } from "./WalletProvider";

const pollIntervalMs = 1800;

type ModalState = "idle" | "tpLoading" | "tpPolling" | "rainbowSigning";

export function WalletLoginModal() {
  const { t } = useI18n();
  const { showToast } = useToast();
  const { closeLoginModal, completeLogin, loginModalOpen, signInInjected } =
    useWallet();
  const { openConnectModal } = useConnectModal();
  const { address, isConnected } = useAccount();
  const { signMessageAsync } = useSignMessage();
  const [state, setState] = useState<ModalState>("idle");
  const [error, setError] = useState("");
  const [tpRequest, setTpRequest] = useState<TokenPocketLoginRequest | null>(
    null,
  );
  const [rainbowPending, setRainbowPending] = useState(false);
  const rainbowSigningRef = useRef(false);

  const close = () => {
    if (state === "tpLoading" || state === "rainbowSigning") return;
    closeLoginModal();
    setError("");
  };

  useEffect(() => {
    if (!loginModalOpen || !tpRequest) return;
    if (state !== "tpPolling") return;

    let cancelled = false;
    const poll = async () => {
      try {
        const result = await fetchTokenPocketLoginResult(tpRequest.actionId);
        if (cancelled) return;
        if (result.status === "completed") {
          const verified = await verifyWalletSignature({
            address: result.address,
            message: result.message,
            signature: result.signature,
          });
          if (cancelled) return;
          completeLogin(verified.token, verified.wallet);
          showToast(t("walletLoginSuccess"));
          setState("idle");
          setTpRequest(null);
          return;
        }
        if (result.status === "expired" || result.status === "failed") {
          setState("idle");
          setError(result.error || t("walletTpExpired"));
        }
      } catch {
        if (!cancelled) setError(t("walletLoginFailed"));
      }
    };

    void poll();
    const timer = window.setInterval(() => void poll(), pollIntervalMs);
    return () => {
      cancelled = true;
      window.clearInterval(timer);
    };
  }, [completeLogin, loginModalOpen, state, tpRequest, t, showToast]);

  useEffect(() => {
    if (!rainbowPending || !isConnected || !address) return;
    if (rainbowSigningRef.current) return;
    rainbowSigningRef.current = true;
    setState("rainbowSigning");
    setError("");

    void (async () => {
      try {
        const nonce = await requestWalletNonce(address);
        const signature = await signMessageAsync({ message: nonce.message });
        const verified = await verifyWalletSignature({
          address,
          message: nonce.message,
          signature,
        });
        completeLogin(verified.token, verified.wallet);
        showToast(t("walletLoginSuccess"));
      } catch (err) {
        const message =
          err instanceof Error ? err.message : t("walletLoginFailed");
        setError(message || t("walletLoginFailed"));
        showToast(t("walletLoginFailed"), "error");
      } finally {
        setState("idle");
        setRainbowPending(false);
        rainbowSigningRef.current = false;
      }
    })();
  }, [
    address,
    isConnected,
    rainbowPending,
    showToast,
    signMessageAsync,
    t,
    completeLogin,
  ]);

  if (!loginModalOpen) return null;

  const startInjected = async () => {
    setError("");
    setState("idle");
    await signInInjected().catch(() => undefined);
  };

  const startTokenPocketQr = async () => {
    setError("");
    setState("tpLoading");
    try {
      const req = await createTokenPocketLoginRequest();
      setTpRequest(req);
      setState("tpPolling");
    } catch {
      setState("idle");
      setError(t("walletTpQrFailed"));
    }
  };

  const startRainbowFallback = () => {
    setError("");
    setRainbowPending(true);
    openConnectModal?.();
    if (!openConnectModal) setError(t("walletRainbowUnavailable"));
  };

  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-[520px] 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-4">
          <div>
            <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}
            className="rounded-full border border-white/10 px-3 py-1.5 text-sm text-neutral-300 transition hover:border-ark-gold/50 hover:text-ark-gold"
          >
            {t("close")}
          </button>
        </div>

        <div className="mt-5 grid gap-3">
          <button
            type="button"
            onClick={() => void startInjected()}
            className="rounded-2xl border border-ark-gold/40 bg-ark-gold/10 p-4 text-left transition hover:bg-ark-gold/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/80"
          >
            <span className="block font-semibold text-ark-gold2">
              {t("walletInjected")}
            </span>
            <span className="mt-1 block text-sm text-neutral-400">
              {t("walletInjectedDesc")}
            </span>
          </button>

          <div className="rounded-2xl border border-white/10 bg-white/[0.03] p-4">
            <div className="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
              <div>
                <h3 className="font-semibold text-white">
                  {t("walletTokenPocketQr")}
                </h3>
                <p className="mt-1 text-sm leading-6 text-neutral-400">
                  {t("walletTokenPocketQrDesc")}
                </p>
              </div>
              <button
                type="button"
                onClick={() => void startTokenPocketQr()}
                disabled={state === "tpLoading"}
                className="shrink-0 rounded-full bg-ark-gold px-4 py-2 text-sm font-semibold text-black transition hover:bg-ark-gold2 disabled:cursor-wait disabled:opacity-70"
              >
                {state === "tpLoading" ? t("loading") : t("walletGenerateQr")}
              </button>
            </div>
            {tpRequest ? (
              <div className="mt-4 grid place-items-center gap-3 rounded-2xl bg-white p-4 text-center">
                <QRCodeSVG value={tpRequest.qrUrl} size={196} level="M" />
                <p className="text-xs font-medium text-neutral-700">
                  {t("walletQrUseAnotherDevice")}
                </p>
              </div>
            ) : null}
          </div>

          <div className="grid gap-2 sm:grid-cols-3">
            <button
              type="button"
              onClick={() => openWalletDeepLink("tokenPocket")}
              className="rounded-2xl border border-white/10 bg-[#20202a] px-4 py-3 text-sm font-semibold text-neutral-100 transition hover:border-ark-gold/40"
            >
              {t("walletOpenTokenPocket")}
            </button>
            <button
              type="button"
              onClick={() => openWalletDeepLink("metaMask")}
              className="rounded-2xl border border-white/10 bg-[#20202a] px-4 py-3 text-sm font-semibold text-neutral-100 transition hover:border-ark-gold/40"
            >
              {t("walletOpenMetaMask")}
            </button>
            <button
              type="button"
              onClick={() => openWalletDeepLink("imToken")}
              className="rounded-2xl border border-white/10 bg-[#20202a] px-4 py-3 text-sm font-semibold text-neutral-100 transition hover:border-ark-gold/40"
            >
              {t("walletOpenImToken")}
            </button>
          </div>

          <div className="rounded-2xl border border-dashed border-white/15 p-4">
            <div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
              <div>
                <h3 className="font-semibold text-white">
                  {t("walletRainbowFallback")}
                </h3>
                <p className="mt-1 text-sm leading-6 text-neutral-400">
                  {t("walletRainbowFallbackDesc")}
                </p>
              </div>
              <button
                type="button"
                onClick={startRainbowFallback}
                disabled={state === "rainbowSigning"}
                className="shrink-0 rounded-full border border-ark-gold/50 px-4 py-2 text-sm font-semibold text-ark-gold transition hover:bg-ark-gold/10 disabled:cursor-wait disabled:opacity-70"
              >
                {state === "rainbowSigning"
                  ? t("walletSigning")
                  : t("walletOpenRainbow")}
              </button>
            </div>
            <p className="mt-3 text-xs leading-5 text-yellow-200/80">
              {t("walletNetworkWarning")}
            </p>
          </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>
  );
}
