import '../styles/main.css';
import { MapComponent } from '../components/Map';
import { initI18n } from '../services/i18n';

type MobileMapIntegrationHarness = {
  ready: boolean;
  pendingDeferredCallbacks: number;
  flushDeferredCallbacks: () => void;
  destroyMap: () => void;
  getDynamicLayerChildCount: () => number;
  getInitialDynamicRendered: () => boolean;
  getWrapperTransform: () => string;
  getPopupRect: () => {
    left: number;
    top: number;
    right: number;
    bottom: number;
    width: number;
    height: number;
    viewportWidth: number;
    viewportHeight: number;
  } | null;
};

declare global {
  interface Window {
    __mobileMapIntegrationHarness?: MobileMapIntegrationHarness;
  }
}

const app = document.getElementById('app');
if (!app) {
  throw new Error('Missing #app container for mobile map integration harness');
}

const controlDeferredCallbacks = new URLSearchParams(window.location.search).get('defer-control') === '1';
const deferredCallbacks: IdleRequestCallback[] = [];
if (controlDeferredCallbacks) {
  window.requestIdleCallback = ((callback: IdleRequestCallback) => {
    deferredCallbacks.push(callback);
    return deferredCallbacks.length;
  }) as typeof window.requestIdleCallback;
}

document.body.style.margin = '0';
document.body.style.overflow = 'hidden';

app.className = 'map-container';
app.style.width = '100vw';
app.style.height = '100vh';
app.style.position = 'relative';
app.style.overflow = 'hidden';

const MINIMAL_WORLD_TOPOLOGY = {
  type: 'Topology',
  objects: {
    countries: {
      type: 'GeometryCollection',
      geometries: [
        {
          type: 'Polygon',
          id: 1,
          arcs: [[0]],
        },
      ],
    },
  },
  arcs: [
    [
      [0, 0],
      [3600, 0],
      [0, 1800],
      [-3600, 0],
      [0, -1800],
    ],
  ],
  transform: {
    scale: [0.1, 0.1],
    translate: [-180, -90],
  },
};

const originalFetch = window.fetch.bind(window);
window.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
  const url =
    typeof input === 'string'
      ? input
      : input instanceof URL
      ? input.toString()
      : input.url;

  if (url.includes('/data/countries-50m.json')) {
    return new Response(JSON.stringify(MINIMAL_WORLD_TOPOLOGY), {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  return originalFetch(input, init);
}) as typeof fetch;

const layers = {
  gpsJamming: false,
  satellites: false,

  conflicts: false,
  bases: false,
  cables: false,
  pipelines: false,
  hotspots: true,
  ais: false,
  nuclear: false,
  irradiators: false,
  sanctions: false,
  weather: false,
  economic: false,
  waterways: false,
  outages: false,
  cyberThreats: false,
  datacenters: false,
  protests: false,
  flights: false,
  military: false,
  natural: false,
  spaceports: false,
  minerals: false,
  fires: false,
  ucdpEvents: false,
  displacement: false,
  climate: false,
  startupHubs: false,
  cloudRegions: false,
  accelerators: false,
  techHQs: false,
  techEvents: false,
  stockExchanges: false,
  financialCenters: false,
  centralBanks: false,
  commodityHubs: false,
  gulfInvestments: false,
  positiveEvents: false,
  kindness: false,
  happiness: false,
  speciesRecovery: false,
  renewableInstallations: false,
  tradeRoutes: false,
  iranAttacks: false,

  ciiChoropleth: false,
  resilienceScore: false,
  dayNight: false,
  miningSites: false,
  processingPlants: false,
  commodityPorts: false,
  webcams: false,
  diseaseOutbreaks: false,
};

await initI18n();

const map = new MapComponent(app, {
  zoom: 2.7,
  pan: { x: 0, y: 0 },
  view: 'global',
  layers,
  timeRange: 'all',
});

let ready = false;
let fallbackInjected = false;
const ensureHotspotsRendered = (): void => {
  if (document.querySelector('.hotspot')) {
    ready = true;
    return;
  }

  // Fallback for deterministic tests if the async world fetch is delayed.
  if (!fallbackInjected) {
    const mapInternals = map as unknown as {
      worldData: unknown;
      countryFeatures: unknown;
      baseRendered: boolean;
      hotspots: Array<{
        id: string;
        name: string;
        lat: number;
        lon: number;
        keywords: string[];
        level: 'low' | 'elevated' | 'high';
        description: string;
        status: string;
      }>;
      state: { layers: { hotspots: boolean } };
    };
    mapInternals.worldData = MINIMAL_WORLD_TOPOLOGY;
    mapInternals.countryFeatures = [
      {
        type: 'Feature',
        properties: { name: 'E2E Country' },
        geometry: {
          type: 'Polygon',
          coordinates: [[[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]]],
        },
      },
    ];
    mapInternals.hotspots = [
      {
        id: 'e2e-map-hotspot',
        name: 'E2E Map Hotspot',
        lat: 20,
        lon: 10,
        keywords: ['e2e', 'integration'],
        level: 'high',
        description: 'Integration harness hotspot',
        status: 'monitoring',
      },
    ];
    mapInternals.state.layers.hotspots = true;
    mapInternals.baseRendered = false;
    map.render();
    fallbackInjected = true;
  }

  requestAnimationFrame(ensureHotspotsRendered);
};
ensureHotspotsRendered();

window.__mobileMapIntegrationHarness = {
  get ready() {
    return ready;
  },
  get pendingDeferredCallbacks() {
    return deferredCallbacks.length;
  },
  flushDeferredCallbacks: () => {
    const callbacks = deferredCallbacks.splice(0);
    callbacks.forEach((callback) => {
      callback({
        didTimeout: false,
        timeRemaining: () => 50,
      });
    });
  },
  destroyMap: () => {
    map.destroy();
  },
  getDynamicLayerChildCount: () =>
    document.querySelector('.map-dynamic')?.childElementCount ?? 0,
  getInitialDynamicRendered: () =>
    Boolean((map as unknown as { initialDynamicRendered?: boolean }).initialDynamicRendered),
  getWrapperTransform: () =>
    (document.querySelector('.map-wrapper') as HTMLElement | null)?.style.transform ?? '',
  getPopupRect: () => {
    const element = document.querySelector('.map-popup') as HTMLElement | null;
    if (!element) return null;
    const rect = element.getBoundingClientRect();
    return {
      left: rect.left,
      top: rect.top,
      right: rect.right,
      bottom: rect.bottom,
      width: rect.width,
      height: rect.height,
      viewportWidth: window.innerWidth,
      viewportHeight: window.innerHeight,
    };
  },
};
