// wci26/live-config.jsx - address slots and validation for live WCI26 Ethereum mainnet data.
// Keep this file address-only; RPC reads live state in live-adapter.jsx.

const WCI_LIVE_CONFIG_VERSION = 'wci26-mainnet-live-v1';
const WCI_LIVE_CONFIG_STORAGE_KEY = 'wci26-live-config-v2';

const WCI_LIVE_REQUIRED_GLOBAL_FIELDS = [
  'factoryAddress',
  'buybackExecutorAddress',
  'wci26Address',
  'wethAddress',
];

const WCI_LIVE_COUNTRY_FIELDS = [
  'onchainIsoCode',
  'tokenAddress',
  'v3PoolAddress',
  'lpTokenId',
];

const wciLiveCountryCodes = () => {
  if (typeof buildCountryTokens === 'function') {
    return buildCountryTokens('live').map((country) => country.code);
  }
  if (typeof COUNTRY_GEO !== 'undefined') return Object.keys(COUNTRY_GEO);
  return [];
};

const isLiveAddress = (value) => /^0x[a-fA-F0-9]{40}$/.test(String(value || '').trim());
const normaliseLiveAddress = (value) => (isLiveAddress(value) ? String(value).trim() : '');
const normaliseLiveIso = (value) => String(value || '').trim().toUpperCase();
const normaliseLiveRpcUrls = (urls = []) => [...new Set(urls
  .map((url) => String(url || '').trim())
  .filter((url) => /^https?:\/\//i.test(url)))];
const normaliseLiveHttpUrl = (url = '') => (/^https?:\/\//i.test(String(url || '').trim()) ? String(url).trim() : '');
const normaliseLiveBytes2 = (value, fallbackIso = '') => {
  const normalized = normaliseLiveIso(value || fallbackIso);
  return /^[A-Z0-9]{2}$/.test(normalized) ? normalized : '';
};

const buildCountryAddressSlots = () => wciLiveCountryCodes().reduce((slots, isoCode) => {
  slots[isoCode] = {
    isoCode,
    onchainIsoCode: '',
    tokenAddress: '',
    v3PoolAddress: '',
    lpTokenId: '',
    deploymentBlock: null,
    poolFeeTier: 10000,
  };
  return slots;
}, {});

const getLiveSourceOverrides = () => (
  typeof WCI_LIVE_ADDRESS_OVERRIDES !== 'undefined' ? WCI_LIVE_ADDRESS_OVERRIDES : {}
);

const WCI_LIVE_DEFAULT_CONFIG = {
  version: WCI_LIVE_CONFIG_VERSION,
  chainId: null,
  chainName: '',
  chainKey: '',
  rpcHttpUrl: '',
  rpcHttpUrls: [],
  logRpcHttpUrls: [],
  rpcWebSocketUrl: '',
  indexerGraphqlUrl: '',
  realtimeUrl: '',
  uniswapV3SubgraphUrl: '',
  ponderGraphqlUrl: '',
  ponderApiBaseUrl: '',
  ponderSnapshotUrl: '',
  ponderEventsUrl: '',
  ponderTimeoutMs: 1200,
  logAddressChunkSize: 12,
  factoryAddress: '',
  buybackExecutorAddress: '',
  countryTokenImplementationAddress: '',
  wci26Address: '',
  wethAddress: '',
  buybackWethAddress: '',
  uniswapV3FactoryAddress: '',
  uniswapV3PositionManagerAddress: '',
  uniswapV2RouterAddress: '',
  uniswapV2WethPairAddress: '',
  swapRouterAddress: '',
  startBlock: null,
  poolStartBlock: null,
  countries: buildCountryAddressSlots(),
};

const normaliseCountryConfig = (country, fallbackIso) => {
  const isoCode = normaliseLiveIso(country?.isoCode || fallbackIso);
  return {
    isoCode,
    onchainIsoCode: normaliseLiveBytes2(country?.onchainIsoCode || country?.contractIsoCode, isoCode.slice(0, 2)),
    name: country?.name || '',
    ticker: country?.ticker || '',
    tokenAddress: normaliseLiveAddress(country?.tokenAddress),
    v3PoolAddress: normaliseLiveAddress(country?.v3PoolAddress || country?.poolAddress),
    lpTokenId: country?.lpTokenId ? String(country.lpTokenId) : '',
    deploymentBlock: Number.isFinite(Number(country?.deploymentBlock)) ? Number(country.deploymentBlock) : null,
    poolFeeTier: Number(country?.poolFeeTier || 10000),
  };
};

const mergeLiveConfig = (overrides = {}) => {
  const sourceOverrides = getLiveSourceOverrides();
  const combinedOverrides = {
    ...sourceOverrides,
    ...overrides,
    countries: {
      ...(sourceOverrides.countries || {}),
      ...(overrides.countries || {}),
    },
  };
  const countrySlots = buildCountryAddressSlots();
  const overrideCountries = combinedOverrides.countries || {};
  Object.keys(overrideCountries).forEach((rawIso) => {
    const isoCode = normaliseLiveIso(rawIso);
    countrySlots[isoCode] = {
      ...(countrySlots[isoCode] || { isoCode }),
      ...normaliseCountryConfig(overrideCountries[rawIso], isoCode),
    };
  });

  const merged = {
    ...WCI_LIVE_DEFAULT_CONFIG,
    ...combinedOverrides,
    countries: countrySlots,
  };
  merged.rpcHttpUrls = normaliseLiveRpcUrls([
    ...(Array.isArray(merged.rpcHttpUrls) ? merged.rpcHttpUrls : []),
    merged.rpcHttpUrl,
  ]);
  merged.logRpcHttpUrls = normaliseLiveRpcUrls([
    ...(Array.isArray(merged.logRpcHttpUrls) ? merged.logRpcHttpUrls : []),
  ]);
  merged.rpcHttpUrl = merged.rpcHttpUrls[0] || '';
  merged.ponderApiBaseUrl = normaliseLiveHttpUrl(merged.ponderApiBaseUrl);
  merged.ponderSnapshotUrl = normaliseLiveHttpUrl(merged.ponderSnapshotUrl);
  merged.ponderEventsUrl = normaliseLiveHttpUrl(merged.ponderEventsUrl);
  merged.ponderTimeoutMs = Math.max(250, Math.floor(Number(merged.ponderTimeoutMs || 1200)));
  merged.logAddressChunkSize = Math.max(1, Math.floor(Number(merged.logAddressChunkSize || 12)));

  WCI_LIVE_REQUIRED_GLOBAL_FIELDS.forEach((field) => {
    merged[field] = normaliseLiveAddress(merged[field]);
  });
  [
    'countryTokenImplementationAddress',
    'buybackWethAddress',
    'uniswapV3FactoryAddress',
    'uniswapV3PositionManagerAddress',
    'uniswapV2RouterAddress',
    'uniswapV2WethPairAddress',
    'swapRouterAddress',
  ].forEach((field) => {
    merged[field] = normaliseLiveAddress(merged[field]);
  });

  return merged;
};

const validateLiveConfig = (configInput = {}) => {
  const config = mergeLiveConfig(configInput);
  const missingGlobal = [];
  if (!config.chainId) missingGlobal.push('chainId');
  WCI_LIVE_REQUIRED_GLOBAL_FIELDS.forEach((field) => {
    if (!isLiveAddress(config[field])) missingGlobal.push(field);
  });

  const countryStatus = {};
  let readyCountryCount = 0;
  Object.keys(config.countries).forEach((isoCode) => {
    const country = config.countries[isoCode];
    const missing = WCI_LIVE_COUNTRY_FIELDS.filter((field) => !country[field]);
    const ready = missing.length === 0
      && isLiveAddress(country.tokenAddress)
      && isLiveAddress(country.v3PoolAddress);
    if (ready) readyCountryCount += 1;
    countryStatus[isoCode] = {
      isoCode,
      ready,
      missing,
      tokenAddress: country.tokenAddress,
      v3PoolAddress: country.v3PoolAddress,
      lpTokenId: country.lpTokenId,
      deploymentBlock: country.deploymentBlock,
      onchainIsoCode: country.onchainIsoCode,
    };
  });

  const countryCount = Object.keys(countryStatus).length;
  const globalReady = missingGlobal.length === 0;
  const mode = !globalReady
    ? 'missing-global-addresses'
    : readyCountryCount === countryCount
      ? 'live-ready'
      : readyCountryCount > 0
        ? 'partial-live-ready'
        : 'missing-country-addresses';

  return {
    mode,
    globalReady,
    missingGlobal,
    readyCountryCount,
    missingCountryCount: countryCount - readyCountryCount,
    countryCount,
    countryStatus,
  };
};

const loadLiveConfig = () => {
  try {
    const raw = localStorage.getItem(WCI_LIVE_CONFIG_STORAGE_KEY);
    return raw ? mergeLiveConfig(JSON.parse(raw)) : mergeLiveConfig();
  } catch {
    return mergeLiveConfig();
  }
};

const saveLiveConfig = (config) => {
  const merged = mergeLiveConfig(config);
  localStorage.setItem(WCI_LIVE_CONFIG_STORAGE_KEY, JSON.stringify(merged));
  return merged;
};

const clearLiveConfig = () => {
  localStorage.removeItem(WCI_LIVE_CONFIG_STORAGE_KEY);
  return mergeLiveConfig();
};

const WCI_LIVE_CONFIG = {
  version: WCI_LIVE_CONFIG_VERSION,
  storageKey: WCI_LIVE_CONFIG_STORAGE_KEY,
  defaultConfig: WCI_LIVE_DEFAULT_CONFIG,
  requiredGlobalFields: WCI_LIVE_REQUIRED_GLOBAL_FIELDS,
  countryFields: WCI_LIVE_COUNTRY_FIELDS,
  isAddress: isLiveAddress,
  mergeConfig: mergeLiveConfig,
  validateConfig: validateLiveConfig,
  loadConfig: loadLiveConfig,
  saveConfig: saveLiveConfig,
  clearConfig: clearLiveConfig,
};

Object.assign(window, {
  WCI_LIVE_CONFIG,
});
