'use client';

import React, { createContext, useContext, useState, useEffect } from 'react';
import api from '@/lib/axios';
import type { AxiosError } from 'axios';
import { useAuth } from '@/context/AuthContext';
import { DetailedDevice } from '@/types/devices';
import { disableConsoleInProd } from '@/lib/disableConsole';
disableConsoleInProd();

interface DriveInfo {
  name: string;
  driveType: string;
  totalSizeGB: number;
  freeSpaceGB: number;
}

interface IpAddress {
  interfaceName: string;
  ipAddress: string;
}

interface MacAddress {
  interfaceName: string;
  macAddress: string;
}

interface InstalledApp {
  app_name: string;
  app_version: string;
  publisher: string;
}

type RawRecord = Record<string, unknown>;

const normalizeKey = (key: string): string =>
  key.toLowerCase().replace(/[^a-z0-9]/g, '');

const getDirectValue = (source: RawRecord | null | undefined, keys: string[]): unknown => {
  if (!source) return undefined;
  for (const key of keys) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      const value = source[key];
      if (value !== undefined && value !== null) {
        return value;
      }
    }
  }
  return undefined;
};

const findValueDeep = (
  source: unknown,
  normalizedTargets: string[],
  seen = new WeakSet<object>()
): unknown => {
  if (!source || typeof source !== 'object') return undefined;

  const stack: unknown[] = [source];

  while (stack.length > 0) {
    const current = stack.pop();
    if (!current || typeof current !== 'object') continue;

    if (seen.has(current as object)) continue;
    seen.add(current as object);

    if (Array.isArray(current)) {
      for (const item of current) {
        if (item && (typeof item === 'object' || typeof item === 'string')) {
          stack.push(item);
        }
      }
      continue;
    }

    for (const [key, value] of Object.entries(current as RawRecord)) {
      const normalizedKey = normalizeKey(key);
      if (normalizedTargets.includes(normalizedKey) && value !== undefined && value !== null) {
        return value;
      }
      if (value && typeof value === 'object') {
        stack.push(value);
      }
    }
  }

  return undefined;
};

const resolveValue = (
  source: RawRecord | null | undefined,
  keys: string[],
  fallbackKeys: string[] = keys
): unknown => {
  if (!source) return undefined;

  const direct = getDirectValue(source, keys);
  if (direct !== undefined && direct !== null) {
    return direct;
  }

  const normalizedTargets = Array.from(new Set(fallbackKeys.map(normalizeKey))).filter(Boolean);
  return findValueDeep(source, normalizedTargets);
};

const resolveArray = <T = unknown>(
  source: RawRecord | null | undefined,
  keys: string[],
  fallbackKeys?: string[]
): T[] | undefined => {
  const value = resolveValue(source, keys, fallbackKeys ?? keys);
  if (Array.isArray(value)) {
    return value as T[];
  }
  return undefined;
};

const toOptionalString = (value: unknown): string | undefined => {
  if (value === null || value === undefined) return undefined;
  if (typeof value === 'string') return value;
  if (typeof value === 'number' || typeof value === 'boolean') return String(value);
  return undefined;
};

const toNonEmptyString = (value: unknown, fallback = ''): string => {
  const candidate = toOptionalString(value)?.trim();
  return candidate && candidate.length > 0 ? candidate : fallback;
};

