// ADS-B Exchange — Unfiltered Flight Tracking (including Military)
// Unlike FlightRadar24/FlightAware, ADS-B Exchange does NOT filter military aircraft.
// Public feed access varies; RapidAPI tier available for programmatic use.
// This module reports explicit disabled/degraded state instead of making
// unavailable aircraft data look live.

import { safeFetch } from '../utils/fetch.mjs';

// Known endpoints (availability may change)
const ENDPOINTS = {
  // v2 API via RapidAPI (requires ADSB_API_KEY)
  rapidApi: 'https://adsbexchange-com1.p.rapidapi.com/v2',
  // Public globe feed (may be rate-limited or blocked for automated access)
  publicFeed: 'https://globe.adsbexchange.com/data/aircraft.json',
  // Alternative: aircraft within bounding box
  publicTrace: 'https://globe.adsbexchange.com/data/traces',
};

// Known military aircraft types and ICAO type designators
const MILITARY_TYPES = {
  // Reconnaissance / ISR
  'RC135': 'RC-135 Rivet Joint (SIGINT)',
  'E3CF':  'E-3 Sentry AWACS',
  'E3TF':  'E-3 Sentry AWACS',
  'E6B':   'E-6B Mercury (TACAMO)',
  'EP3':   'EP-3 Aries (SIGINT)',
  'P8':    'P-8 Poseidon (Maritime Patrol)',
  'P8A':   'P-8A Poseidon',
  'RQ4':   'RQ-4 Global Hawk (UAV)',
  'RQ4B':  'RQ-4B Global Hawk',
  'U2':    'U-2 Dragon Lady',
  'MQ9':   'MQ-9 Reaper (UAV)',
  'MQ1':   'MQ-1 Predator (UAV)',
  'E8':    'E-8 JSTARS',
  // Tankers
  'KC135': 'KC-135 Stratotanker',
  'KC10':  'KC-10 Extender',
  'KC46':  'KC-46 Pegasus',
  // Bombers
  'B52':   'B-52 Stratofortress',
  'B1':    'B-1B Lancer',
  'B2':    'B-2 Spirit',
  // Transport / Special
  'C17':   'C-17 Globemaster III',
  'C5':    'C-5 Galaxy',
  'C130':  'C-130 Hercules',
  'VC25':  'VC-25 (Air Force One)',
  'E4B':   'E-4B Nightwatch (Doomsday Plane)',
  'C32':   'C-32 (Air Force Two)',
  'C40':   'C-40 Clipper',
};

// Known military ICAO hex ranges (partial — US military allocations)
const MIL_HEX_RANGES = [
  { start: 0xADF7C8, end: 0xAFFFFF, country: 'US Military' },
  { start: 0xAE0000, end: 0xAFFFFF, country: 'US Military (alt)' },
  { start: 0x43C000, end: 0x43CFFF, country: 'UK Military' },
  { start: 0x3F0000, end: 0x3FFFFF, country: 'France Military' },
  { start: 0x3CC000, end: 0x3CFFFF, country: 'Germany Military' },
];

// Interesting callsign patterns that suggest military/government flights
const MIL_CALLSIGN_PATTERNS = [
  /^RCH/,      // US AMC (Air Mobility Command) — strategic airlift
  /^REACH/,    // US AMC alternate
  /^DUKE/,     // Often military special ops
  /^IRON/,     // US military
  /^JAKE/,     // Military
  /^NAVY/,     // US Navy
  /^TOPCAT/,   // E-6B Mercury
  /^DARKST/,   // Dark Star / classified
  /^GORDO/,    // USAF
  /^BISON/,    // B-52
  /^DEATH/,    // B-1B
  /^DOOM/,     // E-4B
  /^SAM/,      // Special Air Mission (VIP)
  /^EXEC/,     // Executive transport
  /^PCSF/,     // Chinese military
  /^CHN/,      // Chinese military
  /^RF/,       // Russian Air Force
  /^RFF/,      // Russian Air Force
];

// Check if an ICAO hex code falls in known military ranges
function isMilitaryHex(hex) {
  if (!hex) return false;
  const num = parseInt(hex, 16);
  if (isNaN(num)) return false;
  return MIL_HEX_RANGES.find(r => num >= r.start && num <= r.end) || null;
}

// Check if a callsign matches military patterns
function isMilitaryCallsign(callsign) {
  if (!callsign) return false;
  const cs = callsign.trim().toUpperCase();
  return MIL_CALLSIGN_PATTERNS.some(p => p.test(cs));
}

