import { Pool } from 'pg';
import { getDatabasePool } from '../client';

export interface SwapEventRecord {
  chainId: number;
  poolAddress: string;
  transactionHash: string;
  blockNumber: number;
  logIndex: number;
  token0Address: string;
  token1Address: string;
  amount0In: string;
  amount1In: string;
  amount0Out: string;
  amount1Out: string;
  amountUsd?: number;
  priceUsd?: number;
  token0PriceUsd?: number;
  token1PriceUsd?: number;
  sender?: string;
  toAddress?: string;
  timestamp: Date;
}

export class SwapEventRepository {
  private pool: Pool;

  constructor() {
    this.pool = getDatabasePool();
  }

  private isMissingRelationError(error: unknown): boolean {
    if (!error || typeof error !== 'object') {
      return false;
    }

    const code = (error as { code?: string }).code;
    const message = (error as { message?: string }).message || '';
    return code === '42P01' || (message.includes('relation "') && message.includes('" does not exist'));
  }

  async upsertSwapEvent(event: SwapEventRecord): Promise<void> {
    try {
      await this.pool.query(
        `INSERT INTO swap_events (
           chain_id, pool_address, transaction_hash, block_number, log_index,
           token0_address, token1_address, amount0_in, amount1_in, amount0_out, amount1_out,
           amount_usd, price_usd, token0_price_usd, token1_price_usd, sender, to_address, timestamp
         )
         VALUES (
           $1, $2, $3, $4, $5,
           $6, $7, $8, $9, $10, $11,
           $12, $13, $14, $15, $16, $17, $18
         )
         ON CONFLICT (chain_id, transaction_hash, log_index) DO UPDATE SET
           pool_address = EXCLUDED.pool_address,
           block_number = EXCLUDED.block_number,
           token0_address = EXCLUDED.token0_address,
           token1_address = EXCLUDED.token1_address,
           amount0_in = EXCLUDED.amount0_in,
           amount1_in = EXCLUDED.amount1_in,
           amount0_out = EXCLUDED.amount0_out,
           amount1_out = EXCLUDED.amount1_out,
           amount_usd = EXCLUDED.amount_usd,
           price_usd = EXCLUDED.price_usd,
           token0_price_usd = EXCLUDED.token0_price_usd,
           token1_price_usd = EXCLUDED.token1_price_usd,
           sender = EXCLUDED.sender,
           to_address = EXCLUDED.to_address,
           timestamp = EXCLUDED.timestamp`,
        [
          event.chainId,
          event.poolAddress.toLowerCase(),
          event.transactionHash.toLowerCase(),
          event.blockNumber,
          event.logIndex,
          event.token0Address.toLowerCase(),
          event.token1Address.toLowerCase(),
          event.amount0In,
          event.amount1In,
          event.amount0Out,
          event.amount1Out,
          event.amountUsd,
          event.priceUsd,
          event.token0PriceUsd,
          event.token1PriceUsd,
          event.sender?.toLowerCase(),
          event.toAddress?.toLowerCase(),
          event.timestamp,
        ]
      );
    } catch (error) {
      if (this.isMissingRelationError(error)) {
        return;
      }
      throw error;
    }
  }
}
