// main_dns.js — Analysis for DNS events
import { backendUrl } from './config.js'
import * as translate from './translate_tls.js'
let lastDnsEvents = [];
let sortFieldDNS = null;
let sortAscDNS = true;
let chartDNS;
let lastSummary = null;
let hasRecentEventsDNS = false;

const byIdDNS = (id) => document.getElementById(id);

const tr = (key) => {
  const lang = localStorage.getItem('lang') || 'ru';
  return translate.translations[lang]?.[key] || key;
};
const applyLanguage = (lang) => {
  const dict = translate.translations[lang] || translate.translations['ru'];
  document.querySelectorAll('[data-i18n]').forEach(el => {
    const key = el.getAttribute('data-i18n');
    if (dict[key]) el.textContent = dict[key];
  });
  localStorage.setItem('lang', lang);
  if (lastSummary) {
    showSummaryDNS(lastSummary.total, lastSummary.anomalies, lastSummary.visible);
  }
};

const initLanguage = () => {
  const lang = localStorage.getItem('lang') || 'ru';
  const select = byIdDNS('langSelectDNS');
  if (select) select.value = lang;
  applyLanguage(lang);
  if (select) {
    select.addEventListener('change', (e) => {
      applyLanguage(e.target.value);
    });
  }
};
const saveDnsState = () => {
  localStorage.setItem('limitDNS', byIdDNS('limitInputDNS').value);
  localStorage.setItem('offsetDNS', byIdDNS('offsetInputDNS').value);
  localStorage.setItem('anomalyOnlyDNS', byIdDNS('anomalyOnlyCheckboxDNS').checked);
  localStorage.setItem('intervalDNS', byIdDNS('intervalSelectDNS').value);
};
const LoadDnsState = () => {
  if (localStorage.getItem('limitDNS')) byIdDNS('limitInputDNS').value = localStorage.getItem('limitDNS');
  if (localStorage.getItem('offsetDNS')) byIdDNS('offsetInputDNS').value = localStorage.getItem('offsetDNS');
  if (localStorage.getItem('anomalyOnlyDNS')) byIdDNS('anomalyOnlyCheckboxDNS').checked = localStorage.getItem('anomalyOnlyDNS') === 'true';
  if (localStorage.getItem('intervalDNS')) byIdDNS('intervalSelectDNS').value = localStorage.getItem('intervalDNS');
};

const analyzeManualDNS = async () => {
  const input = byIdDNS('jsonInputDNS').value;
  const errorBox = byIdDNS('errorDNS');
  const resultBox = byIdDNS('resultDNS');
  errorBox.textContent = '';
  resultBox.innerHTML = '';

  let events;
  try {
    events = JSON.parse(input);
    if (!Array.isArray(events)) throw new Error('Expected array of objects');
  } catch (err) {
    errorBox.textContent = 'Invalid JSON: ' + err.message;
    return;
  }

  try {
    const res = await fetch(`${backendUrl}/ai/analyze/dns`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ events })
    });
    const data = await res.json();

    if (data.error) {
      errorBox.textContent = 'Error: ' + data.error;
    } else {
      resultBox.innerHTML = `
        <p><strong>Total events:</strong> ${data.total}</p>
        <p><strong>Anomalie:</strong> ${data.anomaly_count}</p>
        <pre>${JSON.stringify(data.anomalies, null, 2)}</pre>
      `;
    }
  } catch (err) {
    errorBox.textContent = 'Request error: ' + err.message;
  }
};

const analyzeDnsFromRedis = async () => {
  const limit = parseInt(byIdDNS('limitInputDNS').value) || 100;
  const offset = parseInt(byIdDNS('offsetInputDNS').value) || 0;
  const onlyAnomalies = byIdDNS('anomalyOnlyCheckboxDNS').checked;

  try {
    const res = await fetch(`${backendUrl}/api/analyze/dns?limit=${limit}&offset=${offset}&only_anomalies=${onlyAnomalies}`);
    const data = await res.json();

    if (data.error) throw new Error(data.error);

    lastDnsEvents = data.events;
    hasRecentEventsDNS = data.events.length > 0;
    sortFieldDNS = null;
    sortAscDNS = true;

    byIdDNS('dns-results').innerHTML = '';
    byIdDNS('detailsBoxDNS').innerHTML = '';

    const visibleCount = onlyAnomalies ? limit : data.events.length;
    showSummaryDNS(data.total, data.anomaly_count, visibleCount);
    renderDnsEvents(data.events);
  } catch (err) {
    byIdDNS('dns-results').innerHTML = `<tr><td colspan="8" class="error">Error: ${err.message}</td></tr>`;
  }
};

