"use client";

import {
  useCallback,
  useEffect,
  useState,
  type ReactNode,
} from "react";

import { usePortalAuth } from "@/components/auth/portal-auth-provider";
import {
  clearPortalSession,
  fetchPortalSession,
  type AuthMethod,
} from "@/lib/portal-session";

export type PortalIdentity = {
  isLoading: boolean;
  isSignedIn: boolean;
  label: string | null;
  source: "briven" | "demo" | "wallet" | "konnos" | null;
  userId: string | null;
  walletAddress: string | null;
  method: AuthMethod | null;
  signOut: () => Promise<void>;
};

/**
 * Identity for dashboard gates. Any login method (email OTP, Konnos, MetaMask,
 * later mavi) mints first-party /api/session so the user stays signed in.
 */
export function IdentityConsumer({
  children,
}: {
  children: (identity: PortalIdentity) => ReactNode;
}) {
  const { brivenConfigured } = usePortalAuth();
  if (brivenConfigured) {
    return <SessionIdentityConsumer>{children}</SessionIdentityConsumer>;
  }
  return <DemoIdentityConsumer>{children}</DemoIdentityConsumer>;
}

function DemoIdentityConsumer({
  children,
}: {
  children: (identity: PortalIdentity) => ReactNode;
}) {
  const portal = usePortalAuth();
  const identity: PortalIdentity = {
    isLoading: false,
    isSignedIn: Boolean(portal.demoSession),
    label: portal.demoSession?.label ?? null,
    source: portal.demoSession?.kind ?? null,
    userId: portal.demoSession?.userId ?? null,
    walletAddress: portal.demoSession?.walletAddress ?? null,
    method: portal.demoSession?.kind === "wallet" ? "wallet" : "demo",
    signOut: async () => {
      portal.clearDemo();
    },
  };
  return <>{children(identity)}</>;
}

function SessionIdentityConsumer({
  children,
}: {
  children: (identity: PortalIdentity) => ReactNode;
}) {
  const portal = usePortalAuth();
  const [loading, setLoading] = useState(true);
  const [userId, setUserId] = useState<string | null>(null);
  const [email, setEmail] = useState<string | null>(null);
  const [method, setMethod] = useState<AuthMethod | null>(null);
  const [walletAddress, setWalletAddress] = useState<string | null>(null);

  const refresh = useCallback(async () => {
    const s = await fetchPortalSession();
    if (s.authenticated) {
      setUserId(s.userId);
      setEmail(s.email ?? null);
      setMethod(s.method ?? null);
      setWalletAddress(s.walletAddress ?? null);
    } else if (portal.demoSession) {
      setUserId(portal.demoSession.userId);
      setEmail(
        portal.demoSession.kind === "demo" ? portal.demoSession.label : null,
      );
      setMethod(
        portal.demoSession.kind === "wallet" ? "wallet" : "demo",
      );
      setWalletAddress(portal.demoSession.walletAddress ?? null);
    } else {
      setUserId(null);
      setEmail(null);
      setMethod(null);
      setWalletAddress(null);
    }
    setLoading(false);
  }, [portal.demoSession]);

  useEffect(() => {
    void refresh();
    const onFocus = () => void refresh();
    window.addEventListener("focus", onFocus);
    window.addEventListener("krypco-auth-change", onFocus);
    return () => {
      window.removeEventListener("focus", onFocus);
      window.removeEventListener("krypco-auth-change", onFocus);
    };
  }, [refresh]);

  const signedIn = Boolean(userId) || Boolean(portal.demoSession);

  const source: PortalIdentity["source"] = (() => {
    if (method === "wallet" || portal.demoSession?.kind === "wallet")
      return "wallet";
    if (method === "konnos") return "konnos";
    if (method === "demo" || portal.demoSession?.kind === "demo") return "demo";
    if (userId) return "briven";
    return null;
  })();

  const label =
    email ||
    (walletAddress
      ? `${walletAddress.slice(0, 6)}…${walletAddress.slice(-4)}`
      : null) ||
    portal.demoSession?.label ||
    userId;

  const identity: PortalIdentity = {
    isLoading: loading,
    isSignedIn: signedIn,
    label,
    source,
    userId: userId || portal.demoSession?.userId || null,
    walletAddress:
      walletAddress || portal.demoSession?.walletAddress || null,
    method:
      method ||
      (portal.demoSession?.kind === "wallet" ? "wallet" : null),
    signOut: async () => {
      try {
        await fetch("/api/auth/signout", {
          method: "POST",
          credentials: "include",
          headers: {
            "content-type": "application/json",
            rid: "session",
          },
          body: "{}",
        }).catch(() => null);
        await clearPortalSession();
      } finally {
        portal.clearDemo();
        setUserId(null);
        setEmail(null);
        setMethod(null);
        setWalletAddress(null);
        window.dispatchEvent(new Event("krypco-auth-change"));
      }
    },
  };
  return <>{children(identity)}</>;
}
