const { execFile } = require('child_process');
const fs = require('fs');

const CSV_FILE = './casino_affiliate_sites.csv';
const CP_FILE  = './.dns.json';

function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }

function generateCandidates() {
  const PFX = ['best','top','trusted','verified','rated','legal','licensed','pro',
    'ultimate','exclusive','premium','mega','super','ultra','fast','safe'];
  const KW  = ['casinoreviews','casino-reviews','online-casinos','best-casinos','top-casinos',
    'casino-guide','casino-ratings','casino-ranking','casino-directory','casino-list',
    'casino-hub','safe-casino','new-casinos'];
  const TLD = ['.com','.net','.org','.info','.site','.xyz'];

  const candidates = [];
  for (const p of PFX) {
    for (const k of KW) {
      for (const t of TLD) {
        candidates.push(`${p}-${k}${t}`);
      }
    }
    for (const t of TLD) {
      candidates.push(`${p}-casino${t}`);
      candidates.push(`${p}-casinos${t}`);
    }
  }

  for (let n = 1; n <= 20; n++) {
    for (const t of ['.com','.net','.org']) {
      candidates.push(`${n}-best-casinoreviews${t}`);
      candidates.push(`top-${n}-casinos${t}`);
      candidates.push(`best-${n}-online-casinos${t}`);
    }
  }

  for (const t of ['.com','.net','.org']) {
    candidates.push(`casinoreviews${t}`);
    candidates.push(`bestcasinoreviews${t}`);
    candidates.push(`topcasinoreviews${t}`);
    candidates.push(`trustedcasinos${t}`);
    candidates.push(`safecasinos${t}`);
    candidates.push(`legalonlinecasinos${t}`);
    candidates.push(`casino-directory${t}`);
  }

  return [...new Set(candidates)].filter(d => d.length > 0 && !d.endsWith('.'));
}

async function checkDNS(domain) {
  try {
    const s = await new Promise((resolve) => {
      execFile('dig', ['+short','+time=1','+tries=1', domain, 'A'],
        { timeout: 3000 }, (_, o) => resolve(o || ''));
    });
    return !!(s && s.trim().length > 0);
  } catch { return false; }
}

function getDomain(url) {
  try { const u = new URL(url); let h = u.hostname; if (h.startsWith('www.')) h = h.slice(4); return h.toLowerCase(); }
  catch { return url.toLowerCase(); }
}

(async () => {
  console.log('═══ DNS Domain Enumerator ═══\n');

  let cp;
  try {
    if (fs.existsSync(CP_FILE)) cp = JSON.parse(fs.readFileSync(CP_FILE, 'utf8'));
    else cp = { checked: {}, found: [] };
  } catch { cp = { checked: {}, found: [] }; }

  const candidates = generateCandidates();
  console.log(`Generated ${candidates.length} candidate domains\n`);

  const CONC = 8;
  let checkedCount = Object.keys(cp.checked).length || 0;

  for (let i = 0; i < candidates.length; ) {
    if (cp.checked[candidates[i]]) { i++; continue; }

    const end = Math.min(i + CONC, candidates.length);
    const batch = candidates.slice(i, end);
    i += CONC;

    const promises = batch.map(async d => {
      cp.checked[d] = true;
      const exists = await checkDNS(d);
      return { domain: d, exists };
    });

    const results = await Promise.all(promises);

    for (const r of results) {
      if (r.exists && !cp.found.some(f => f.domain === r.domain)) {
        cp.found.push({ url: `https://${r.domain}`, title: '', domain: r.domain });
      }
    }

    checkedCount += batch.length;
    if (checkedCount % 100 === 0) {
      fs.writeFileSync(CP_FILE, JSON.stringify(cp));
      console.log(`Checked: ${checkedCount}/${candidates.length} → Found: ${cp.found.length}`);
    }
    await sleep(50);
  }

  // Merge all collected data
  const allSites = new Map();

  // DNS found domains
  for (const f of cp.found) {
    if (!allSites.has(f.domain)) allSites.set(f.domain, f);
  }

  // Load from mega crawler checkpoint
  try {
    const mcData = JSON.parse(fs.readFileSync('.mega_crawl.json', 'utf8'));
    if (mcData && mcData.results) {
      for (const r of mcData.results) {
        if (!r.url) continue;
        const d = getDomain(r.url);
        if (!allSites.has(d)) {
          allSites.set(d, { url: r.url, title: (r.title||'').substring(0,200), domain: d });
        }
      }
    }
  } catch {}

  const finalData = [...allSites.values()].sort((a,b) => a.domain.localeCompare(b.domain));

  const header = 'url,title,domain';
  const rows = finalData.map(v => {
    const t = (v.title || '').replace(/"/g, "'");
    return `"${v.url}","${t}","${v.domain}"`;
  });

  fs.writeFileSync(CSV_FILE, [header, ...rows].join('\n'), 'utf8');

  console.log(`\n══ Final: ${finalData.length} sites → ${CSV_FILE} ════`);
})();
