

import { callExplorerApi } from '../../core/explorerApi';
import { formatTokenAmount, truncateString } from '../../utils/formatters';
import { getTokenInfo } from '../tokens/tokens';


export interface TransactionMethod {
  signature: string;
  name: string;
  params?: any; 
}


export const EVENT_SIGNATURES = {
  Transfer: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
  Approval: '0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925',
  
  Mint: '0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885',
  Burn: '0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5',
  Pause: '0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258',
  Unpause: '0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa',
  
  OwnershipTransferred: '0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0',
  
  RoleGranted: '0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d',
  RoleRevoked: '0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b',
};


export const TOKEN_RELATED_EVENTS = [
  EVENT_SIGNATURES.Transfer,
  EVENT_SIGNATURES.Mint,
  EVENT_SIGNATURES.Burn
];

/**
 *
 * @param topic 
 * @returns 
 */
export function parseAddressFromTopic(topic: string): string {
  if (!topic || typeof topic !== 'string') {
    return '';
  }
  

  if (topic.length >= 42) {
    return '0x' + topic.substring(topic.length - 40).toLowerCase();
  }
  
  return topic.toLowerCase();
}

/**
 * 
 * @param signature 
 * @returns 
 */
export function getEventType(signature: string): string {
  for (const [name, sig] of Object.entries(EVENT_SIGNATURES)) {
    if (sig.toLowerCase() === signature.toLowerCase()) {
      return name;
    }
  }
  return 'Unknown';
}

/**
 *
 * 
 * @param event 
 * @returns 
 */
export async function enhanceEvent(event: any): Promise<any> {
  if (!event) return null;
  

  const enhancedEvent = { ...event };
  

  if (event.from_address || event.to_address || event.tx_hash) {
    enhancedEvent.transaction = {
      from: event.from_address,
      to: event.to_address,
      hash: event.tx_hash
    };
    
    if (event.method_signature || event.method_name) {
      enhancedEvent.transaction.method = {
        signature: event.method_signature || null,
        name: event.method_name || 'unknown'
      };
    }
  }
  
  enhancedEvent.technical = {
    signature: event.topics && event.topics[0] ? event.topics[0] : null,
    topics: event.topics || [],
    data: event.data || '0x',
    address: event.address || null,
    blockNumber: event.block_number,
    logIndex: event.log_index,
    method: event.method_signature ? {
      signature: event.method_signature,
      name: event.method_name || 'unknown'
    } : null
  };
  
  if (event.topics && event.topics[0]) {
    const signature = event.topics[0];
    const eventType = getEventType(signature);
    
    enhancedEvent.event_type = eventType;
    

    if (eventType === 'Transfer') {

      let from = '';
      
      if (event.raw_from) {
        from = parseAddressFromTopic(event.raw_from);
      } 
      else if (event.from_address) {
        from = event.from_address.toLowerCase();
      } 
      else if (event.topics && event.topics.length > 1) {
        from = parseAddressFromTopic(event.topics[1]);
      }
      
      let to = '';
      
      if (event.raw_to) {
        to = parseAddressFromTopic(event.raw_to);
      }
      else if (event.to_address && event.address && event.to_address.toLowerCase() !== event.address.toLowerCase()) {
        to = event.to_address.toLowerCase();
      }
      else if (event.topics && event.topics.length > 2) {
        to = parseAddressFromTopic(event.topics[2]);
      }
      
      const isTaxTransfer = from && to && from.toLowerCase() === to.toLowerCase();
      
      let tokenSymbol = event.token_symbol || 'TOKEN';
      let decimals = event.decimals || 18;
      
      if ((!event.token_symbol || event.token_symbol === 'TOKEN' || event.token_symbol === 'UNKNOWN') && event.address) {
        try {
          const tokenInfo = await getTokenInfo(event.address);
          if (tokenInfo) {
            tokenSymbol = tokenInfo.symbol || 'TOKEN';
            decimals = tokenInfo.decimals || 18;
          }
        } catch (error: any) {
          console.warn(`Failed to get token info for ${event.address}: ${error.message}`);
        }
      }
      

      const value = formatTokenAmount(event.data, decimals);
      
      enhancedEvent.token_transfer = {
        from,
        to,
        value,
        token_address: event.address || event.token_address,
        token_symbol: tokenSymbol,
        is_tax: isTaxTransfer
      };
      
      const shortFrom = truncateString(from);
      const shortTo = truncateString(to);
      
      if (isTaxTransfer) {
        enhancedEvent.display_type = 'Self-Transfer';
        enhancedEvent.description = `Token Fee: ${value} ${tokenSymbol} retained as transaction fee`;
        enhancedEvent.transfer_type = 'fee';
      } else {
        enhancedEvent.display_type = 'Transfer';
        enhancedEvent.description = `Transfer ${value} ${tokenSymbol} from ${shortFrom} to ${shortTo}`;
        enhancedEvent.transfer_type = 'transfer';
      }
      
      enhancedEvent.parameters = [
        { name: 'signature', value: signature },
        { name: 'topic1', value: event.topics[1] },
        { name: 'topic2', value: event.topics[2] },
        { name: 'data', value: event.data }
      ];
    } 
    else if (eventType === 'Approval') {
      const owner = event.topics && event.topics.length > 1 ? parseAddressFromTopic(event.topics[1]) : '';
      const spender = event.topics && event.topics.length > 2 ? parseAddressFromTopic(event.topics[2]) : '';
      
      let tokenSymbol = event.token_symbol || 'TOKEN';
      let decimals = event.decimals || 18;
      
      if ((!event.token_symbol || event.token_symbol === 'TOKEN' || event.token_symbol === 'UNKNOWN') && event.address) {
        try {
          const tokenInfo = await getTokenInfo(event.address);
          if (tokenInfo) {
            tokenSymbol = tokenInfo.symbol || 'TOKEN';
            decimals = tokenInfo.decimals || 18;
          }
        } catch (error: any) {
          console.warn(`Failed to get token info for ${event.address}: ${error.message}`);
        }
      }
      
      const value = formatTokenAmount(event.data, decimals);
      
      enhancedEvent.token_approval = {
        owner,
        spender,
        value,
        token_address: event.address,
        token_symbol: tokenSymbol
      };
      
      const shortOwner = truncateString(owner);
      const shortSpender = truncateString(spender);
      enhancedEvent.description = `Approval: ${shortOwner} approved ${shortSpender} to spend ${value} ${tokenSymbol}`;
      
      enhancedEvent.display_type = 'Approval';
      
      enhancedEvent.parameters = [
        { name: 'signature', value: signature },
        { name: 'topic1', value: event.topics[1] },
        { name: 'topic2', value: event.topics[2] },
        { name: 'data', value: event.data }
      ];
    }
    else {
      enhancedEvent.display_type = eventType;
    }
  }
  
  return enhancedEvent;
}