const showSummaryDNS = (total, anomalies, visible) => {
  const percent = ((anomalies / (visible || 1)) * 100).toFixed(2);
  byIdDNS('summaryBoxDNS').innerHTML = `
    <p><strong>Total in Redis:</strong> ${total} events</p>
    <p><strong>In sample:</strong> ${visible}, found anomalies: ${anomalies} (${percent}%)</p>
  `;
};

const renderDnsEvents = (events) => {
  const tbody = byIdDNS('dns-results');
  tbody.innerHTML = '';
  events.forEach(({ index, src_ip, dst_ip, anomaly, full }) => {
    const {
      src_port,
      dest_port,
      proto,
      dns = {}
    } = full;
  
    const type = dns.type || '';
  
    const row = document.createElement('tr');
    row.className = anomaly ? 'anomaly' : 'normal';
    row.innerHTML = `
      <td>${index + 1}</td>
      <td>${src_ip}:${src_port || ''}</td>
      <td>${dst_ip}:${dest_port || ''}</td>
      <td>${proto || ''}</td>
      <td>${type}</td>
      <td>${anomaly ? 'Yes 🚨' : 'No ✅'}</td>
      <td><button style="font-size: 12px; padding: 2px 6px;" onclick='showDetailsDNS(${JSON.stringify(full)})'>🔍</button></td>
      <td><button style="font-size: 12px; padding: 2px 6px;" onclick='copySuricataRuleDNS("${src_ip}")'>⚡</button></td>
    `;
    tbody.appendChild(row);
  });
};

window.showDetailsDNS = (event) => {
  byIdDNS('detailsBoxDNS').innerHTML = `<h3>Event details:</h3><pre>${JSON.stringify(event, null, 2)}</pre>`;
  byIdDNS('detailsBoxDNS').scrollIntoView({ behavior: 'smooth' });
};

const exportAnomaliesDNS = (format) => {
  const anomalies = lastDnsEvents.filter(e => e.anomaly);
  if (anomalies.length === 0) return alert('No anomalies for export');

  if (format === 'csv') {
    const headers = Object.keys(anomalies[0]);
    const rows = anomalies.map(e => headers.map(h => JSON.stringify(e[h] ?? '')).join(','));
    const csv = [headers.join(','), ...rows].join('\n');
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = 'dns_anomalies.csv';
    link.click();
  } else {
    const blob = new Blob([JSON.stringify(anomalies, null, 2)], { type: 'application/json' });
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = 'dns_anomalies.json';
    link.click();
  }
};

// JS function for generating a rule and showing a modal window
window.copySuricataRuleDNS = (ip) => {
  const rule = `drop ip [${ip}] any -> any any (msg:"Blocked malicious IP ${ip}"; sid:999001; rev:1;)`;
  
  // Insert a rule into a modal window
  const modal = document.getElementById('suricataModal');
  const ruleBox = document.getElementById('suricataRule');
  
  if (modal && ruleBox) {
    ruleBox.textContent = rule;
    modal.style.display = 'block';
  } else {
    alert('Error: Failed to display rule.');
  }
};


byIdDNS('analyzeManualDNS').addEventListener('click', analyzeManualDNS);
byIdDNS('analyzeRedisDNS').addEventListener('click', analyzeDnsFromRedis);
byIdDNS('exportCSVDNS').addEventListener('click', () => exportAnomaliesDNS('csv'));
byIdDNS('exportJSONDNS').addEventListener('click', () => exportAnomaliesDNS('json'));

// Graphs
const loadTimelineChartDNS = async () => {
  console.log("start");
  const interval = byIdDNS('intervalSelectDNS').value;
  const limit = parseInt(byIdDNS('limitInputDNS').value) || 100;
  const offset = parseInt(byIdDNS('offsetInputDNS').value) || 0;
  const url = `${backendUrl}/api/analyze_dns_timeline?interval=${interval}&limit=${limit}&offset=${offset}`;

  try {
    const res = await fetch(url);
    const data = await res.json();
    console.log("start mapping");
    const labels = data.timeline.map(t => t.time);
    const values = data.timeline.map(t => t.anomalies);
    console.log("end mapping");
    if (chartDNS) chartDNS.destroy();
    const ctx = byIdDNS('timelineChartDNS').getContext('2d');
    console.log("start charting");
    chartDNS = new Chart(ctx, {
      type: 'line',
      data: {
        labels,
        datasets: [{
          label: `Anomalies (${interval})`,
          data: values,
          fill: false,
          tension: 0.2
        }]
      },
      options: {
        responsive: true,
        scales: { y: { beginAtZero: true } }
      }
    });
  } catch (err) {
    alert('Error loading chart: ' + err.message);
  }
};