// Check if aircraft type is a known military type
function isMilitaryType(typeCode) {
  if (!typeCode) return false;
  const tc = typeCode.toUpperCase().replace(/[^A-Z0-9]/g, '');
  return MILITARY_TYPES[tc] || null;
}

// Classify an aircraft from ADS-B data
function classifyAircraft(ac) {
  const hex = ac.hex || ac.icao || ac.icao24 || null;
  const callsign = ac.flight || ac.callsign || ac.call || '';
  const type = ac.t || ac.type || ac.typecode || '';
  const mil = ac.mil || ac.military || false;

  const milHex = isMilitaryHex(hex);
  const milCall = isMilitaryCallsign(callsign);
  const milType = isMilitaryType(type);

  const isMilitary = !!(mil || milHex || milCall || milType);

  return {
    hex,
    callsign: callsign.trim(),
    type,
    typeDescription: milType || null,
    latitude: ac.lat || ac.latitude || null,
    longitude: ac.lon || ac.longitude || null,
    altitude: ac.alt_baro || ac.alt_geom || ac.altitude || null,
    speed: ac.gs || ac.speed || null,
    heading: ac.track || ac.heading || null,
    squawk: ac.squawk || null,
    isMilitary,
    militaryMatch: milHex?.country || (milCall ? 'callsign pattern' : null) || (milType ? 'type match' : null),
    registration: ac.r || ac.registration || null,
    seen: ac.seen || ac.last_contact || null,
  };
}

// Attempt to fetch from RapidAPI (requires ADSB_API_KEY)
async function fetchViaRapidApi(apiKey) {
  if (!apiKey) return null;

  // Get all military aircraft
  const data = await safeFetch(`${ENDPOINTS.rapidApi}/mil`, {
    timeout: 20000,
    source: 'adsb-rapidapi',
    headers: {
      'X-RapidAPI-Key': apiKey,
      'X-RapidAPI-Host': 'adsbexchange-com1.p.rapidapi.com',
    },
  });

  return data;
}

// Attempt to fetch from public feed
async function fetchPublicFeed() {
  const data = await safeFetch(ENDPOINTS.publicFeed, { timeout: 15000, source: 'adsb-public' });
  return data;
}

async function getMilitaryAircraftResult(apiKey) {
  const failures = [];

  // Try RapidAPI first if key available
  if (apiKey) {
    const data = await fetchViaRapidApi(apiKey);
    if (data && !data.error) {
      const aircraft = data.ac || data.aircraft || [];
      if (Array.isArray(aircraft)) {
        return {
          provider: 'rapidapi',
          aircraft: aircraft.map(classifyAircraft).filter(a => a.isMilitary),
        };
      }
    }
    failures.push({ provider: 'rapidapi', error: data?.error || 'RapidAPI returned an unsupported payload' });
  }

  // Try public feed
  const pubData = await fetchPublicFeed();
  if (pubData && !pubData.error) {
    const aircraft = pubData.ac || pubData.aircraft || pubData.states || [];
    if (Array.isArray(aircraft)) {
      return {
        provider: 'public-feed',
        aircraft: aircraft.map(classifyAircraft).filter(a => a.isMilitary),
      };
    }
  }
  failures.push({ provider: 'public-feed', error: pubData?.error || 'Public feed returned an unsupported payload' });

  return { provider: null, aircraft: null, failures };
}

// Get military aircraft from available sources
export async function getMilitaryAircraft(apiKey) {
  const result = await getMilitaryAircraftResult(apiKey);
  return result.aircraft;
}

// Get all aircraft in a geographic bounding box via RapidAPI
export async function getAircraftInArea(lat, lon, radiusNm = 250, apiKey) {
  if (!apiKey) {
    return { error: 'ADSB_API_KEY required for area search', hint: 'Set ADSB_API_KEY (RapidAPI key)' };
  }

  const data = await safeFetch(
    `${ENDPOINTS.rapidApi}/lat/${lat}/lon/${lon}/dist/${radiusNm}/`,
    {
      timeout: 20000,
      headers: {
        'X-RapidAPI-Key': apiKey,
        'X-RapidAPI-Host': 'adsbexchange-com1.p.rapidapi.com',
      },
    }
  );

  if (data && !data.error) {
    const aircraft = data.ac || data.aircraft || [];
    if (Array.isArray(aircraft)) return aircraft.map(classifyAircraft);
  }

  return data;
}