const parseSizeToGB = (value: unknown): number => {
  if (value === null || value === undefined) return 0;

  const normalizeNumeric = (num: number): number => {
    if (!Number.isFinite(num)) return 0;
    if (num > 1024 ** 3) return +(num / 1024 ** 3).toFixed(2); // bytes
    if (num > 1024 ** 2) return +(num / 1024 ** 2).toFixed(2); // KB
    if (num > 1024) return +(num / 1024).toFixed(2); // MB
    return +num.toFixed(2); // already GB
  };

  if (typeof value === 'number') {
    return normalizeNumeric(value);
  }

  if (typeof value === 'string') {
    const trimmed = value.trim();
    if (!trimmed) return 0;

    const numeric = parseFloat(trimmed.replace(/[^\d.\-]/g, ''));
    if (!Number.isFinite(numeric)) return 0;

    if (/tb/i.test(trimmed)) return +(numeric * 1024).toFixed(2);
    if (/gb/i.test(trimmed)) return +numeric.toFixed(2);
    if (/mb/i.test(trimmed)) return +(numeric / 1024).toFixed(2);
    if (/kb/i.test(trimmed)) return +(numeric / (1024 ** 2)).toFixed(2);
    if (/bytes?/i.test(trimmed)) return +(numeric / (1024 ** 3)).toFixed(2);

    return normalizeNumeric(numeric);
  }

  return 0;
};

const normalizeDrive = (driveInput: unknown, index: number): DriveInfo | null => {
  if (!driveInput || typeof driveInput !== 'object') return null;
  const drive = driveInput as RawRecord;

  const name = toNonEmptyString(
    resolveValue(drive, ['name', 'driveName', 'label', 'volume'], [
      'name',
      'driveName',
      'label',
      'volume',
      'drive_letter',
      'driveletter',
      'mount_point',
      'mountpoint',
      'logicaldisk',
      'deviceid',
    ]) ?? `Drive ${index + 1}`,
    `Drive ${index + 1}`
  );
  const driveType = toNonEmptyString(
    resolveValue(drive, ['driveType', 'drive_type', 'type'], [
      'driveType',
      'drive_type',
      'type',
      'drivetype',
      'mediatype',
      'busType',
    ]),
    'Unknown'
  );
  const totalSizeGB = parseSizeToGB(
    resolveValue(
      drive,
      ['totalSizeGB', 'total_size_gb', 'totalSize', 'total_size', 'size', 'capacity', 'totalBytes', 'total_bytes'],
      [
        'totalSizeGB',
        'total_size_gb',
        'totalSize',
        'total_size',
        'size',
        'capacity',
        'totalBytes',
        'total_bytes',
        'size_bytes',
        'capacity_bytes',
        'totalsize',
        'totalspace',
        'totalspacebytes',
      ]
    )
  );
  const freeSpaceGB = parseSizeToGB(
    resolveValue(
      drive,
      ['freeSpaceGB', 'free_space_gb', 'freeSpace', 'free_space', 'free', 'freeBytes', 'free_bytes', 'availableBytes'],
      [
        'freeSpaceGB',
        'free_space_gb',
        'freeSpace',
        'free_space',
        'free',
        'freeBytes',
        'free_bytes',
        'availableBytes',
        'available_bytes',
        'freespace',
        'freespacebytes',
        'remaining',
      ]
    )
  );

  if (!name && !totalSizeGB && !freeSpaceGB) return null;

  return {
    name,
    driveType,
    totalSizeGB,
    freeSpaceGB,
  };
};

