import type { TupleToUnion } from './utils/type-utils.js';

/**
 * Represents the blockchain platform type
 * Used to distinguish between different blockchain ecosystems
 */
export enum ChainType {
  EVM = 'EVM',
  Solana = 'Solana',
  Sui = 'Sui',
}

/**
 * Enum of chain IDs for supported blockchains
 * EVM chains use their standard chain IDs
 * Non-EVM chains use custom assigned IDs
 */
export enum ChainID {
  Arbitrum = 42161,
  Optimism = 10,
  Base = 8453,
  Hyperliquid = 999,
  Solana = 7565164,
  Sui = 101,
}

/**
 * Array of chain IDs that are supported by the SDK
 * Used as a source of truth for type generation
 */
export const SupportedChains = [
  ChainID.Arbitrum,
  ChainID.Base,
  ChainID.Optimism,
  ChainID.Hyperliquid,
  ChainID.Solana,
  ChainID.Sui,
] as const;

/**
 * Type utility to identify chains not in the SupportedChains array
 * @internal
 */
type UnsupportedChain = Exclude<ChainID, TupleToUnion<typeof SupportedChains>>;

/**
 * Type representing chains that are supported by the SDK
 * Derived from the SupportedChains array
 */
export type SupportedChain = Exclude<ChainID, UnsupportedChain>;

export type SupportedSolanaChain = 7565164;
export type SupportedSuiChain = 101;
export type SupportedEvmChain = Exclude<ChainID, SupportedSolanaChain | SupportedSuiChain>;

export function isEvmChain(chainId: ChainID): chainId is SupportedEvmChain {
  return chainId !== 7565164 && chainId !== 101;
}

/**
 * Type guard that checks if a chain ID is among the supported chains
 * @param chain - The chain ID to check
 * @returns Boolean indicating if the chain is supported
 */
export const isSupportedChain = (chain: unknown): chain is SupportedChain => {
  if (typeof chain !== 'number') return false;
  return (SupportedChains as readonly number[]).includes(chain);
};

/**
 * Maps chain IDs to their corresponding chain types
 * Used to determine which SDK implementation to use for a given chain
 */
export const chainIdToChainTypeMap = {
  [ChainID.Arbitrum]: ChainType.EVM,
  [ChainID.Base]: ChainType.EVM,
  [ChainID.Optimism]: ChainType.EVM,
  [ChainID.Hyperliquid]: ChainType.EVM,
  [ChainID.Solana]: ChainType.Solana,
  [ChainID.Sui]: ChainType.Sui,
} as const;