// Briefing — attempt to get military flight data, document what's available
export async function briefing() {
  const apiKey = process.env.ADSB_API_KEY || process.env.RAPIDAPI_KEY || null;
  const result = await getMilitaryAircraftResult(apiKey);
  const militaryAircraft = result.aircraft;

  // If we got data, analyze it
  if (militaryAircraft && militaryAircraft.length > 0) {
    // Group by military match type
    const byCountry = {};
    const reconAircraft = [];
    const bombers = [];
    const tankers = [];
    const vipTransport = [];

    for (const ac of militaryAircraft) {
      const country = ac.militaryMatch || 'Unknown';
      byCountry[country] = (byCountry[country] || 0) + 1;

      const desc = (ac.typeDescription || '').toLowerCase();
      if (desc.includes('sigint') || desc.includes('awacs') || desc.includes('patrol') ||
          desc.includes('global hawk') || desc.includes('dragon lady') || desc.includes('jstars')) {
        reconAircraft.push(ac);
      } else if (desc.includes('stratofortress') || desc.includes('lancer') || desc.includes('spirit')) {
        bombers.push(ac);
      } else if (desc.includes('tanker') || desc.includes('extender') || desc.includes('pegasus')) {
        tankers.push(ac);
      } else if (desc.includes('air force one') || desc.includes('nightwatch') ||
                 desc.includes('air force two') || desc.includes('special air')) {
        vipTransport.push(ac);
      }
    }

    const signals = [];
    if (reconAircraft.length > 5) {
      signals.push(`HIGH ISR ACTIVITY: ${reconAircraft.length} reconnaissance/surveillance aircraft airborne`);
    }
    if (bombers.length > 0) {
      signals.push(`BOMBERS AIRBORNE: ${bombers.length} strategic bombers detected`);
    }
    if (tankers.length > 8) {
      signals.push(`ELEVATED TANKER OPS: ${tankers.length} aerial refueling aircraft active (possible surge)`);
    }
    if (vipTransport.length > 0) {
      signals.push(`VIP AIRCRAFT: ${vipTransport.length} VIP/continuity-of-government aircraft airborne`);
    }

    return {
      source: 'ADS-B Exchange',
      timestamp: new Date().toISOString(),
      status: 'live',
      provider: result.provider,
      totalMilitary: militaryAircraft.length,
      byCountry,
      categories: {
        reconnaissance: reconAircraft.slice(0, 20),
        bombers: bombers.slice(0, 10),
        tankers: tankers.slice(0, 10),
        vipTransport: vipTransport.slice(0, 5),
      },
      militaryAircraft: militaryAircraft.slice(0, 50), // cap for briefing size
      signals: signals.length > 0 ? signals : ['Military flight activity within normal patterns'],
    };
  }

  // No data available — return stub with integration documentation
  const status = apiKey ? 'degraded' : 'disabled';
  const error = apiKey
    ? 'ADS-B providers returned no usable aircraft data'
    : 'ADSB_API_KEY or RAPIDAPI_KEY is not configured';

  return {
    source: 'ADS-B Exchange',
    timestamp: new Date().toISOString(),
    status,
    provider: result.provider,
    error,
    failures: result.failures,
    militaryAircraft: [],
    message: apiKey
      ? 'ADS-B Exchange API returned no data. The endpoint may be temporarily unavailable.'
      : 'No ADS-B Exchange API key configured. Set ADSB_API_KEY for military flight tracking.',
    signals: ['ADS-B data unavailable — cannot assess military flight activity'],
    integrationGuide: {
      step1: 'Sign up at https://rapidapi.com/adsbexchange/api/adsbexchange-com1',
      step2: 'Subscribe to the free tier (500 requests/month)',
      step3: 'Set ADSB_API_KEY=<your-rapidapi-key> in .env',
      features: [
        'Unfiltered military aircraft tracking (unlike FlightRadar24)',
        'Real-time position, altitude, speed, heading',
        'ICAO hex code identification for military registrations',
        'Geographic area search within radius',
        'Dedicated /mil endpoint for military-only feed',
      ],
    },
    complementarySource: 'OpenSky (opensky.mjs) provides partial military coverage for free',
    knownMilitaryTypes: MILITARY_TYPES,
  };
}

// Run standalone
if (process.argv[1]?.endsWith('adsb.mjs')) {
  const data = await briefing();
  console.log(JSON.stringify(data, null, 2));
}