const extractDrives = (rawInput: unknown): DriveInfo[] => {
  if (!rawInput || typeof rawInput !== 'object') return [];
  const raw = rawInput as RawRecord;

  const potentialArrays = [
    resolveArray(raw, ['drives']),
    resolveArray(raw, ['driveInfo']),
    resolveArray(raw, ['drive_info']),
    resolveArray(raw, ['storageDevices']),
    resolveArray(raw, ['drive_details']),
    resolveArray(raw, ['storage']),
    resolveArray(raw, ['logicalDrives']),
    resolveArray(raw, ['logical_drives']),
    resolveArray(raw, ['volumes']),
    resolveArray(raw, ['volume_info']),
    resolveArray(raw, ['disks']),
  ];

  for (const candidate of potentialArrays) {
    if (Array.isArray(candidate)) {
      return candidate
        .map((drive, idx: number) => normalizeDrive(drive, idx))
        .filter((drive): drive is DriveInfo => Boolean(drive));
    }
  }

  const aggregatedDrive = {
    totalSize: resolveValue(raw, ['total_disk_space', 'totalDiskSpace', 'total_storage'], [
      'total_disk_space',
      'totalDiskSpace',
      'total_storage',
      'totalSpace',
      'total_space',
      'storage_total',
      'disk_total',
    ]),
    freeSpace: resolveValue(raw, ['free_disk_space', 'freeDiskSpace', 'available_storage'], [
      'free_disk_space',
      'freeDiskSpace',
      'available_storage',
      'free_storage',
      'freeSpace',
      'free_space',
      'availableSpace',
      'available_space',
      'storage_free',
    ]),
  };

  if (aggregatedDrive.totalSize || aggregatedDrive.freeSpace) {
    const normalized = normalizeDrive(
      {
        name: 'System',
        driveType: 'Unknown',
        totalSizeGB: aggregatedDrive.totalSize,
        freeSpaceGB: aggregatedDrive.freeSpace,
      },
      0
    );

    return normalized ? [normalized] : [];
  }

  return [];
};

const normalizeIpAddress = (entryInput: unknown, index: number): IpAddress | null => {
  if (!entryInput || typeof entryInput !== 'object') return null;
  const entry = entryInput as RawRecord;

  const ipAddress = toNonEmptyString(
    resolveValue(entry, ['ipAddress', 'ip_address', 'address', 'ip', 'ipv4', 'ipv6'], [
      'ipAddress',
      'ip_address',
      'address',
      'ip',
      'ipv4',
      'ipv6',
      'primary_ip',
      'primaryIp',
      'lan_ip',
    ]) ?? '',
    ''
  );

  const interfaceName = toNonEmptyString(
    resolveValue(entry, ['interfaceName', 'interface_name', 'adapter', 'name', 'nic'], [
      'interfaceName',
      'interface_name',
      'adapter',
      'name',
      'nic',
      'network_adapter',
      'interface',
      'description',
    ]) ?? '',
    ipAddress ? `Interface ${index + 1}` : ''
  );

  if (!ipAddress && !interfaceName) return null;

  const macAddress = toOptionalString(
    resolveValue(entry, ['macAddress', 'mac_address', 'mac', 'physicalAddress'], [
      'macAddress',
      'mac_address',
      'mac',
      'physicalAddress',
      'physical_address',
      'hw_address',
    ])
  );

  return {
    interfaceName: interfaceName || `Interface ${index + 1}`,
    ipAddress: ipAddress || 'Unknown',
    macAddress: macAddress?.trim() || undefined,
  };
};

const extractIpAddresses = (rawInput: unknown): IpAddress[] => {
  if (!rawInput || typeof rawInput !== 'object') return [];
  const raw = rawInput as RawRecord;

  const potentialArrays = [
    resolveArray(raw, ['ipAddresses']),
    resolveArray(raw, ['ip_addresses']),
    resolveArray(raw, ['networkInterfaces']),
    resolveArray(raw, ['network_interfaces']),
    resolveArray(raw, ['interfaces']),
    resolveArray(raw, ['networkAdapters']),
    resolveArray(raw, ['network_adapters']),
    resolveArray(raw, ['network']),
  ];

  for (const candidate of potentialArrays) {
    if (Array.isArray(candidate)) {
      return candidate
        .map((entry, idx: number) => normalizeIpAddress(entry, idx))
        .filter((entry): entry is IpAddress => Boolean(entry));
    }
  }

  const singleIp = resolveValue(raw, ['ipAddress', 'ip_address', 'primary_ip', 'primaryIp']);
  if (singleIp) {
    return [
      normalizeIpAddress(
        {
          ipAddress: singleIp,
          interfaceName: resolveValue(raw, ['interfaceName', 'interface_name', 'adapter']),
          macAddress: resolveValue(raw, ['macAddress', 'mac_address']),
        },
        0
      ) as IpAddress,
    ].filter(Boolean);
  }

  return [];
};

