import { build } from 'esbuild';
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { createBrowserEnvironment } from './runtime-config-panel-harness.mjs';

const __dirname = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dirname, '..', '..');
const entry = resolve(root, 'src/components/CountryDeepDivePanel.ts');

function snapshotGlobal(name) {
  return {
    exists: Object.prototype.hasOwnProperty.call(globalThis, name),
    value: globalThis[name],
  };
}

function restoreGlobal(name, snapshot) {
  if (snapshot.exists) {
    Object.defineProperty(globalThis, name, {
      configurable: true,
      writable: true,
      value: snapshot.value,
    });
    return;
  }
  delete globalThis[name];
}

function defineGlobal(name, value) {
  Object.defineProperty(globalThis, name, {
    configurable: true,
    writable: true,
    value,
  });
}

async function loadCountryDeepDivePanel(options = {}) {
  const resilienceWidgetMode = options.resilienceWidgetMode ?? 'success';
  const premiumAccess = options.premiumAccess === true;
  const tempDir = mkdtempSync(join(tmpdir(), 'wm-country-deep-dive-'));
  const outfile = join(tempDir, 'CountryDeepDivePanel.bundle.mjs');
  const resilienceWidgetStub = resilienceWidgetMode === 'import-reject'
    ? `
      throw new Error('synthetic resilience widget chunk failure');
      export class ResilienceWidget {}
    `
    : resilienceWidgetMode === 'constructor-throw'
      ? `
        export class ResilienceWidget {
          constructor() {
            throw new Error('synthetic resilience widget constructor failure');
          }
        }
      `
      : resilienceWidgetMode === 'get-element-throw'
        ? `
          const state = globalThis.__wmCountryDeepDiveTestState;
          export class ResilienceWidget {
            constructor(code) {
              this.code = code;
              this.destroyCount = 0;
              this.energyMixData = null;
              state.widgets.push(this);
            }
            setEnergyMix(data) {
              this.energyMixData = data;
            }
            getElement() {
              throw new Error('synthetic resilience widget getElement failure');
            }
            destroy() {
              this.destroyCount += 1;
            }
          }
        `
      : `
        const state = globalThis.__wmCountryDeepDiveTestState;
        export class ResilienceWidget {
          constructor(code) {
            this.code = code;
            this.destroyCount = 0;
            this.energyMixData = null;
            this.element = document.createElement('section');
            this.element.className = 'resilience-widget-stub';
            this.element.setAttribute('data-country-code', code);
            this.element.textContent = 'Resilience ' + code;
            state.widgets.push(this);
          }
          setEnergyMix(data) {
            this.energyMixData = data;
          }
          getElement() {
            return this.element;
          }
          destroy() {
            this.destroyCount += 1;
          }
        }
      `;

  const stubModules = new Map([
    ['feeds-stub', `
      export function getSourcePropagandaRisk() {
        return { stateAffiliated: '' };
      }
      export function getSourceTier() {
        return 2;
      }
    `],
    ['country-geometry-stub', `
      export function getCountryCentroid() {
        return null;
      }
      export const ME_STRIKE_BOUNDS = [];
    `],
    ['i18n-stub', `
      export function t(key, params) {
        if (params && typeof params.count === 'number') {
          return key + ':' + params.count;
        }
        return key;
      }
    `],
    ['related-assets-stub', `
      export function getNearbyInfrastructure() {
        return [];
      }
      export function getCountryInfrastructure() {
        return [];
      }
      export function haversineDistanceKm() {
        return 0;
      }
    `],
    ['sanitize-stub', `
      export function sanitizeUrl(value) { return value ?? ''; }
      export function escapeHtml(value) { return value ?? ''; }
      export function safeHtmlToString(value) { return String(value ?? ''); }
    `],
    ['intel-brief-stub', `export function formatIntelBrief(value) { return value; }`],
    ['export-stub', `
      const state = globalThis.__wmCountryDeepDiveTestState;
      export function exportCountryEvidenceMarkdown(data) {
        state.evidenceExports.push(data);
      }
    `],
    ['utils-stub', `
      export function getCSSColor() { return '#44ff88'; }
      export function showToast(msg) { globalThis.__wmCountryDeepDiveTestState.toasts.push(msg); }
      export function createCircuitBreaker() { return { execute: (fn) => fn() }; }
      export function loadFromStorage() { return null; }
      export function saveToStorage() {}
    `],
    ['country-flag-stub', `export function toFlagEmoji(code, fallback = '🌍') { return code ? ':' + code + ':' : fallback; }`],
    ['ports-stub', `export const PORTS = [];`],
    ['trade-routes-stub', `export function getChokepointRoutes() { return []; } export const TRADE_ROUTES = [];`],
    ['geo-stub', `export const STRATEGIC_WATERWAYS = [];`],
    ['analytics-stub', `export function trackGateHit(feature) { globalThis.__wmCountryDeepDiveTestState.gateHits.push(feature); }`],
    ['chokepoint-registry-stub', `export const CHOKEPOINT_REGISTRY = [];`],
    ['supplier-route-risk-stub', `
      export function computeAlternativeSuppliers(exporters) {
        return exporters.map(e => ({ ...e, risk: { riskLevel: 'safe', transitChokepoints: [], maxDisruptionScore: 0, recommendation: '', routeIds: [], exporterIso2: e.partnerIso2, importerIso2: '' }, safeAlternative: null }));
      }
      export function computeSupplierRouteRisk() {
        return { riskLevel: 'safe', transitChokepoints: [], maxDisruptionScore: 0, recommendation: '', routeIds: [], exporterIso2: '', importerIso2: '' };
      }
    `],
    ['supply-chain-stub', `
      export function fetchBypassOptions() { return Promise.resolve({ corridors: [] }); }
      export function getCountryChokepointIndex() { return null; }
      export function fetchChokepointStatus() { return Promise.resolve({ chokepoints: [], fetchedAt: '', upstreamUnavailable: false }); }
      export function fetchMultiSectorCostShock() { return Promise.resolve({ iso2: '', chokepointId: '', closureDays: 30, warRiskTier: 'WAR_RISK_TIER_UNSPECIFIED', sectors: [], totalAddedCost: 0, fetchedAt: '', unavailableReason: '' }); }
      export const HS2_SHORT_LABELS = { '27': 'Energy', '84': 'Machinery', '85': 'Electronics', '87': 'Vehicles', '30': 'Pharma', '72': 'Iron & Steel', '39': 'Plastics', '29': 'Chemicals', '10': 'Cereals', '62': 'Apparel' };
    `],
    ['runtime-stub', `
      export function toApiUrl(path) { return path; }
      export function isDesktopRuntime() { return false; }
      export function getConfiguredWebApiBaseUrl() { return ''; }
    `],
    ['intelligence-client-stub', `
      export class IntelligenceServiceClient {}
    `],
    ['panel-gating-stub', `
      export function hasPremiumAccess() { return ${premiumAccess ? 'true' : 'false'}; }
      export function getPanelGateReason() { return 'none'; }
    `],
    ['auth-state-stub', `
      export function getAuthState() { return { user: null }; }
    `],
    ['resilience-widget-stub', resilienceWidgetStub],
    ['sentry-defer-stub', `
      const state = globalThis.__wmCountryDeepDiveTestState;
      export function enqueueSentryCall(fn) {
        fn({
          addBreadcrumb(breadcrumb) {
            state.sentryBreadcrumbs.push(breadcrumb);
          },
          captureException(error, context) {
            state.sentryExceptions.push({ error, context });
          },
          captureMessage(message, context) {
            state.sentryMessages.push({ message, context });
          },
          setUser(user) {
            state.sentryUser = user;
          },
        });
      }
    `],
  ]);

  const aliasMap = new Map([
    ['@/config/feeds', 'feeds-stub'],
    ['@/services/country-geometry', 'country-geometry-stub'],
    ['@/services/i18n', 'i18n-stub'],
    ['@/services/related-assets', 'related-assets-stub'],
    ['@/utils/sanitize', 'sanitize-stub'],
    ['@/utils/format-intel-brief', 'intel-brief-stub'],
    ['@/utils/export', 'export-stub'],
    ['@/utils', 'utils-stub'],
    ['@/utils/country-flag', 'country-flag-stub'],
    ['@/config/ports', 'ports-stub'],
    ['@/config/trade-routes', 'trade-routes-stub'],
    ['@/config/geo', 'geo-stub'],
    ['@/services/analytics', 'analytics-stub'],
    ['@/config/chokepoint-registry', 'chokepoint-registry-stub'],
    ['@/utils/supplier-route-risk', 'supplier-route-risk-stub'],
    ['@/services/supply-chain', 'supply-chain-stub'],
    ['./ResilienceWidget', 'resilience-widget-stub'],
    ['@/components/ResilienceWidget', 'resilience-widget-stub'],
    ['@/services/runtime', 'runtime-stub'],
    ['@/generated/client/worldmonitor/intelligence/v1/service_client', 'intelligence-client-stub'],
    ['@/services/panel-gating', 'panel-gating-stub'],
    ['@/services/auth-state', 'auth-state-stub'],
    ['@/bootstrap/sentry-defer', 'sentry-defer-stub'],
  ]);

  const plugin = {
    name: 'country-deep-dive-test-stubs',
    setup(buildApi) {
      buildApi.onResolve({ filter: /.*/ }, (args) => {
        const target = aliasMap.get(args.path);
        return target ? { path: target, namespace: 'stub' } : null;
      });

      buildApi.onLoad({ filter: /.*/, namespace: 'stub' }, (args) => ({
        contents: stubModules.get(args.path),
        loader: 'js',
      }));
    },
  };

  const result = await build({
    entryPoints: [entry],
    bundle: true,
    format: 'esm',
    platform: 'browser',
    target: 'es2020',
    write: false,
    plugins: [plugin],
  });

  writeFileSync(outfile, result.outputFiles[0].text, 'utf8');

  const mod = await import(`${pathToFileURL(outfile).href}?t=${Date.now()}`);
  return {
    CountryDeepDivePanel: mod.CountryDeepDivePanel,
    cleanupBundle() {
      rmSync(tempDir, { recursive: true, force: true });
    },
  };
}

