import { existsSync, readFileSync } from 'fs';
import path from 'path';
import { loadDeploymentStatusFile } from '../config/deployment-status';
import { getGruV2DeploymentPoolRows } from '../config/gru-v2-deployment-pools';
import { logger } from '../utils/logger';

export type CuratedPoolVenue = 'dodo_pmm' | 'uniswap_v2';

export interface CuratedPoolRegistryEntry {
  chainId: number;
  chainName: string;
  poolAddress: string;
  lpTokenAddress: string;
  lpTokenType: 'dodo_dvm' | 'univ2_pair';
  venue: CuratedPoolVenue;
  baseSymbol: string;
  quoteSymbol: string;
  baseAddress: string;
  quoteAddress: string;
  status?: string;
  role?: string;
  publicRoutingEnabled?: boolean;
  feeBps?: number;
  totalLiquidityUsd?: number;
  reserve0?: string;
  reserve1?: string;
  reserve0Usd?: number;
  reserve1Usd?: number;
  liquiditySource?: string;
  liquidityAsOf?: string;
  section?: string;
  integrationStack?: string;
}

export interface CuratedPoolRegistryReport {
  generatedAt: string;
  source: string;
  complete: boolean;
  version?: string;
  updated?: string;
  lastModified?: string;
  homeChainId?: number;
  chain138StackAIntegration?: string;
  count: number;
  pools: CuratedPoolRegistryEntry[];
}

interface LiveUniswapV2PoolRow {
  chainId: number;
  chainName?: string;
  poolAddress: string;
  baseSymbol?: string;
  quoteSymbol?: string;
  baseAddress?: string;
  quoteAddress?: string;
  totalLiquidityUsd?: number;
}

const LIVE_UNISWAP_CATALOG = 'config/live-uniswap-v2-pool-catalog.json';
const CHAIN138_STACK_A = '0x86ADA6Ef91A3B450F89f2b751e93B1b7A3218895';

function resolveCatalogRoots(): string[] {
  const cwd = process.cwd();
  const nested = path.join(cwd, 'smom-dbis-138', 'services', 'token-aggregation');
  return [
    ...new Set(
      [
        cwd,
        nested,
        process.env.PROXMOX_REPO_ROOT,
        process.env.PROJECT_ROOT,
        path.resolve(cwd, '..', '..', '..'),
      ].filter(Boolean) as string[],
    ),
  ];
}

function loadLiveUniswapPools(): LiveUniswapV2PoolRow[] {
  const configured = process.env.TOKEN_AGGREGATION_LIVE_UNISWAP_V2_POOL_CATALOG_JSON?.trim();
  const candidates = [
    configured,
    ...resolveCatalogRoots().map((root) => path.join(root, LIVE_UNISWAP_CATALOG)),
  ].filter(Boolean) as string[];

  for (const candidate of candidates) {
    if (!existsSync(candidate)) continue;
    try {
      const parsed = JSON.parse(readFileSync(candidate, 'utf8')) as { pools?: LiveUniswapV2PoolRow[] };
      return (parsed.pools ?? []).filter(
        (pool) =>
          Number.isFinite(pool.chainId) &&
          typeof pool.poolAddress === 'string' &&
          pool.poolAddress.startsWith('0x'),
      );
    } catch (error) {
      logger.warn('pool-registry: failed to parse live Uniswap catalog', { candidate, error });
    }
  }
  return [];
}

export function buildCuratedPoolRegistry(chainIdFilter?: number | null): CuratedPoolRegistryReport {
  const fileBacked = loadDeploymentStatusFile();
  const dodoRows = getGruV2DeploymentPoolRows();
  const univ2Rows = loadLiveUniswapPools();

  const pools: CuratedPoolRegistryEntry[] = [];

  for (const row of dodoRows) {
    if (chainIdFilter && row.chainId !== chainIdFilter) continue;
    pools.push({
      chainId: row.chainId,
      chainName: row.chainName,
      poolAddress: row.poolAddress,
      lpTokenAddress: row.poolAddress,
      lpTokenType: 'dodo_dvm',
      venue: 'dodo_pmm',
      baseSymbol: row.baseSymbol,
      quoteSymbol: row.quoteSymbol,
      baseAddress: row.baseAddress,
      quoteAddress: row.quoteAddress,
      status: row.status,
      role: row.role,
      publicRoutingEnabled: row.publicRoutingEnabled,
      feeBps: row.feeBps,
      section: row.section,
      integrationStack: row.chainId === 138 ? CHAIN138_STACK_A : undefined,
    });
  }

  for (const row of univ2Rows) {
    if (chainIdFilter && row.chainId !== chainIdFilter) continue;
    if (!row.baseAddress?.startsWith('0x') || !row.quoteAddress?.startsWith('0x')) continue;
    pools.push({
      chainId: row.chainId,
      chainName: row.chainName || `Chain ${row.chainId}`,
      poolAddress: row.poolAddress.toLowerCase(),
      lpTokenAddress: row.poolAddress.toLowerCase(),
      lpTokenType: 'univ2_pair',
      venue: 'uniswap_v2',
      baseSymbol: row.baseSymbol || 'BASE',
      quoteSymbol: row.quoteSymbol || 'QUOTE',
      baseAddress: row.baseAddress.toLowerCase(),
      quoteAddress: row.quoteAddress.toLowerCase(),
      totalLiquidityUsd: row.totalLiquidityUsd,
    });
  }

  pools.sort((a, b) => {
    const chainCmp = a.chainId - b.chainId;
    if (chainCmp !== 0) return chainCmp;
    return a.poolAddress.localeCompare(b.poolAddress);
  });

  return {
    generatedAt: new Date().toISOString(),
    source: fileBacked ? 'deployment-status-file+live-uniswap-catalog' : 'partial-fallback',
    complete: !!fileBacked,
    version: fileBacked?.data.version,
    updated: fileBacked?.data.updated,
    lastModified: fileBacked?.lastModified,
    homeChainId:
      typeof fileBacked?.data.homeChainId === 'number' ? fileBacked.data.homeChainId : undefined,
    chain138StackAIntegration: CHAIN138_STACK_A,
    count: pools.length,
    pools,
  };
}