const normalizeInstalledApp = (appInput: unknown): InstalledApp | null => {
  if (!appInput || typeof appInput !== 'object') return null;
  const app = appInput as RawRecord;

  const appName = toNonEmptyString(
    resolveValue(app, ['app_name', 'name', 'title'], [
      'app_name',
      'name',
      'title',
      'display_name',
      'product_name',
    ]) ?? '',
    ''
  );
  if (!appName) return null;

  return {
    app_name: appName,
    app_version: toNonEmptyString(
      resolveValue(app, ['app_version', 'version'], ['app_version', 'version', 'display_version', 'product_version']) ?? '',
      ''
    ),
    publisher: toNonEmptyString(
      resolveValue(app, ['publisher', 'manufacturer', 'vendor'], [
        'publisher',
        'manufacturer',
        'vendor',
        'company',
        'publisher_name',
      ]) ?? '',
      ''
    ),
  };
};

const extractInstalledApps = (rawInput: unknown): InstalledApp[] => {
  if (!rawInput || typeof rawInput !== 'object') return [];
  const raw = rawInput as RawRecord;

  const potentialArrays = [
    resolveArray(raw, ['installedApplications']),
    resolveArray(raw, ['installed_applications']),
    resolveArray(raw, ['software']),
    resolveArray(raw, ['applications']),
    resolveArray(raw, ['apps']),
    resolveArray(raw, ['installedPrograms']),
    resolveArray(raw, ['installed_programs']),
    resolveArray(raw, ['programs']),
  ];

  for (const candidate of potentialArrays) {
    if (Array.isArray(candidate)) {
      return candidate
        .map((app) => normalizeInstalledApp(app))
        .filter((app): app is InstalledApp => Boolean(app));
    }
  }
  return [];
};

const extractMacAddresses = (rawInput: unknown, ipAddresses: IpAddress[]): MacAddress[] => {
  if (!rawInput || typeof rawInput !== 'object') return [];
  const raw = rawInput as RawRecord;
  const potentialArrays = resolveArray(raw, ['macAddresses', 'mac_addresses', 'macs', 'mac_list']);

  if (Array.isArray(potentialArrays)) {
    return potentialArrays
      .map((entry, idx: number) => {
        if (!entry || typeof entry !== 'object') return null;
        const record = entry as RawRecord;
        const macAddress = toOptionalString(
          resolveValue(record, ['macAddress', 'mac_address', 'mac'], [
            'macAddress',
            'mac_address',
            'mac',
            'physicalAddress',
            'hw_address',
          ])
        );
        if (!macAddress) return null;
        return {
          interfaceName: toNonEmptyString(
            resolveValue(record, ['interfaceName', 'interface_name', 'adapter'], [
              'interfaceName',
              'interface_name',
              'adapter',
              'network_adapter',
              'name',
            ]) ?? `Interface ${idx + 1}`,
            `Interface ${idx + 1}`
          ),
          macAddress: macAddress.trim(),
        };
      })
      .filter((entry): entry is MacAddress => Boolean(entry));
  }

  return ipAddresses
    .filter((entry) => Boolean(entry.macAddress))
    .map((entry) => ({
      interfaceName: entry.interfaceName,
      macAddress: entry.macAddress as string,
    }));
};

const splitGpuNames = (value: unknown): string[] => {
  if (Array.isArray(value)) {
    return value
      .map((item) => toNonEmptyString(item, ''))
      .filter((item) => item.length > 0);
  }

  if (typeof value === 'string') {
    return value
      .split(/[,;\n]+/)
      .map((item) => item.trim())
      .filter((item) => item.length > 0);
  }

  return [];
};