export async function createCountryDeepDivePanelHarness(options = {}) {
  const originalGlobals = {
    document: snapshotGlobal('document'),
    window: snapshotGlobal('window'),
    localStorage: snapshotGlobal('localStorage'),
    requestAnimationFrame: snapshotGlobal('requestAnimationFrame'),
    cancelAnimationFrame: snapshotGlobal('cancelAnimationFrame'),
    navigator: snapshotGlobal('navigator'),
    HTMLElement: snapshotGlobal('HTMLElement'),
    HTMLButtonElement: snapshotGlobal('HTMLButtonElement'),
  };
  const browserEnvironment = createBrowserEnvironment();
  const state = {
    widgets: [],
    sentryBreadcrumbs: [],
    sentryExceptions: [],
    sentryMessages: [],
    sentryUser: undefined,
    evidenceExports: [],
    gateHits: [],
    toasts: [],
  };

  defineGlobal('document', browserEnvironment.document);
  defineGlobal('window', browserEnvironment.window);
  defineGlobal('localStorage', browserEnvironment.localStorage);
  defineGlobal('requestAnimationFrame', browserEnvironment.requestAnimationFrame);
  defineGlobal('cancelAnimationFrame', browserEnvironment.cancelAnimationFrame);
  defineGlobal('navigator', browserEnvironment.window.navigator);
  defineGlobal('HTMLElement', browserEnvironment.HTMLElement);
  defineGlobal('HTMLButtonElement', browserEnvironment.HTMLButtonElement);
  globalThis.__wmCountryDeepDiveTestState = state;

  let CountryDeepDivePanel;
  let cleanupBundle;
  try {
    ({ CountryDeepDivePanel, cleanupBundle } = await loadCountryDeepDivePanel(options));
  } catch (error) {
    delete globalThis.__wmCountryDeepDiveTestState;
    restoreGlobal('document', originalGlobals.document);
    restoreGlobal('window', originalGlobals.window);
    restoreGlobal('localStorage', originalGlobals.localStorage);
    restoreGlobal('requestAnimationFrame', originalGlobals.requestAnimationFrame);
    restoreGlobal('cancelAnimationFrame', originalGlobals.cancelAnimationFrame);
    restoreGlobal('navigator', originalGlobals.navigator);
    restoreGlobal('HTMLElement', originalGlobals.HTMLElement);
    restoreGlobal('HTMLButtonElement', originalGlobals.HTMLButtonElement);
    throw error;
  }

  function createPanel() {
    return new CountryDeepDivePanel(null);
  }

  function getPanelRoot() {
    return browserEnvironment.document.getElementById('country-deep-dive-panel');
  }

  function cleanup() {
    cleanupBundle();
    delete globalThis.__wmCountryDeepDiveTestState;
    restoreGlobal('document', originalGlobals.document);
    restoreGlobal('window', originalGlobals.window);
    restoreGlobal('localStorage', originalGlobals.localStorage);
    restoreGlobal('requestAnimationFrame', originalGlobals.requestAnimationFrame);
    restoreGlobal('cancelAnimationFrame', originalGlobals.cancelAnimationFrame);
    restoreGlobal('navigator', originalGlobals.navigator);
    restoreGlobal('HTMLElement', originalGlobals.HTMLElement);
    restoreGlobal('HTMLButtonElement', originalGlobals.HTMLButtonElement);
  }

  return {
    createPanel,
    document: browserEnvironment.document,
    getPanelRoot,
    getWidgets() {
      return state.widgets;
    },
    getSentryBreadcrumbs() {
      return state.sentryBreadcrumbs;
    },
    getSentryExceptions() {
      return state.sentryExceptions;
    },
    getEvidenceExports() {
      return state.evidenceExports;
    },
    getGateHits() {
      return state.gateHits;
    },
    getToasts() {
      return state.toasts;
    },
    cleanup,
  };
}
