const fs = require('fs');
const axios = require('axios');
const { promisify } = require('util');
const writeFileAsync = promisify(fs.writeFile);
require('dotenv').config();

// Cloudflare API credentials
// You'll need to replace these with your own
const CF_API_TOKEN = process.env.CF_API_TOKEN;
const CF_EMAIL = process.env.CF_EMAIL; // Only needed if using API key instead of token

// Output file
const OUTPUT_FILE = 'cloudflare-dns-records.txt';

/**
 * Fetch all zones (domains) from Cloudflare
 */
async function getZones() {
  try {
    let zones = [];
    let page = 1;
    let hasMorePages = true;
    
    console.log('Fetching zones from Cloudflare...');
    
    while (hasMorePages) {
      const response = await axios({
        method: 'GET',
        url: 'https://api.cloudflare.com/client/v4/zones',
        headers: {
          'Authorization': `Bearer ${CF_API_TOKEN}`,
          'Content-Type': 'application/json'
        },
        params: {
          page: page,
          per_page: 50
        }
      });
      
      const result = response.data.result;
      zones = zones.concat(result);
      
      // Check if there are more pages
      if (result.length < 50) {
        hasMorePages = false;
      } else {
        page++;
      }
    }
    
    console.log(`Found ${zones.length} zones.`);
    return zones;
  } catch (error) {
    console.error('Error fetching zones:', error.message);
    if (error.response) {
      console.error('API response:', error.response.data);
    }
    throw error;
  }
}

/**
 * Fetch DNS records for a specific zone
 */
async function getDnsRecords(zoneId, zoneName) {
  try {
    let records = [];
    let page = 1;
    let hasMorePages = true;
    
    console.log(`Fetching DNS records for ${zoneName}...`);
    
    while (hasMorePages) {
      const response = await axios({
        method: 'GET',
        url: `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`,
        headers: {
          'Authorization': `Bearer ${CF_API_TOKEN}`,
          'Content-Type': 'application/json'
        },
        params: {
          page: page,
          per_page: 100
        }
      });
      
      const result = response.data.result;
      records = records.concat(result);
      
      // Check if there are more pages
      if (result.length < 100) {
        hasMorePages = false;
      } else {
        page++;
      }
    }
    
    console.log(`Found ${records.length} DNS records for ${zoneName}.`);
    return records;
  } catch (error) {
    console.error(`Error fetching DNS records for ${zoneName}:`, error.message);
    if (error.response) {
      console.error('API response:', error.response.data);
    }
    throw error;
  }
}

/**
 * Format a DNS record to a human-readable string
 */
function formatDnsRecord(record, zoneName) {
  let formattedRecord = `[${zoneName}] ${record.name} ${record.ttl} IN ${record.type} `;
  
  switch (record.type) {
    case 'A':
    case 'AAAA':
      formattedRecord += record.content;
      break;
    case 'CNAME':
    case 'NS':
    case 'PTR':
      formattedRecord += `${record.content}`;
      break;
    case 'MX':
      formattedRecord += `${record.priority} ${record.content}`;
      break;
    case 'TXT':
      formattedRecord += `"${record.content}"`;
      break;
    case 'SRV':
      formattedRecord += `${record.data.priority} ${record.data.weight} ${record.data.port} ${record.data.target}`;
      break;
    default:
      formattedRecord += JSON.stringify(record.content);
  }
  
  if (record.proxied) {
    formattedRecord += ' [Proxied]';
  }
  
  return formattedRecord;
}

/**
 * Main function to get all DNS records and write them to a file
 */
async function exportAllDnsRecords() {
  try {
    // Get all zones
    const zones = await getZones();
    
    let allRecords = [];
    
    // For each zone, get its DNS records
    for (const zone of zones) {
      const records = await getDnsRecords(zone.id, zone.name);
      
      // Add a zone header
      allRecords.push(`\n==== Domain: ${zone.name} ====\n`);
      
      // Format and add each record
      for (const record of records) {
        const formattedRecord = formatDnsRecord(record, zone.name);
        allRecords.push(formattedRecord);
      }
    }
    
    // Join all records with newlines and write to file
    const outputContent = allRecords.join('\n');
    await writeFileAsync(OUTPUT_FILE, outputContent);
    
    console.log(`\nDNS records exported to ${OUTPUT_FILE}`);
  } catch (error) {
    console.error('Export failed:', error);
  }
}

// Run the script
exportAllDnsRecords().catch(err => {
  console.error('Script execution failed:', err);
  process.exit(1);
});