"use client";

/**
 * Unified login methods — same weight for each path into the dashboard:
 * 1. Email OTP (Briven)
 * 2. Konnos OAuth (Briven)
 * 3. MetaMask (browser wallet)
 * 4. mavi wallet (local encrypted vault — create at /portal/mavi)
 */

import { injected } from "@wagmi/connectors/injected";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useRef, useState } from "react";
import { useAccount, useConnect, useDisconnect } from "wagmi";

import { usePortalAuth } from "@/components/auth/portal-auth-provider";
import { Button } from "@/components/ui/button";
import { ErrorBanner } from "@/components/ui/error-banner";
import { Input } from "@/components/ui/input";
import { PasswordInput } from "@/components/ui/password-input";
import {
  MetaMaskLogo,
  MaviWalletLogo,
} from "@/components/wallet/wallet-logos";
import { getBrivenAuth } from "@/lib/auth";
import { createDemoWalletSession } from "@/lib/demo-session";
import {
  type LoginMethodId,
  readLastLoginMethod,
  writeLastLoginMethod,
} from "@/lib/last-login";
import { hasVault, unlockVault } from "@/lib/mavi/storage";
import { establishPortalSession } from "@/lib/portal-session";

const OTP_LEN = 6;

function LastUsedBadge({ show }: { show: boolean }) {
  if (!show) return null;
  return (
    <span className="rounded-full border border-accent/40 bg-accent-muted px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-accent-hover">
      Last used to sign in
    </span>
  );
}