const loadCompareChartDNS = async () => {
  const from = parseInt(byIdDNS('fromHourDNS').value);
  const to = parseInt(byIdDNS('toHourDNS').value);
  const url = `${backendUrl}/api/anomaly_dns_compare?from_hour=${from}&to_hour=${to}`;

  try {
    const res = await fetch(url);
    const data = await res.json();
    if (data.error) throw new Error(data.error);

    const ctx = byIdDNS('dnsCompareChart').getContext('2d');
    if (window.compareChartObj) window.compareChartObj.destroy();

    window.compareChartObj = new Chart(ctx, {
      type: 'bar',
      data: {
        labels: ['Today', 'Yesterday'],
        datasets: [{
          label: `Anomalies (${data.interval})`,
          data: [data.today.anomalies, data.yesterday.anomalies],
          backgroundColor: ['#e19435', '#0e56ff']
        }]
      },
      options: {
        scales: { y: { beginAtZero: true } }
      }
    });
  } catch (err) {
    alert('Comparison error: ' + err.message);
  }
};

const loadHourlyCompareChartDNS = async () => {
  const from = parseInt(byIdDNS('fromHourChartDNS').value);
  const to = parseInt(byIdDNS('toHourChartDNS').value);
  const url = `${backendUrl}/api/anomaly_dns_compare_timeline?from_hour=${from}&to_hour=${to}`;

  try {
    const res = await fetch(url);
    const data = await res.json();
    if (data.error) throw new Error(data.error);

    const labels = data.timeline.map(t => t.hour);
    const todayData = data.timeline.map(t => t.today);
    const yesterdayData = data.timeline.map(t => t.yesterday);

    const ctx = byIdDNS('dnsHourlyCompareChart').getContext('2d');
    if (window.hourlyCompareChartObj) window.hourlyCompareChartObj.destroy();

    window.hourlyCompareChartObj = new Chart(ctx, {
      type: 'bar',
      data: {
        labels,
        datasets: [
          {
            label: 'Today',
            data: todayData,
            backgroundColor: '#e19435'
          },
          {
            label: 'Yesterday',
            data: yesterdayData,
            backgroundColor: '#0e56ff'
          }
        ]
      },
      options: {
        responsive: true,
        scales: { y: { beginAtZero: true } }
      }
    });
  } catch (err) {
    alert('Error building chart: ' + err.message);
  }
};

byIdDNS('timelineBtnDNS').addEventListener('click', loadTimelineChartDNS);
byIdDNS('compareBtnDNS').addEventListener('click', loadCompareChartDNS);
byIdDNS('hourlyCompareBtnDNS').addEventListener('click', loadHourlyCompareChartDNS);

let autoRefreshIntervalDNS = null;

const setupAutoRefreshDNS = () => {
  const checkbox = byIdDNS('autoRefreshDNS');
  if (!checkbox) return;

  if (autoRefreshIntervalDNS) clearInterval(autoRefreshIntervalDNS);

  if (checkbox.checked) {
    autoRefreshIntervalDNS = setInterval(() => {
      if (checkbox.checked && hasRecentEventsDNS) {
        analyzeDnsFromRedis();
      }
    }, 120000); // 120 sec
  }
};

const autoCheckbox = byIdDNS('autoRefresh');
if (autoCheckbox) {
  autoCheckbox.addEventListener('change', setupAutoRefreshDNS);
}

const sortDNSTableBy = (field) => {
  if (sortFieldDNS === field) {
    sortAscDNS = !sortAscDNS;
  } else {
    sortFieldDNS = field;
    sortAscDNS = true;
  }

  lastDnsEvents.sort((a, b) => {
    const getValue = (obj) => {
      if (field in obj) return obj[field];
      if (obj.full && field in obj.full) return obj.full[field];
      if (obj.full?.dns && field in obj.full.dns) return obj.full.dns[field];
      return null;
    };

    const valA = getValue(a);
    const valB = getValue(b);

    if (valA < valB) return sortAscDNS ? -1 : 1;
    if (valA > valB) return sortAscDNS ? 1 : -1;
    return 0;
  });

  renderDnsEvents(lastDnsEvents);
};

document.querySelectorAll('th[data-sort]').forEach(th => {
  th.addEventListener('click', () => sortDNSTableBy(th.dataset.sort));
});
LoadDnsState();
setupAutoRefreshDNS();
//initLanguageDNS();