/**
 * 
 * @param events 
 * @returns 
 */
export async function enhanceEvents(events: any[]): Promise<any[]> {
  if (!events || !Array.isArray(events)) {
    return [];
  }
  
  const enhancedEvents = [];
  for (const event of events) {
    const enhanced = await enhanceEvent(event);
    enhancedEvents.push(enhanced);
  }
  
  return enhancedEvents;
}

/**
 * 
 * @param response 
 * @returns 
 */
export async function enhanceEventResponse(response: any): Promise<any> {
  if (!response) return response;
  

  if (response.events) {
    const enhancedEvents = await enhanceEvents(response.events);
    return {
      ...response,
      events: enhancedEvents
    };
  } else if (response.transfers) {
    const enhancedTransfers = await enhanceEvents(response.transfers);
    return {
      ...response,
      transfers: enhancedTransfers
    };
  } else if (response.token_events) {
    const enhancedEvents = await enhanceEvents(response.token_events);
    return {
      ...response,
      token_events: enhancedEvents
    };
  } else if (response.data && Array.isArray(response.data)) {
    const enhancedData = await enhanceEvents(response.data);
    return {
      ...response,
      data: enhancedData
    };
  }
  
  return response;
}

/**

 * @param address 
 * @param params 
 * @returns 
 */
export async function getAddressEvents(address: string, params: { 
  page?: number; 
  limit?: number; 
  eventType?: string;
} = {}): Promise<any> {
  const queryParams: Record<string, any> = {
    page: params.page || 1,
    limit: params.limit || 10
  };
  
  if (params.eventType) {
    queryParams.eventType = params.eventType;
  }
  
  const response = await callExplorerApi(`events/address/${address}`, queryParams);
  return await enhanceEventResponse(response);
}

/**
 
 * @param txHash 
 * @param params 
 * @returns 
 */
export async function getTransactionEvents(txHash: string, params: {
  eventType?: string;
} = {}): Promise<any> {
  const queryParams: Record<string, any> = {};
  
  if (params.eventType) {
    queryParams.eventType = params.eventType;
  }
  
  const response = await callExplorerApi(`events/tx/${txHash}`, queryParams);
  return await enhanceEventResponse(response);
}

/**
 * 
 * @param params 
 * @returns 
 */
export async function getAllEvents(params: { 
  page?: number; 
  limit?: number; 
  eventType?: string;
} = {}): Promise<any> {
  const queryParams: Record<string, any> = {
    page: params.page || 1,
    limit: params.limit || 10
  };
  
  if (params.eventType) {
    queryParams.eventType = params.eventType;
  }
  
  const response = await callExplorerApi('events', queryParams);
  return await enhanceEventResponse(response);
}

/**
 * 
 * @param params 
 * @returns 
 */
export async function getTokenTransfers(params: { 
  page?: number; 
  limit?: number;
} = {}): Promise<any> {
  const queryParams: Record<string, any> = {
    page: params.page || 1,
    limit: params.limit || 10
  };
  
  const response = await callExplorerApi('events/token-transfers', queryParams);
  return await enhanceEventResponse(response);
}

/**
 * 
 * @param tokenAddress 
 * @param params 
 * @returns 
 */
export async function getTokenTransfersByToken(tokenAddress: string, params: { 
  page?: number; 
  limit?: number;
} = {}): Promise<any> {
  const queryParams: Record<string, any> = {
    page: params.page || 1,
    limit: params.limit || 10
  };
  
  const response = await callExplorerApi(`events/token-transfers/token/${tokenAddress}`, queryParams);
  return await enhanceEventResponse(response);
}

/**
 * 
 * @param address 
 * @param params 
 * @returns 
 */
export async function getTokenTransfersByAddress(address: string, params: { 
  page?: number; 
  limit?: number;
} = {}): Promise<any> {
  const queryParams: Record<string, any> = {
    page: params.page || 1,
    limit: params.limit || 10
  };
  
  const response = await callExplorerApi(`events/token-transfers/address/${address}`, queryParams);
  return await enhanceEventResponse(response);
} 