export function SignInMethods({
  redirectTo = "/portal/dashboard",
}: {
  redirectTo?: string;
}) {
  const router = useRouter();
  const auth = getBrivenAuth();
  const { setDemoSession, clearDemo } = usePortalAuth();
  const { address, isConnected } = useAccount();
  const { connect, isPending, error: walletError } = useConnect();
  const { disconnect } = useDisconnect();

  const [email, setEmail] = useState("");
  const [otp, setOtp] = useState("");
  const [otpOpen, setOtpOpen] = useState(false);
  const [otpSent, setOtpSent] = useState(false);
  const [busy, setBusy] = useState(false);
  const [message, setMessage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [maviOpen, setMaviOpen] = useState(false);
  const [maviPassword, setMaviPassword] = useState("");
  const [maviHasVault, setMaviHasVault] = useState(false);
  const [lastUsed, setLastUsed] = useState<LoginMethodId | null>(null);
  const verifyingRef = useRef(false);
  const lastTriedRef = useRef("");

  useEffect(() => {
    setLastUsed(readLastLoginMethod());
    // Open email panel if that was last used
    if (readLastLoginMethod() === "email") setOtpOpen(true);
    if (readLastLoginMethod() === "mavi") setMaviOpen(true);
    setMaviHasVault(hasVault());
  }, []);

  const remember = useCallback((method: LoginMethodId) => {
    writeLastLoginMethod(method);
    setLastUsed(method);
  }, []);

  const goIn = useCallback(
    async (opts: {
      userId: string;
      method: "email" | "wallet" | "konnos";
      loginMethodId: LoginMethodId;
      email?: string;
      walletAddress?: string;
    }) => {
      remember(opts.loginMethodId);
      if (opts.method === "wallet" && opts.walletAddress) {
        setDemoSession(createDemoWalletSession(opts.walletAddress));
      }
      await establishPortalSession({
        userId: opts.userId,
        email: opts.email,
        method: opts.method,
        walletAddress: opts.walletAddress,
      });
      window.dispatchEvent(new Event("krypco-auth-change"));
      router.push(redirectTo);
      router.refresh();
    },
    [redirectTo, remember, router, setDemoSession],
  );

  const verifyOtp = useCallback(
    async (code: string) => {
      if (!auth) return;
      const cleaned = code.replace(/\s/g, "").trim();
      if (cleaned.length < 4) return;
      if (verifyingRef.current) return;
      if (lastTriedRef.current === cleaned) return;

      verifyingRef.current = true;
      lastTriedRef.current = cleaned;
      setError(null);
      setBusy(true);
      setMessage("Checking code…");
      try {
        const loginEmail = email.trim().toLowerCase();
        const r = await auth.signIn.otpVerify({
          email: loginEmail,
          otp: cleaned,
        });
        if (!r.ok) {
          setError(r.message || r.code);
          setMessage(null);
          lastTriedRef.current = "";
          return;
        }
        const userId =
          ("userId" in r && typeof r.userId === "string" && r.userId) ||
          `user_${loginEmail}`;
        setMessage("Signed in — opening dashboard…");
        await goIn({
          userId,
          method: "email",
          loginMethodId: "email",
          email: loginEmail,
        });
      } catch (e) {
        setError(e instanceof Error ? e.message : "Could not verify code");
        setMessage(null);
        lastTriedRef.current = "";
      } finally {
        setBusy(false);
        verifyingRef.current = false;
      }
    },
    [auth, email, goIn],
  );

  async function sendOtp() {
    if (!auth) {
      setError("Briven Auth is not configured.");
      return;
    }
    setError(null);
    setMessage(null);
    setBusy(true);
    try {
      const r = await auth.signIn.otpRequest({
        email: email.trim(),
        redirectTo,
      });
      if (!r.ok) {
        setError(r.message || r.code);
        return;
      }
      setOtpSent(true);
      setOtp("");
      lastTriedRef.current = "";
      setMessage("Check your email for a one-time code.");
    } catch (e) {
      setError(e instanceof Error ? e.message : "Could not send code");
    } finally {
      setBusy(false);
    }
  }

  function onOtpChange(raw: string) {
    const digits = raw.replace(/\D/g, "").slice(0, OTP_LEN);
    setOtp(digits);
    setError(null);
    if (digits.length === OTP_LEN) void verifyOtp(digits);
  }

  function startKonnos() {
    if (!auth) {
      setError("Briven Auth is not configured for Konnos.");
      return;
    }
    setError(null);
    remember("konnos");
    const { redirectUrl } = auth.signIn.social({
      provider: "konnos",
      redirectTo:
        typeof window !== "undefined"
          ? `${window.location.origin}${redirectTo}`
          : redirectTo,
    });
    window.location.assign(redirectUrl);
  }

  function startMetaMask() {
    setError(null);
    setMaviOpen(false);
    setMessage(null);
    connect(
      { connector: injected() },
      {
        onSuccess: (data) => {
          const addr = data.accounts[0];
          if (!addr) {
            setError("No account returned from MetaMask.");
            return;
          }
          setMessage("Wallet connected — opening dashboard…");
          void goIn({
            userId: `wallet_${addr.toLowerCase()}`,
            method: "wallet",
            loginMethodId: "metamask",
            walletAddress: addr,
          });
        },
        onError: (e) => {
          const msg = e.message || "MetaMask connection failed.";
          if (/provider|injected|ethereum|meta\s*mask/i.test(msg)) {
            setError(
              "MetaMask was not found. Install the MetaMask browser extension, then try again.",
            );
          } else if (/reject|denied|user/i.test(msg)) {
            setError("Connection was cancelled in MetaMask. You can try again.");
          } else {
            setError(msg);
          }
        },
      },
    );
  }

  function startMavi() {
    setError(null);
    setMessage(null);
    setMaviHasVault(hasVault());
    setMaviOpen((o) => !o);
  }

  async function unlockMaviAndEnter() {
    setError(null);
    if (!maviPassword) {
      setError("Enter your mavi password.");
      return;
    }
    setBusy(true);
    setMessage("Unlocking mavi…");
    try {
      const u = await unlockVault(maviPassword);
      setMessage("mavi unlocked — opening dashboard…");
      await goIn({
        userId: `mavi_${u.address.toLowerCase()}`,
        method: "wallet",
        loginMethodId: "mavi",
        walletAddress: u.address,
      });
    } catch (e) {
      setMessage(null);
      setError(e instanceof Error ? e.message : "mavi unlock failed");
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="space-y-4">
      <p className="text-sm text-muted-foreground leading-relaxed">
        Pick any method below. All of them take you into the same dashboard.
      </p>

      {/* 1 — Email OTP */}
      <div
        className={
          lastUsed === "email"
            ? "rounded-xl border border-accent/50 bg-card/50 p-4 ring-1 ring-accent/20"
            : "rounded-xl border border-border bg-card/50 p-4"
        }
      >
        <button
          type="button"
          className="flex w-full flex-wrap items-center justify-between gap-2 text-left"
          onClick={() => setOtpOpen((o) => !o)}
        >
          <span className="flex flex-wrap items-center gap-2">
            <span className="text-sm font-medium">Email code (OTP)</span>
            <LastUsedBadge show={lastUsed === "email"} />
          </span>
          <span className="text-xs text-muted-foreground">
            {otpOpen ? "Hide" : "Open"}
          </span>
        </button>
        {otpOpen ? (
          <div className="mt-4 space-y-3 border-t border-border pt-4">
            <div className="space-y-2">
              <label htmlFor="signin-email" className="text-sm font-medium">
                Email
              </label>
              <Input
                id="signin-email"
                type="email"
                autoComplete="email"
                placeholder="you@company.com"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                disabled={busy}
              />
            </div>
            <Button
              type="button"
              className="w-full"
              disabled={busy || !email.includes("@")}
              onClick={() => void sendOtp()}
            >
              {otpSent ? "Resend email code" : "Send email code"}
            </Button>
            {otpSent ? (
              <div className="flex flex-col items-center pt-2 text-center">
                <label
                  htmlFor="signin-otp"
                  className="mb-2 text-sm font-medium"
                >
                  Code from email
                </label>
                <Input
                  id="signin-otp"
                  inputMode="numeric"
                  autoComplete="one-time-code"
                  autoFocus
                  placeholder="······"
                  maxLength={OTP_LEN}
                  value={otp}
                  onChange={(e) => onOtpChange(e.target.value)}
                  disabled={busy}
                  className="mx-auto h-14 w-full max-w-[16rem] text-center font-mono text-2xl tracking-[0.35em]"
                />
                <p className="mt-2 text-xs text-muted-foreground">
                  All {OTP_LEN} digits → auto sign-in
                </p>
              </div>
            ) : null}
          </div>
        ) : null}
      </div>

      <div className="relative py-1">
        <div className="absolute inset-0 flex items-center">
          <span className="w-full border-t border-border" />
        </div>
        <div className="relative flex justify-center text-[11px] uppercase tracking-wide text-muted-foreground">
          <span className="bg-background px-2">or continue with</span>
        </div>
      </div>

      {/* 2 — Konnos */}
      <div className="space-y-1.5">
        <div className="flex justify-end px-0.5">
          <LastUsedBadge show={lastUsed === "konnos"} />
        </div>
        <Button
          type="button"
          variant="outline"
          className={
            lastUsed === "konnos"
              ? "inline-flex h-12 w-full items-center justify-center gap-2.5 ring-1 ring-accent/30"
              : "inline-flex h-12 w-full items-center justify-center gap-2.5"
          }
          disabled={busy}
          onClick={startKonnos}
        >
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img
            src="/konnos.svg"
            alt=""
            width={22}
            height={22}
            className="h-[22px] w-[22px] shrink-0 object-contain"
            aria-hidden
          />
          Konnos
        </Button>
      </div>

      {/* 3 — MetaMask */}
      <div className="space-y-1.5">
        <div className="flex justify-end px-0.5">
          <LastUsedBadge show={lastUsed === "metamask"} />
        </div>
        <Button
          type="button"
          variant="outline"
          className={
            lastUsed === "metamask"
              ? "inline-flex h-12 w-full items-center justify-center gap-2.5 ring-1 ring-accent/30"
              : "inline-flex h-12 w-full items-center justify-center gap-2.5"
          }
          disabled={busy || isPending}
          onClick={startMetaMask}
        >
          <MetaMaskLogo size={22} />
          {isPending ? "Connecting MetaMask…" : "MetaMask"}
        </Button>
      </div>

      {/* 4 — mavi wallet */}
      <div
        className={
          lastUsed === "mavi"
            ? "rounded-xl border border-accent/50 bg-card/50 p-4 ring-1 ring-accent/20"
            : "rounded-xl border border-border bg-card/50 p-4"
        }
      >
        <div className="flex justify-end px-0.5">
          <LastUsedBadge show={lastUsed === "mavi"} />
        </div>
        <Button
          type="button"
          variant="outline"
          className="inline-flex h-12 w-full items-center justify-center gap-2.5"
          disabled={busy}
          onClick={startMavi}
        >
          <MaviWalletLogo size={22} />
          mavi wallet
        </Button>
        {maviOpen ? (
          <div className="mt-4 space-y-3 border-t border-border pt-4">
            {maviHasVault ? (
              <>
                <p className="text-xs text-muted-foreground leading-relaxed">
                  Unlock the mavi vault saved in this browser with your
                  password.
                </p>
                <PasswordInput
                  id="signin-mavi-password"
                  label="mavi password"
                  hideLabel
                  autoComplete="current-password"
                  placeholder="mavi password"
                  value={maviPassword}
                  onChange={setMaviPassword}
                  disabled={busy}
                  onEnter={() => void unlockMaviAndEnter()}
                />
                <Button
                  type="button"
                  className="w-full"
                  disabled={busy || maviPassword.length < 1}
                  onClick={() => void unlockMaviAndEnter()}
                >
                  Unlock and sign in
                </Button>
              </>
            ) : (
              <div className="space-y-2 text-sm text-muted-foreground leading-relaxed">
                <p>No mavi wallet on this browser yet.</p>
                <div className="flex flex-col gap-2">
                  <Link
                    href="/portal/mavi/create"
                    className="inline-flex h-10 items-center justify-center gap-2 rounded-md border border-border px-3 font-medium text-foreground hover:bg-muted"
                  >
                    <MaviWalletLogo size={16} />
                    Create mavi wallet
                  </Link>
                  <Link
                    href="/portal/mavi/import"
                    className="inline-flex h-10 items-center justify-center rounded-md px-3 text-accent-hover hover:underline"
                  >
                    Import recovery phrase
                  </Link>
                </div>
              </div>
            )}
          </div>
        ) : null}
      </div>

      {isConnected && address ? (
        <div className="rounded-lg border border-border bg-muted/30 px-3 py-2 text-center">
          <p className="font-mono text-xs break-all text-muted-foreground">
            {address}
          </p>
          <Button
            type="button"
            variant="ghost"
            size="sm"
            className="mt-1"
            onClick={() => {
              disconnect();
              clearDemo();
            }}
          >
            Disconnect wallet
          </Button>
        </div>
      ) : null}

      {message ? (
        <p className="text-center text-sm text-proof" role="status">
          {message}
        </p>
      ) : null}
      {error || walletError ? (
        <ErrorBanner title="Could not sign in">
          {error ||
            (walletError?.message?.includes("provider")
              ? "MetaMask was not found. Install the extension, then try again."
              : walletError?.message)}
        </ErrorBanner>
      ) : null}
    </div>
  );
}
