import { isCapacitorNativeRuntime } from '../../logic/platform-detection.rules';

type CapacitorCoreModule = typeof import('@capacitor/core');

let capacitorCoreModulePromise: Promise<CapacitorCoreModule> | null = null;

const pluginPromises = new Map<string, Promise<unknown>>();

async function loadCapacitorCore(): Promise<CapacitorCoreModule['Capacitor'] | null> {
  if (typeof window === 'undefined' || !isCapacitorNativeRuntime()) {
    return null;
  }

  if (!capacitorCoreModulePromise) {
    capacitorCoreModulePromise = import('@capacitor/core');
  }

  const module = await capacitorCoreModulePromise;

  return module.Capacitor;
}

async function resolveCapacitorPlugin<T>(
  pluginName: string,
  loader: () => Promise<T>
): Promise<T | null> {
  const Capacitor = await loadCapacitorCore();

  if (!Capacitor) {
    return null;
  }

  if (!Capacitor.isPluginAvailable(pluginName)) {
    console.warn(`[mobile] Capacitor plugin "${pluginName}" is not implemented on ${Capacitor.getPlatform()}`);
    return null;
  }

  if (!pluginPromises.has(pluginName)) {
    pluginPromises.set(pluginName, loader());
  }

  return pluginPromises.get(pluginName) as Promise<T>;
}

/** Resolve the active Capacitor platform id on native shells. */
export async function getCapacitorPlatform(): Promise<string | null> {
  const Capacitor = await loadCapacitorCore();

  return Capacitor?.getPlatform() ?? null;
}

/** Resolve the Capacitor App plugin on native shells; returns null on web/electron or when unavailable. */
export async function loadCapacitorAppPlugin(): Promise<import('@capacitor/app').AppPlugin | null> {
  return resolveCapacitorPlugin('App', async () => {
    const module = await import('@capacitor/app');

    return module.App;
  });
}

/** Resolve the Capacitor LocalNotifications plugin on native shells. */
export async function loadCapacitorLocalNotificationsPlugin(): Promise<import('@capacitor/local-notifications').LocalNotificationsPlugin | null> {
  return resolveCapacitorPlugin('LocalNotifications', async () => {
    const module = await import('@capacitor/local-notifications');

    return module.LocalNotifications;
  });
}

/** Resolve the Capacitor PushNotifications plugin on native shells. */
export async function loadCapacitorPushNotificationsPlugin(): Promise<import('@capacitor/push-notifications').PushNotificationsPlugin | null> {
  return resolveCapacitorPlugin('PushNotifications', async () => {
    const module = await import('@capacitor/push-notifications');

    return module.PushNotifications;
  });
}

/** Resolve the Capacitor Device plugin on native shells. */
export async function loadCapacitorDevicePlugin(): Promise<import('@capacitor/device').DevicePlugin | null> {
  return resolveCapacitorPlugin('Device', async () => {
    const module = await import('@capacitor/device');

    return module.Device;
  });
}

/** Resolve the Capacitor AudioSession plugin on native shells. */
export async function loadCapacitorAudioSessionPlugin(): Promise<import('@capgo/capacitor-audio-session').AudioSessionPlugin | null> {
  return resolveCapacitorPlugin('AudioSession', async () => {
    const module = await import('@capgo/capacitor-audio-session');

    return module.AudioSession;
  });
}

/** Resolve the Capacitor App Update plugin on native shells. */
export async function loadCapacitorAppUpdatePlugin(): Promise<import('@capawesome/capacitor-app-update').AppUpdatePlugin | null> {
  return resolveCapacitorPlugin('AppUpdate', async () => {
    const module = await import('@capawesome/capacitor-app-update');

    return module.AppUpdate;
  });
}
