import { afterEach, expect, test } from "bun:test";
import {
  MobileUnavailableError,
  invoke,
  isNative,
  platform,
  plugin,
  registerPlugin,
  whenNative,
} from "../src/index.ts";

const root = globalThis as typeof globalThis & { Capacitor?: unknown };
const original = root.Capacitor;

afterEach(() => {
  if (original === undefined) delete root.Capacitor;
  else root.Capacitor = original;
});

test("falls back safely without Capacitor", async () => {
  delete root.Capacitor;
  expect(isNative()).toBe(false);
  expect(platform()).toBe("web");
  expect(plugin("Camera")).toBeUndefined();
  expect(
    await whenNative(
      () => "native",
      () => "browser",
    ),
  ).toBe("browser");
});

test("exposes and invokes injected plugins", async () => {
  root.Capacitor = {
    isNativePlatform: () => true,
    getPlatform: () => "android",
    Plugins: { Haptics: { impact: async (options: unknown) => ({ options, completed: true }) } },
  };
  expect(isNative()).toBe(true);
  expect(platform()).toBe("android");
  expect(plugin("Haptics")).toBeDefined();
  expect(
    await invoke<{ options: { style: string }; completed: boolean }>("Haptics", "impact", {
      style: "MEDIUM",
    }),
  ).toEqual({
    options: { style: "MEDIUM" },
    completed: true,
  });
});

test("registered JavaScript plugin proxies take precedence", async () => {
  root.Capacitor = { isNativePlatform: () => true, Plugins: {} };
  registerPlugin("Device", { getInfo: async () => ({ model: "test" }) });
  expect(await invoke<{ model: string }>("Device", "getInfo")).toEqual({ model: "test" });
});

test("explains missing plugins", async () => {
  root.Capacitor = { isNativePlatform: () => true, Plugins: {} };
  expect(invoke("Camera", "getPhoto")).rejects.toBeInstanceOf(MobileUnavailableError);
});