const normalizeDevice = (rawInput: unknown): DetailedDevice => {
  const raw: RawRecord =
    rawInput && typeof rawInput === 'object' ? (rawInput as RawRecord) : {};

  const deviceId = Number(
    resolveValue(raw, ['deviceId', 'device_id', 'id', 'deviceID', 'device_id_pk'], [
      'deviceId',
      'device_id',
      'id',
      'deviceID',
      'device_id_pk',
    ]) ?? 0
  );

  const drives = extractDrives(raw);
  const ipAddresses = extractIpAddresses(raw);
  const macAddresses = extractMacAddresses(raw, ipAddresses);
  const clientEntry = resolveValue(raw, ['client'], ['client', 'clientInfo', 'customer']);
  const clientNameFromNested =
    clientEntry && typeof clientEntry === 'object'
      ? resolveValue(clientEntry as RawRecord, ['name', 'clientName', 'client_name'])
      : undefined;

  const hostname = toNonEmptyString(
    resolveValue(raw, ['hostname', 'hostName', 'computerName', 'deviceName'], [
      'hostname',
      'hostName',
      'computerName',
      'deviceName',
      'host',
      'machineName',
    ]) ?? `Device ${deviceId}`,
    deviceId ? `Device ${deviceId}` : 'Unknown Device'
  );

  return {
    deviceId,
    hostname,
    osName: toNonEmptyString(
      resolveValue(
        raw,
        ['osName', 'os_name', 'operatingSystem', 'os'],
        [
          'osName',
          'os_name',
          'operatingSystem',
          'operating_system',
          'operatingSystemName',
          'operating_system_name',
          'osFriendlyName',
          'os_caption',
          'oscaption',
          'os',
        ]
      ) ?? '',
      ''
    ),
    osVersion: toNonEmptyString(
      resolveValue(raw, ['osVersion', 'os_version', 'osVersionString'], [
        'osVersion',
        'os_version',
        'osVersionString',
        'operatingSystemVersion',
        'osversion',
      ]) ?? '',
      ''
    ),
    windowsVersion: toNonEmptyString(
      resolveValue(raw, ['windowsVersion', 'windows_version', 'osRelease'], [
        'windowsVersion',
        'windows_version',
        'osRelease',
        'windowsRelease',
        'windows_release',
      ]) ?? '',
      ''
    ),
    windowsBuild: toNonEmptyString(
      resolveValue(raw, ['windowsBuild', 'windows_build', 'buildNumber'], [
        'windowsBuild',
        'windows_build',
        'buildNumber',
        'build_number',
        'windowsBuildNumber',
      ]) ?? '',
      ''
    ),
    osArchitecture: toNonEmptyString(
      resolveValue(raw, ['osArchitecture', 'os_architecture', 'architecture'], [
        'osArchitecture',
        'os_architecture',
        'architecture',
        'platform',
        'osarch',
      ]) ?? '',
      ''
    ),
    processorName: toNonEmptyString(
      resolveValue(raw, ['processorName', 'processor_name', 'cpuName'], [
        'processorName',
        'processor_name',
        'cpuName',
        'cpu_name',
        'processor',
      ]) ?? '',
      ''
    ),
    processorArchitecture: toNonEmptyString(
      resolveValue(raw, ['processorArchitecture', 'processor_architecture', 'cpuArchitecture'], [
        'processorArchitecture',
        'processor_architecture',
        'cpuArchitecture',
        'cpu_architecture',
        'cpuArch',
      ]) ?? '',
      ''
    ),
    gpuNames: splitGpuNames(
      resolveValue(raw, ['gpuNames', 'gpu_names', 'gpu_name', 'gpus', 'graphics']) ?? []
    ),
    totalMemory: toNonEmptyString(
      resolveValue(
        raw,
        ['totalMemory', 'total_memory', 'memory', 'totalMemoryMb', 'totalMemoryMB'],
        [
          'totalMemory',
          'total_memory',
          'memory',
          'totalMemoryMb',
          'totalMemoryMB',
          'memory_total',
          'ram_total',
          'physicalMemory',
        ]
      ) ?? '',
      ''
    ),
    lastBootTime: toNonEmptyString(
      resolveValue(raw, ['lastBootTime', 'last_boot_time', 'bootTime', 'lastBoot', 'lastBootUpTime'], [
        'lastBootTime',
        'last_boot_time',
        'bootTime',
        'lastBoot',
        'lastBootUpTime',
        'last_boot',
        'boot_time',
      ]) ?? '',
      ''
    ),
    lastCheckedIn: toNonEmptyString(
      resolveValue(raw, ['lastCheckedIn', 'last_checked_in', 'lastSeen', 'checked_in_at'], [
        'lastCheckedIn',
        'last_checked_in',
        'lastSeen',
        'checked_in_at',
        'lastSeenAt',
        'last_seen',
      ]) ?? '',
      ''
    ),
    drives,
    ipAddresses,
    macAddresses,
    installedApplications: extractInstalledApps(raw),
    clientName:
      toOptionalString(
        resolveValue(raw, ['clientName', 'client_name'], ['clientName', 'client_name', 'client']) ??
          clientNameFromNested ??
          resolveValue(raw, ['clientIdentifier', 'client_identifier'])
      ) ?? undefined,
  };
};


