import type { BackupPool } from '../types';

/** One connectable Stratum endpoint (wallet-only Monero pools). */
export interface PoolPreset {
  id: string;
  provider: string;
  host: string;
  port: number;
  tls: boolean;
  hint: string;
}

/** Western-US friendly presets — TLS variant preferred per provider. */
export const XMR_POOL_PRESETS: PoolPreset[] = [
  {
    id: 'moneroocean-tls',
    provider: 'MoneroOcean',
    host: 'gulf.moneroocean.stream',
    port: 20128,
    tls: true,
    hint: 'gulf TLS :20128',
  },
  {
    id: 'moneroocean',
    provider: 'MoneroOcean',
    host: 'gulf.moneroocean.stream',
    port: 10128,
    tls: false,
    hint: 'gulf plain :10128',
  },
  {
    id: 'supportxmr-tls',
    provider: 'SupportXMR',
    host: 'pool.supportxmr.com',
    port: 443,
    tls: true,
    hint: ':443 TLS',
  },
  {
    id: 'supportxmr',
    provider: 'SupportXMR',
    host: 'pool.supportxmr.com',
    port: 3333,
    tls: false,
    hint: ':3333',
  },
  {
    id: 'herominers-tls',
    provider: 'HeroMiners',
    host: 'xmr.herominers.com',
    port: 1120,
    tls: true,
    hint: ':1120 TLS',
  },
  {
    id: 'herominers',
    provider: 'HeroMiners',
    host: 'xmr.herominers.com',
    port: 1111,
    tls: false,
    hint: ':1111',
  },
  {
    id: '2miners',
    provider: '2Miners',
    host: 'xmr.2miners.com',
    port: 2222,
    tls: false,
    hint: ':2222',
  },
  {
    id: 'xmrpool',
    provider: 'XMRPool.eu',
    host: 'pool.xmrpool.eu',
    port: 3333,
    tls: false,
    hint: ':3333',
  },
];

export const DEFAULT_PRESET_IDS = ['supportxmr-tls', 'moneroocean-tls', 'herominers-tls'] as const;

// ─── Ravencoin (RVN / KawPoW) pool presets ───────────────────────────────────

export interface RVNPoolPreset {
  id: string;
  provider: string;
  host: string;
  port: number;
  tls: boolean;
  hint: string;
}

export const RVN_POOL_PRESETS: RVNPoolPreset[] = [
  {
    id: '2miners-rvn',
    provider: '2Miners',
    host: 'rvn.2miners.com',
    port: 6060,
    tls: false,
    hint: ':6060',
  },
  {
    id: 'herominers-rvn',
    provider: 'HeroMiners',
    host: 'rvn.herominers.com',
    port: 1140,
    tls: false,
    hint: ':1140',
  },
  {
    id: 'minerpool-rvn',
    provider: 'MinePool',
    host: 'us.rvn.minepool.io',
    port: 3333,
    tls: false,
    hint: ':3333',
  },
  {
    id: 'woolypooly-rvn',
    provider: 'WoolyPooly',
    host: 'rvn.woolypooly.com',
    port: 55555,
    tls: false,
    hint: ':55555',
  },
  {
    id: 'ravenminer',
    provider: 'RavenMiner',
    host: 'us.ravenminer.com',
    port: 3838,
    tls: false,
    hint: ':3838',
  },
  {
    id: 'nanopool-rvn',
    provider: 'Nanopool',
    host: 'rvn-us-west1.nanopool.org',
    port: 12222,
    tls: false,
    hint: ':12222',
  },
];

export const DEFAULT_RVN_PRESET_IDS = ['2miners-rvn', 'herominers-rvn', 'ravenminer'] as const;

export interface RVNPoolForgeFields {
  rvn_pool_host: string;
  rvn_pool_port: number;
  rvn_pool_tls: boolean;
  rvn_backup_pools: BackupPool[];
}

export function orderedRVNPoolsFromSelection(
  presetIds: string[],
  pass: string,
  custom?: BackupPool | null,
): BackupPool[] {
  const out: BackupPool[] = [];
  const seen = new Set<string>();
  for (const id of presetIds) {
    const preset = RVN_POOL_PRESETS.find((p) => p.id === id);
    if (!preset) continue;
    const key = endpointKey(preset.host, preset.port, preset.tls);
    if (seen.has(key)) continue;
    seen.add(key);
    out.push({ host: preset.host, port: preset.port, tls: preset.tls, pass });
  }
  if (custom?.host?.trim() && custom.port > 0) {
    const key = endpointKey(custom.host, custom.port, !!custom.tls);
    if (!seen.has(key)) out.push({ ...custom, pass: custom.pass || pass || 'x' });
  }
  return out;
}

