import { existsSync, readFileSync } from "node:fs";
import { join, resolve } from "node:path";
import { runMobileCommand } from "./mobile-command.ts";

interface CapabilityPackage {
  browser: string;
  capacitor?: string;
  expo?: string;
}

export const nativeCatalog: Record<string, CapabilityPackage> = {
  camera: {
    browser: "MediaDevices / file input",
    capacitor: "@capacitor/camera",
    expo: "expo-camera",
  },
  clipboard: {
    browser: "Clipboard API",
    capacitor: "@capacitor/clipboard",
    expo: "expo-clipboard",
  },
  device: {
    browser: "Browser device information",
    capacitor: "@capacitor/device",
    expo: "expo-device",
  },
  filesystem: {
    browser: "File System Access API",
    capacitor: "@capacitor/filesystem",
    expo: "expo-file-system",
  },
  geolocation: {
    browser: "Geolocation API",
    capacitor: "@capacitor/geolocation",
    expo: "expo-location",
  },
  haptics: { browser: "Vibration API", capacitor: "@capacitor/haptics", expo: "expo-haptics" },
  network: {
    browser: "Navigator online status",
    capacitor: "@capacitor/network",
    expo: "expo-network",
  },
  notifications: {
    browser: "Notifications API",
    capacitor: "@capacitor/local-notifications",
    expo: "expo-notifications",
  },
  share: { browser: "Web Share API", capacitor: "@capacitor/share" },
  storage: {
    browser: "Web Storage",
    capacitor: "@capacitor/preferences",
    expo: "expo-secure-store",
  },
};

function mode(root: string): "webview" | "native" {
  const file = join(root, "mobile", "package.json");
  if (!existsSync(file))
    throw new Error("No mobile project found. Run `wrnexus generate mobile` first.");
  return (
    (JSON.parse(readFileSync(file, "utf8")) as { wrnexus?: { mode?: "webview" | "native" } })
      .wrnexus?.mode ?? "webview"
  );
}

export async function runNativeCommand(
  appRoot: string,
  subcommand?: string,
  args: string[] = [],
): Promise<void> {
  if (subcommand === "list" || !subcommand) {
    console.log("WrNexus native capabilities:\n");
    for (const [name, entry] of Object.entries(nativeCatalog)) {
      console.log(
        `  ${name.padEnd(14)} browser: ${entry.browser}; Capacitor: ${entry.capacitor ?? "built in"}; Expo: ${entry.expo ?? "built in"}`,
      );
    }
    return;
  }
  if (subcommand === "add") {
    const names = args.filter((arg) => !arg.startsWith("--"));
    if (!names.length) throw new Error("Usage: wrnexus native add <capability...>");
    const unknown = names.filter((name) => !nativeCatalog[name]);
    if (unknown.length)
      throw new Error(
        `Unknown native capability: ${unknown.join(", ")}. Run \`wrnexus native list\`.`,
      );
    const root = resolve(appRoot);
    const target = mode(root);
    const packages = names
      .map((name) => nativeCatalog[name]![target === "native" ? "expo" : "capacitor"])
      .filter((value): value is string => !!value);
    if (!packages.length) {
      console.log(`  ✓ ${names.join(", ")} use built-in APIs; no package installation required`);
      return;
    }
    await runMobileCommand(root, "add", packages);
    return;
  }
  throw new Error("Usage: wrnexus native <list|add <capability...>>");
}