interface DeviceVulnerability {
  cveId: string;
  title: string;
  severity: string;
  score?: number;
  publishedDate: string;   
  lastModifiedDate: string;  
}

interface CachedSoftwareEntry {
  id: number;
  softwareName: string;
  hostname: string;
  version: string;
  deviceId: number;
  totalCves: number;
  lastUpdated: string;
}

interface RawDevicesResponse {
  devices?: unknown[];
  vulnerabilitiesByDevice?: { [deviceId: string]: DeviceVulnerability[] };
}

interface DeviceContextType {
  devices: DetailedDevice[];
  deviceVulns: { [deviceId: string]: DeviceVulnerability[] };
  cachedSoftware: CachedSoftwareEntry[];
  detailedCveLookup: { [cveId: string]: DeviceVulnerability }; // 🔥 New
  setDevices: React.Dispatch<React.SetStateAction<DetailedDevice[]>>;
  setDeviceVulns: React.Dispatch<React.SetStateAction<{ [deviceId: string]: DeviceVulnerability[] }>>;
  setCachedSoftware: React.Dispatch<React.SetStateAction<CachedSoftwareEntry[]>>;
  setDetailedCveLookup: React.Dispatch<React.SetStateAction<{ [cveId: string]: DeviceVulnerability }>>;
  loading: boolean;
}


const DeviceContext = createContext<DeviceContextType | undefined>(undefined);


export const useDeviceContext = () => {
  const context = useContext(DeviceContext);
  if (!context) {
    throw new Error('useDeviceContext must be used within a DeviceProvider');
  }
  return context;
};

