/**
 * MAGATAMA S2 TEN BGP Enrichment Task
 *
 * Enriches MAGATAMA S2 TEN (Cloud) findings with:
 * 1. BGP status (is the IP/prefix announced?)
 * 2. RPKI validity (is the announcing ASN authorized?)
 * 3. Threat intelligence (known malicious IP or ASN?)
 *
 * This bridges PeerCortex local intelligence to MAGATAMA security findings.
 * Called when S2 TEN detects anomalous external traffic.
 */

const pg = require('pg');

// Initialize PostgreSQL connection pool
const pool = new pg.Pool({
  host: process.env.DB_HOST || '192.168.178.82',
  port: parseInt(process.env.DB_PORT || '5432'),
  database: process.env.DB_NAME || 'llm_gateway',
  user: process.env.DB_USER || 'llm',
  password: process.env.DB_PASSWORD || 'llm_secure_2026',
  max: 10,
  idleTimeoutMillis: 10000,
  connectionTimeoutMillis: 5000,
});

/**
 * Get BGP status for an IP address
 */
async function getBgpStatus(ipAddress) {
  const client = await pool.connect();
  try {
    const query = `
      SELECT
        prefix,
        origin_asn,
        ARRAY_AGG(DISTINCT origin_asn) as origin_asns,
        visibility_percent,
        last_seen
      FROM bgp_routes
      WHERE prefix >> $1::inet
      ORDER BY prefix DESC
      LIMIT 1
    `;
    const result = await client.query(query, [ipAddress]);
    return result.rows.length > 0 ? result.rows[0] : null;
  } finally {
    client.release();
  }
}

/**
 * Validate RPKI for a prefix + origin ASN pair
 */
async function validateRpki(prefix, originAsn) {
  const client = await pool.connect();
  try {
    const query = `
      SELECT
        status,
        details
      FROM rpki_roas
      WHERE prefix >> $1::inet
        AND origin_asn = $2
      LIMIT 1
    `;
    const result = await client.query(query, [prefix, originAsn]);
    if (result.rows.length > 0) {
      return {
        status: result.rows[0].status || 'valid',
        details: result.rows[0].details,
      };
    }
    // No ROA found = not-found
    return { status: 'not-found' };
  } finally {
    client.release();
  }
}

/**
 * Get threat intelligence for an IP address
 */
async function getThreatIntel(ipAddress) {
  const client = await pool.connect();
  try {
    const query = `
      SELECT
        ip_address,
        threat_level,
        confidence_score,
        source,
        cached_at
      FROM threat_intel
      WHERE ip_address = $1::inet
      LIMIT 1
    `;
    const result = await client.query(query, [ipAddress]);
    return result.rows.length > 0 ? result.rows[0] : null;
  } finally {
    client.release();
  }
}

/**
 * Determine kill-chain phase based on BGP + RPKI + Threat signals
 */
function determineKillChainPhase(enriched) {
  const flags = enriched.security_flags || [];

  if (flags.some(f => f.flag === 'RPKI_INVALID')) {
    return 'WEAPONIZATION'; // BGP hijack = active attack infrastructure setup
  }

  if (flags.some(f => f.flag === 'MALICIOUS_IP')) {
    return 'DELIVERY'; // Known malicious IP attempting connection
  }

  if (enriched.bgp_intel.announced === false) {
    return 'EXPLOITATION'; // Unknown IP not in routing table = potentially spoofed
  }

  return 'RECONNAISSANCE'; // Announced legitimate IP but with anomalous traffic pattern
}

/**
 * Map to MITRE ATT&CK framework
 */
function mapToMitreAttack(enriched) {
  const mapping = [];

  if (enriched.bgp_intel.rpki_valid === false) {
    mapping.push({
      technique: 'T1040', // Network Sniffing (implicit in BGP hijack)
      tactic: 'Credential Access / Collection',
      description: 'BGP RPKI validation failed - possible route hijack',
    });
  }

  if (enriched.threat_intel?.threat_level === 'CRITICAL') {
    mapping.push({
      technique: 'T1566', // Phishing (network variant)
      tactic: 'Initial Access',
      description: 'Connection from known malicious IP',
    });
  }

  return mapping;
}

/**
 * Enrich a finding with BGP + RPKI + Threat data
 * @param {Object} finding - MAGATAMA finding { ip_address, port, protocol, ... }
 * @returns {Object} Enriched finding with bgp_status, rpki_valid, threat_level
 */