export function applyRVNPoolsToForgeFields(pools: BackupPool[]): RVNPoolForgeFields {
  const { primary, backups } = splitPrimaryAndBackups(pools);
  if (!primary) return { rvn_pool_host: '', rvn_pool_port: 6060, rvn_pool_tls: false, rvn_backup_pools: [] };
  return { rvn_pool_host: primary.host, rvn_pool_port: primary.port, rvn_pool_tls: primary.tls, rvn_backup_pools: backups };
}

export function detectRVNPresetIds(host: string, port: number, tls: boolean, backups: BackupPool[] = []): string[] {
  const keys = new Set<string>();
  keys.add(endpointKey(host, port, tls));
  for (const b of backups) {
    if (b.host && b.port > 0) keys.add(endpointKey(b.host, b.port, !!b.tls));
  }
  return RVN_POOL_PRESETS.filter((p) => keys.has(endpointKey(p.host, p.port, p.tls))).map((p) => p.id);
}

function endpointKey(host: string, port: number, tls: boolean): string {
  return `${host.trim().toLowerCase()}:${port}:${tls ? '1' : '0'}`;
}

export function presetToBackupPool(p: PoolPreset, pass = 'x'): BackupPool {
  return { host: p.host, port: p.port, tls: p.tls, pass };
}

/** Ordered endpoints: first = primary, rest = failover (round-robin on reconnect). */
export function orderedPoolsFromSelection(
  presetIds: string[],
  pass: string,
  custom?: BackupPool | null
): BackupPool[] {
  const out: BackupPool[] = [];
  const seen = new Set<string>();
  for (const id of presetIds) {
    const preset = XMR_POOL_PRESETS.find((p) => p.id === id);
    if (!preset) continue;
    const key = endpointKey(preset.host, preset.port, preset.tls);
    if (seen.has(key)) continue;
    seen.add(key);
    out.push(presetToBackupPool(preset, pass));
  }
  if (custom?.host?.trim() && custom.port > 0) {
    const key = endpointKey(custom.host, custom.port, !!custom.tls);
    if (!seen.has(key)) {
      out.push({
        host: custom.host.trim(),
        port: custom.port,
        tls: !!custom.tls,
        pass: custom.pass || pass || 'x',
      });
    }
  }
  return out;
}

export function splitPrimaryAndBackups(pools: BackupPool[]): {
  primary: BackupPool | null;
  backups: BackupPool[];
} {
  if (!pools.length) return { primary: null, backups: [] };
  return { primary: pools[0], backups: pools.slice(1) };
}

export interface PoolForgeFields {
  pool_host: string;
  pool_port: number;
  pool_tls: boolean;
  backup_pools: BackupPool[];
}

export function applyPoolsToForgeFields(pools: BackupPool[]): PoolForgeFields {
  const { primary, backups } = splitPrimaryAndBackups(pools);
  if (!primary) {
    return { pool_host: '', pool_port: 3333, pool_tls: false, backup_pools: [] };
  }
  return {
    pool_host: primary.host,
    pool_port: primary.port,
    pool_tls: primary.tls,
    backup_pools: backups ?? [],
  };
}

/** Which preset IDs match the current primary + backup endpoints. */
export function detectPresetIds(
  host: string,
  port: number,
  tls: boolean,
  backups: BackupPool[] = []
): string[] {
  const keys = new Set<string>();
  keys.add(endpointKey(host, port, tls));
  for (const b of backups) {
    if (b.host && b.port > 0) keys.add(endpointKey(b.host, b.port, !!b.tls));
  }
  return XMR_POOL_PRESETS.filter((p) => keys.has(endpointKey(p.host, p.port, p.tls))).map((p) => p.id);
}

/** Custom endpoint if it does not match any preset. */
export function detectCustomEndpoint(
  host: string,
  port: number,
  tls: boolean,
  backups: BackupPool[] = []
): BackupPool | null {
  const all = [{ host, port, tls }, ...backups.map((b) => ({ host: b.host, port: b.port, tls: !!b.tls }))];
  for (const ep of all) {
    if (!ep.host?.trim() || ep.port <= 0) continue;
    const matchesPreset = XMR_POOL_PRESETS.some(
      (p) => endpointKey(p.host, p.port, p.tls) === endpointKey(ep.host, ep.port, ep.tls)
    );
    if (!matchesPreset) {
      return { host: ep.host.trim(), port: ep.port, tls: ep.tls };
    }
  }
  return null;
}