export const DeviceProvider = ({
  children,
  initialData,
}: {
  children: React.ReactNode;
  initialData?: {
    devices: DetailedDevice[];
    vulnerabilitiesByDevice: { [deviceId: string]: DeviceVulnerability[] };
  };
}) => {
  const [devices, setDevices] = useState<DetailedDevice[]>(() => {
    if (initialData?.devices?.length) {
      return initialData.devices.map((device) => normalizeDevice(device));
    }
    return [];
  });

  const [deviceVulns, setDeviceVulns] = useState<{ [deviceId: string]: DeviceVulnerability[] }>(
    initialData?.vulnerabilitiesByDevice ?? {}
  );

  const [detailedCveLookup, setDetailedCveLookup] = useState<{ [cveId: string]: DeviceVulnerability }>({});

  const [cachedSoftware, setCachedSoftware] = useState<CachedSoftwareEntry[]>([]); // ⬅️ NEW

  const [loading, setLoading] = useState<boolean>(!initialData);

  const { username, roles, loading: authLoading } = useAuth();

  useEffect(() => {
    if (devices.length > 0 || initialData || authLoading || !username) return;
  
    const fetchDevicesVulnsAndSoftware = async () => {
      try {
        const isAdmin = roles?.includes('ADMIN');
        const devicesEndpoint = isAdmin
          ? '/cached/devices/with-vulns/all'
          : '/cached/devices/with-vulns';
        const softwareEndpoint = '/cached/software/summary';
    
        console.group('📡 Fetching Devices, Vulnerabilities, and Software');
    
        const [devicesRes, softwareRes] = await Promise.all([
          api.get<RawDevicesResponse>(devicesEndpoint, { withCredentials: true }),
          api.get<CachedSoftwareEntry[]>(softwareEndpoint, { withCredentials: true }),
        ]);
    
        console.log('✅ Devices fetched:', devicesRes.data);
        console.log('✅ Software fetched:', softwareRes.data);
        console.groupEnd();
    
        // STEP 1: Set basic data (keep original UTC timestamps for calculations)
        const normalizedDevices = Array.isArray(devicesRes.data?.devices)
          ? (devicesRes.data.devices as unknown[]).map((device) => normalizeDevice(device))
          : [];

        setDevices(normalizedDevices);
        setDeviceVulns(devicesRes.data?.vulnerabilitiesByDevice ?? {});
        setCachedSoftware(softwareRes.data ?? []);
    
        // STEP 2: Extract all unique CVE IDs
        const uniqueCveIds = new Set<string>();
        Object.values(devicesRes.data?.vulnerabilitiesByDevice ?? {}).forEach((vulns) => {
          vulns.forEach((vuln) => {
            if (vuln.cveId) {
              uniqueCveIds.add(vuln.cveId);
            }
          });
        });
    
        // STEP 3: Fetch detailed CVE data
        if (uniqueCveIds.size > 0) {
          console.log('🔎 Fetching detailed CVEs for:', Array.from(uniqueCveIds));
          const params = new URLSearchParams();
Array.from(uniqueCveIds).forEach(cveId => {
  params.append('cveIds', cveId);
});

const cveDetailsRes = await api.get<DeviceVulnerability[]>('/vuln/cves/lookup', {
  params,
  withCredentials: true,
});

          
          
    
          const lookupMap: { [cveId: string]: DeviceVulnerability } = {};
          cveDetailsRes.data.forEach((cve) => {
            lookupMap[cve.cveId] = cve;
          });
    
          setDetailedCveLookup(lookupMap);
        }
    
      } catch (error) {
        console.group('❌ Device fetch failed');
        const axiosError = error as AxiosError;
        console.error('🔴 Axios Error Message:', axiosError.message);
        console.error('🧾 Axios Error Config:', axiosError.config);
        if (axiosError.response) {
          console.error('📉 Status:', axiosError.response.status);
          console.error('📄 Response Headers:', axiosError.response.headers);
          console.error('📄 Response Data:', axiosError.response.data);
        } else if (axiosError.request) {
          console.error('🛑 No response received:', axiosError.request);
        } else {
          console.error('❓ Unexpected error:', error);
        }
        console.groupEnd();
      } finally {
        setLoading(false);
      }
    };
    
      
  
      fetchDevicesVulnsAndSoftware();
}, [devices.length, initialData, username, authLoading, roles]);
  
  useEffect(() => {
    console.log("🧠 Devices updated:", devices);
  }, [devices]);
  
  if (typeof window !== 'undefined') {
    (window as Window & { __debug_devices?: DetailedDevice[] }).__debug_devices = devices;
  }
  
  return (
    <DeviceContext.Provider value={{
      devices,
      deviceVulns,
      cachedSoftware,
      detailedCveLookup,           // ✅ provide it!
      setDevices,
      setDeviceVulns,
      setCachedSoftware,
      setDetailedCveLookup,        // ✅ provide this too!
      loading,
    }}>
    
      {children}
    </DeviceContext.Provider>
  );
};