async function enrichFindingWithBGPIntel(finding) {
  const enriched = { ...finding, bgp_intel: {} };
  const ipAddress = finding.ip_address;

  if (!ipAddress) {
    console.log('[S2TEN Enrichment] No IP address in finding, skipping enrichment');
    return enriched;
  }

  try {
    // ---- Step 1: BGP Status Lookup ----
    // Check if this IP is part of an announced prefix in our local BGP routes
    const bgpStatus = await getBgpStatus(ipAddress);
    if (bgpStatus) {
      enriched.bgp_intel.announced = true;
      enriched.bgp_intel.prefix = bgpStatus.prefix;
      enriched.bgp_intel.origin_asn = bgpStatus.origin_asns ? bgpStatus.origin_asns[0] : null;
      enriched.bgp_intel.origin_asns = bgpStatus.origin_asns || [];
      enriched.bgp_intel.visibility_percent = bgpStatus.visibility_percent;
      enriched.bgp_intel.last_seen = bgpStatus.last_seen;

      // ---- Step 2: RPKI Validity Check ----
      // If we know the origin ASN, validate RPKI
      if (enriched.bgp_intel.origin_asn) {
        try {
          const rpkiResult = await validateRpki(
            bgpStatus.prefix || ipAddress,
            enriched.bgp_intel.origin_asn
          );
          enriched.bgp_intel.rpki_status = rpkiResult.status;
          enriched.bgp_intel.rpki_valid = rpkiResult.status === 'valid';

          // Alert if RPKI is INVALID (potential hijack!)
          if (rpkiResult.status === 'invalid') {
            enriched.security_flags = enriched.security_flags || [];
            enriched.security_flags.push({
              flag: 'RPKI_INVALID',
              severity: 'CRITICAL',
              message: `RPKI validation failed: AS${enriched.bgp_intel.origin_asn} is not authorized to announce this prefix`,
            });
          }
        } catch (e) {
          console.error(`[S2TEN] RPKI check failed for ${ipAddress}:`, e.message);
          enriched.bgp_intel.rpki_status = 'unknown';
        }
      }
    } else {
      enriched.bgp_intel.announced = false;
      enriched.bgp_intel.message = 'IP not found in BGP routing table';
    }

    // ---- Step 3: Threat Intelligence Lookup ----
    // Check if this IP or its origin ASN is in threat_intel table
    const threatIntel = await getThreatIntel(ipAddress);
    if (threatIntel) {
      enriched.threat_intel = {
        ip_address: threatIntel.ip_address,
        threat_level: threatIntel.threat_level,
        confidence_score: threatIntel.confidence_score,
        source: threatIntel.source,
        cached_at: threatIntel.cached_at,
      };

      // Alert if threat level is HIGH or CRITICAL
      if (['HIGH', 'CRITICAL'].includes(threatIntel.threat_level)) {
        enriched.security_flags = enriched.security_flags || [];
        enriched.security_flags.push({
          flag: 'MALICIOUS_IP',
          severity: threatIntel.threat_level,
          message: `Known malicious IP: threat level ${threatIntel.threat_level} (confidence: ${threatIntel.confidence_score}%)`,
          source: threatIntel.source,
        });
      }
    }

    // ---- Step 4: MAGATAMA Kill-Chain Correlation ----
    // Map BGP + RPKI + Threat findings to MITRE ATT&CK kill chain
    enriched.kill_chain_phase = determineKillChainPhase(enriched);
    enriched.mitre_attack_mapping = mapToMitreAttack(enriched);

    return enriched;
  } catch (e) {
    console.error(`[S2TEN Enrichment] Fatal error enriching ${ipAddress}:`, e.message);
    enriched.enrichment_error = e.message;
    return enriched;
  }
}

/**
 * Batch enrich multiple findings
 */
async function enrichFindings(findings) {
  console.log(`[S2TEN Enrichment] Enriching ${findings.length} findings...`);
  const enriched = [];

  for (const finding of findings) {
    try {
      const result = await enrichFindingWithBGPIntel(finding);
      enriched.push(result);
    } catch (e) {
      console.error(`[S2TEN Enrichment] Error enriching finding:`, e.message);
      enriched.push({ ...finding, enrichment_error: e.message });
    }
  }

  return enriched;
}

module.exports = {
  enrichFindingWithBGPIntel,
  enrichFindings,
  determineKillChainPhase,
  mapToMitreAttack,
  pool,
  getBgpStatus,
  validateRpki,
  getThreatIntel,
};
