import {
  afterEach,
  beforeEach,
  describe,
  expect,
  it,
  vi
} from 'vitest';

const capacitorState = vi.hoisted(() => ({
  isNativePlatform: true,
  isPluginAvailable: true,
  platform: 'android'
}));
const appPlugin = vi.hoisted(() => ({
  addListener: vi.fn(() => Promise.resolve({ remove: vi.fn() }))
}));
const localNotificationsPlugin = vi.hoisted(() => ({
  checkPermissions: vi.fn(() => Promise.resolve({ display: 'granted' }))
}));

vi.mock('@capacitor/core', () => ({
  Capacitor: {
    isNativePlatform: () => capacitorState.isNativePlatform,
    isPluginAvailable: (name: string) => capacitorState.isPluginAvailable && name.length > 0,
    getPlatform: () => capacitorState.platform
  }
}));

vi.mock('@capacitor/app', () => ({
  App: appPlugin
}));

vi.mock('@capacitor/local-notifications', () => ({
  LocalNotifications: localNotificationsPlugin
}));

import { loadCapacitorAppPlugin, loadCapacitorLocalNotificationsPlugin } from './capacitor-plugin-loader';

function stubCapacitorWindow(): void {
  vi.stubGlobal('window', {
    Capacitor: {
      isNativePlatform: () => capacitorState.isNativePlatform
    }
  });
}

describe('capacitor-plugin-loader', () => {
  beforeEach(() => {
    stubCapacitorWindow();
  });

  afterEach(() => {
    capacitorState.isNativePlatform = true;
    capacitorState.isPluginAvailable = true;
    capacitorState.platform = 'android';
    vi.unstubAllGlobals();
  });

  it('returns registered plugin instances from dynamic imports on native shells', async () => {
    const resolvedAppPlugin = await loadCapacitorAppPlugin();
    const resolvedNotificationsPlugin = await loadCapacitorLocalNotificationsPlugin();

    expect(resolvedAppPlugin).toBe(appPlugin);
    expect(resolvedNotificationsPlugin).toBe(localNotificationsPlugin);
    expect(resolvedAppPlugin).not.toBeInstanceOf(Promise);
    expect(resolvedNotificationsPlugin).not.toBeInstanceOf(Promise);
  });

  it('returns null when the plugin is unavailable on the active native shell', async () => {
    capacitorState.isPluginAvailable = false;

    expect(await loadCapacitorAppPlugin()).toBeNull();
    expect(await loadCapacitorLocalNotificationsPlugin()).toBeNull();
  });

  it('returns null on non-native shells without importing Capacitor plugins', async () => {
    capacitorState.isNativePlatform = false;
    stubCapacitorWindow();

    expect(await loadCapacitorAppPlugin()).toBeNull();
    expect(await loadCapacitorLocalNotificationsPlugin()).toBeNull();
  });
});
