/**
 * Add ChainID 138 to MetaMask
 */

import { EthereumProvider, AddEthereumChainParameter, MetaMaskError } from './types';
import { NETWORK_METADATA } from './config';

/**
 * Get the Ethereum provider (MetaMask)
 */
export function getEthereumProvider(): EthereumProvider | null {
  if (typeof window === 'undefined') {
    return null;
  }

  const provider = window.ethereum;
  if (!provider) {
    throw new Error('MetaMask is not installed. Please install MetaMask to continue.');
  }

  if (!provider.isMetaMask) {
    throw new Error('The detected wallet is not MetaMask. Please use MetaMask to continue.');
  }

  return provider;
}

/**
 * Add ChainID 138 to MetaMask
 * @param customMetadata - Optional custom network metadata (defaults to standard config)
 * @returns Promise that resolves when the network is added
 */
export async function addNetwork(
  customMetadata?: Partial<AddEthereumChainParameter>
): Promise<void> {
  const provider = getEthereumProvider();

  const metadata: AddEthereumChainParameter = {
    ...NETWORK_METADATA,
    ...customMetadata,
  };

  try {
    await provider.request({
      method: 'wallet_addEthereumChain',
      params: [metadata],
    });
  } catch (error) {
    const metamaskError = error as MetaMaskError;
    
    // Error code 4902 means the chain is already added, but that's actually error 4902 from switchNetwork
    // For addNetwork, if we get 4902, it means the chain is already added, so we should switch
    if (metamaskError.code === 4902) {
      // Chain is already added, try to switch to it
      try {
        await provider.request({
          method: 'wallet_switchEthereumChain',
          params: [{ chainId: NETWORK_METADATA.chainId }],
        });
      } catch (switchError) {
        const switchErr = switchError as MetaMaskError;
        throw new Error(
          `Failed to switch network: ${switchErr.message || 'Unknown error'}`
        );
      }
      return;
    }
    
    throw new Error(
      `Failed to add network: ${metamaskError.message || 'Unknown error'}`
    );
  }
}

/**
 * Check if ChainID 138 is already added to MetaMask
 */
export async function isNetworkAdded(): Promise<boolean> {
  const provider = getEthereumProvider();
  
  try {
    const chainId = await provider.request({ method: 'eth_chainId' }) as string;
    return chainId === NETWORK_METADATA.chainId;
  } catch {
    return false;
  }
}

/**
 * Add or switch to ChainID 138
 * This is a convenience function that adds the network if it's not already added,
 * or switches to it if it is.
 */
export async function addOrSwitchNetwork(): Promise<void> {
  const provider = getEthereumProvider();
  
  try {
    // Try to switch first (network might already be added)
    await provider.request({
      method: 'wallet_switchEthereumChain',
      params: [{ chainId: NETWORK_METADATA.chainId }],
    });
  } catch (error) {
    const metamaskError = error as MetaMaskError;
    
    // If switch fails with 4902, network is not added, so add it
    if (metamaskError.code === 4902) {
      return addNetwork();
    }
    
    // Other errors should be thrown
    throw new Error(
      `Failed to switch network: ${metamaskError.message || 'Unknown error'}`
    );
  }
}

