'use client';
/**
 * WalletAuthContext — Multi-wallet connection for Vaultfire Agent Hub.
 *
 * Supports: Coinbase Wallet, Base Wallet, MetaMask, WalletConnect.
 * The app is fully public. Wallet connection is optional and only required
 * for actions that need signing (register agent, create bond, claim VNS name).
 */
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import type { WalletOption } from '../components/WalletModal';

interface WalletAuthState {
  isUnlocked: boolean;
  address: string | null;
  chainId: number | null;
  isRestoring: boolean;
  activeWallet: WalletOption | null;
  connect: () => void;
  connectWallet: (wallet: WalletOption) => Promise<void>;
  logout: () => void;
  modalOpen: boolean;
  setModalOpen: (open: boolean) => void;
  connecting: WalletOption | null;
  unlock: (pk: string, mnemonic: string, address: string) => Promise<void>;
}

const WalletAuthContext = createContext<WalletAuthState>({
  isUnlocked: false,
  address: null,
  chainId: null,
  isRestoring: false,
  activeWallet: null,
  connect: () => {},
  connectWallet: async () => {},
  logout: () => {},
  modalOpen: false,
  setModalOpen: () => {},
  connecting: null,
  unlock: async () => {},
});

async function initCoinbaseWallet(): Promise<any> {
  const { CoinbaseWalletSDK } = await import('@coinbase/wallet-sdk');
  const sdk = new CoinbaseWalletSDK({
    appName: 'Vaultfire Agent Hub',
    appLogoUrl: 'https://theloopbreaker.com/favicon.ico',
  });
  return sdk.makeWeb3Provider({ options: 'smartWalletOnly' });
}

async function initWalletConnect(): Promise<any> {
  const { default: EthereumProvider } = await import('@walletconnect/ethereum-provider');
  const provider = await EthereumProvider.init({
    projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID || 'a4e7d6e2c7b3f1d0e8a9b2c3d4e5f6a7',
    chains: [8453],
    optionalChains: [1, 43114],
    showQrModal: true,
    metadata: {
      name: 'Vaultfire Agent Hub',
      description: 'The Trust Layer for the Agentic Web',
      url: 'https://theloopbreaker.com',
      icons: ['https://theloopbreaker.com/favicon.ico'],
    },
  });
  await provider.connect();
  return provider;
}

export function WalletAuthProvider({ children }: { children: React.ReactNode }) {
  const [address, setAddress] = useState<string | null>(null);
  const [chainId, setChainId] = useState<number | null>(null);
  const [isRestoring, setIsRestoring] = useState(true);
  const [activeWallet, setActiveWallet] = useState<WalletOption | null>(null);
  const [modalOpen, setModalOpen] = useState(false);
  const [connecting, setConnecting] = useState<WalletOption | null>(null);

  useEffect(() => {
    if (typeof window === 'undefined') { setIsRestoring(false); return; }
    const eth = (window as any).ethereum;
    if (!eth) { setIsRestoring(false); return; }
    eth.request({ method: 'eth_accounts' })
      .then((accounts: string[]) => {
        if (accounts && accounts.length > 0) {
          setAddress(accounts[0]);
          if (eth.isCoinbaseWallet) setActiveWallet('coinbase');
          else if (eth.isMetaMask) setActiveWallet('metamask');
          else setActiveWallet('metamask');
          eth.request({ method: 'eth_chainId' })
            .then((cid: string) => setChainId(parseInt(cid, 16))).catch(() => {});
        }
      })
      .catch(() => {})
      .finally(() => setIsRestoring(false));
    const onAcc = (accounts: string[]) => {
      if (accounts.length === 0) { setAddress(null); setActiveWallet(null); }
      else setAddress(accounts[0]);
    };
    const onChain = (cid: string) => setChainId(parseInt(cid, 16));
    eth.on?.('accountsChanged', onAcc);
    eth.on?.('chainChanged', onChain);
    return () => { eth.removeListener?.('accountsChanged', onAcc); eth.removeListener?.('chainChanged', onChain); };
  }, []);

  const connectWallet = useCallback(async (wallet: WalletOption) => {
    setConnecting(wallet);
    try {
      let wp: any;
      if (wallet === 'coinbase' || wallet === 'base') {
        wp = await initCoinbaseWallet();
        const accounts: string[] = await wp.request({ method: 'eth_requestAccounts' });
        if (accounts?.length) {
          setAddress(accounts[0]); setActiveWallet(wallet);
          const cid: string = await wp.request({ method: 'eth_chainId' });
          setChainId(parseInt(cid, 16));
        }
      } else if (wallet === 'metamask') {
        const eth = (window as any).ethereum;
        if (!eth || !eth.isMetaMask) { window.open('https://metamask.io/download/', '_blank'); setConnecting(null); return; }
        const accounts: string[] = await eth.request({ method: 'eth_requestAccounts' });
        if (accounts?.length) {
          setAddress(accounts[0]); setActiveWallet('metamask');
          const cid: string = await eth.request({ method: 'eth_chainId' });
          setChainId(parseInt(cid, 16));
        }
      } else if (wallet === 'walletconnect') {
        wp = await initWalletConnect();
        const accounts: string[] = await wp.request({ method: 'eth_accounts' });
        if (accounts?.length) {
          setAddress(accounts[0]); setActiveWallet('walletconnect');
          const cid: string = await wp.request({ method: 'eth_chainId' });
          setChainId(parseInt(cid, 16));
        }
      }
      setModalOpen(false);
    } catch (err: any) {
      console.warn('[WalletAuth] Connect rejected:', err?.message);
    } finally { setConnecting(null); }
  }, []);

  const connect = useCallback(() => { setModalOpen(true); }, []);
  const logout = useCallback(() => { setAddress(null); setChainId(null); setActiveWallet(null); setModalOpen(false); }, []);
  const unlock = useCallback(async (_pk: string, _mnemonic: string, addr: string) => { setAddress(addr); }, []);

  return (
    <WalletAuthContext.Provider value={{
      isUnlocked: !!address, address, chainId, isRestoring, activeWallet,
      connect, connectWallet, logout, modalOpen, setModalOpen, connecting, unlock,
    }}>
      {children}
    </WalletAuthContext.Provider>
  );
}

export function useWalletAuth(): WalletAuthState {
  return useContext(WalletAuthContext);
}
