const CANDIDATE_RELATIVE_PATHS = [
  './x_app_sdk_bundle.js',
  '../x_app_sdk_bundle.js',
  '../node_modules/x-app-sdk/dist/index.es.js',
];

const SDK_CANDIDATE_PATHS = CANDIDATE_RELATIVE_PATHS.map((relative) =>
  new URL(relative, import.meta.url).href,
);

let cachedModulePromise = null;

function ensureSdkShape(module, source) {
  if (!module) {
    throw new Error(`Module from ${source} is undefined`);
  }
  const requiredMethods = ['getToken', 'closeApp'];
  for (const method of requiredMethods) {
    if (typeof module[method] !== 'function') {
      throw new Error(`Module from ${source} is missing required export: ${method}`);
    }
  }
}

async function importWithFallback() {
  let lastError;

  for (const path of SDK_CANDIDATE_PATHS) {
    try {
      const module = await import(path);
      ensureSdkShape(module, path);
      console.log(`✅ x-app-sdk loaded from ${path}`);
      console.log('🔧 SDK methods available:', Object.keys(module));
      try {
        Object.defineProperty(module, '__xAppSdkSource', {
          value: path,
          enumerable: false,
        });
      } catch (_) {}
      if (typeof document !== 'undefined' && document?.dispatchEvent) {
        document.dispatchEvent(
          new CustomEvent('xAppSdkReady', {
            detail: { source: path },
          }),
        );
      }
      return module;
    } catch (error) {
      lastError = error;
      console.warn(`ℹ️ Failed to load x-app-sdk from ${path}`, error);
    }
  }

  const message = 'Unable to locate x-app-sdk module';
  console.error(`❌ ${message}`);
  throw lastError ?? new Error(message);
}

export function resetCachedModule() {
  cachedModulePromise = null;
}

export async function loadXAppSdkModule() {
  if (!cachedModulePromise) {
    cachedModulePromise = importWithFallback();
  }
  return cachedModulePromise;
}

export async function bootstrapXAppSdk() {
  const module = await loadXAppSdkModule();
  return module;
}

async function getToken() {
  const module = await loadXAppSdkModule();
  return module.getToken();
}

async function closeApp(payload) {
  const module = await loadXAppSdkModule();
  return module.closeApp(payload);
}

const loaderApi = {
  loadXAppSdkModule,
  bootstrapXAppSdk,
  resetCachedModule,
  getToken,
  closeApp,
};

if (!globalThis.__xAppSdkLoader) {
  Object.defineProperty(globalThis, '__xAppSdkLoader', {
    value: loaderApi,
    writable: false,
    configurable: false,
  });
} else {
  Object.assign(globalThis.__xAppSdkLoader, loaderApi);
}
