#!/usr/bin/env node
/**
 * Scaffold a suite app from the UltiMail pilot template.
 *
 * Usage:
 *   node scripts/new-app.mjs <crate> <ProductName> <identifier> <suiteApp> <startRoute> <scheme>
 *   node scripts/new-app.mjs --all      # (re)generate every sibling app
 *
 * Each app is a Tauri 2 project under apps/<dir>/src-tauri that loads the same
 * shared static export at its own start route, with its own URL scheme + icons.
 */
import { mkdirSync, writeFileSync, copyFileSync, existsSync, readdirSync } from "node:fs"
import { dirname, join } from "node:path"
import { fileURLToPath } from "node:url"

const __dirname = dirname(fileURLToPath(import.meta.url))
const ROOT = join(__dirname, "..")

/** dir is the folder under apps/; crate is the Rust crate name. */
// Schemes follow the `ulti<suite>` convention from lib/platform.ts (appScheme)
// so inter-app deep links resolve consistently.
const APPS = [
  { dir: "ultimail", crate: "ultimail", product: "UltiMail", id: "space.ulti.mail", suite: "mail", route: "/mail/", scheme: "ultimail", linkPrefix: "/app/mail" },
  { dir: "ultidrive", crate: "ultidrive", product: "UltiDrive", id: "space.ulti.drive", suite: "drive", route: "/drive/", scheme: "ultidrive", linkPrefix: "/app/drive" },
  { dir: "ulticalmeet", crate: "ulticalmeet", product: "UltiCal", id: "space.ulti.cal", suite: "agenda", route: "/agenda/", scheme: "ultiagenda", linkPrefix: "/app/agenda" },
  { dir: "ultiai", crate: "ultiai", product: "UltiAI", id: "space.ulti.ai", suite: "chat", route: "/chat/", scheme: "ultichat", linkPrefix: "/app/chat" },
  { dir: "contacts", crate: "ulticontacts", product: "Contacts", id: "space.ulti.contacts", suite: "contacts", route: "/contacts/", scheme: "ulticontacts", linkPrefix: "/app/contacts" },
]

function cargoToml(a) {
  return `[package]
name = "${a.crate}"
version.workspace = true
edition.workspace = true
license.workspace = true
authors.workspace = true
description = "${a.product} — native shell (Tauri 2)"

[lib]
name = "${a.crate}_lib"
crate-type = ["staticlib", "cdylib", "rlib"]

[build-dependencies]
tauri-build = { workspace = true }

[dependencies]
tauri = { workspace = true }
tauri-plugin-deep-link = { workspace = true }
tauri-plugin-notification = { workspace = true }
tauri-plugin-opener = { workspace = true }
ulti-core = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
log = { workspace = true }

[features]
default = []
`
}

function buildRs() {
  return `fn main() {
    tauri_build::build()
}
`
}

function mainRs(a) {
  return `// Prevents an extra console window on Windows in release.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

fn main() {
    ${a.crate}_lib::run()
}
`
}

function libRs(a) {
  return `//! ${a.product} native shell. Loads the shared static export at \`${a.route}\`
//! and wires the suite's native capabilities through \`ulti-core\` + plugins.

use tauri::Emitter;

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_deep_link::init())
        .plugin(tauri_plugin_notification::init())
        .plugin(tauri_plugin_opener::init())
        .plugin(ulti_core::init())
        .setup(|app| {
            #[cfg(any(target_os = "android", target_os = "ios", desktop))]
            {
                use tauri_plugin_deep_link::DeepLinkExt;
                let handle = app.handle().clone();
                app.deep_link().on_open_url(move |event| {
                    let urls: Vec<String> =
                        event.urls().iter().map(|u| u.to_string()).collect();
                    let _ = handle.emit("ulti://deep-link", urls);
                });
            }
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running ${a.product}");
}
`
}

function tauriConf(a) {
  return JSON.stringify(
    {
      $schema: "https://schema.tauri.app/config/2",
      productName: a.product,
      version: "0.1.0",
      identifier: a.id,
      build: {
        frontendDist: "../../../../out",
        devUrl: "http://localhost:3005",
        beforeDevCommand: `bash "$ULTI_REPO_ROOT/mobile/scripts/dev-mobile-tauri.sh" ${a.suite}`,
        beforeBuildCommand: `bash "$ULTI_REPO_ROOT/mobile/scripts/build-mobile.sh" ${a.suite}`,
      },
      app: {
        windows: [
          { label: "main", title: a.product, url: a.route, width: 420, height: 900 },
        ],
        security: { csp: null },
      },
      bundle: {
        active: true,
        targets: "all",
        category: "Productivity",
        icon: ["icons/icon.png"],
      },
      plugins: {
        "deep-link": {
          mobile: [{ host: "space.ulti.app", pathPrefix: [a.linkPrefix] }],
          desktop: { schemes: [a.scheme] },
        },
      },
    },
    null,
    2
  ) + "\n"
}

function capabilities() {
  return JSON.stringify(
    {
      $schema: "../gen/schemas/desktop-schema.json",
      identifier: "default",
      description: "Default capabilities for the suite shell.",
      windows: ["main"],
      permissions: [
        "core:default",
        "core:window:default",
        "core:event:default",
        "core:webview:default",
        "deep-link:default",
        "notification:default",
        "opener:default",
        "opener:allow-open-url",
        "ulti-core:default",
      ],
    },
    null,
    2
  ) + "\n"
}

function write(path, contents) {
  mkdirSync(dirname(path), { recursive: true })
  writeFileSync(path, contents)
}

function generate(a, { force = false } = {}) {
  const base = join(ROOT, "apps", a.dir, "src-tauri")
  if (a.dir === "ultimail" && !force) {
    console.log("skip ultimail (pilot template — use --force to overwrite)")
    return
  }
  write(join(base, "Cargo.toml"), cargoToml(a))
  write(join(base, "build.rs"), buildRs())
  write(join(base, "src", "main.rs"), mainRs(a))
  write(join(base, "src", "lib.rs"), libRs(a))
  write(join(base, "tauri.conf.json"), tauriConf(a))
  write(join(base, "capabilities", "default.json"), capabilities())

  // Icons: copy from the pilot if present.
  const pilotIcons = join(ROOT, "apps", "ultimail", "src-tauri", "icons")
  const iconsDir = join(base, "icons")
  mkdirSync(iconsDir, { recursive: true })
  if (existsSync(pilotIcons)) {
    for (const f of readdirSync(pilotIcons)) {
      copyFileSync(join(pilotIcons, f), join(iconsDir, f))
    }
  }
  console.log(`generated ${a.dir} (${a.product})`)
}

const arg = process.argv[2]
if (arg === "--all") {
  for (const a of APPS) generate(a)
} else if (arg) {
  const [crate, product, id, suite, route, scheme] = process.argv.slice(2)
  generate({
    dir: crate,
    crate,
    product,
    id,
    suite,
    route,
    scheme,
    linkPrefix: `/app/${suite}`,
  }, { force: true })
} else {
  console.error("usage: new-app.mjs --all | <crate> <Product> <id> <suite> <route> <scheme>")
  process.exit(1)
}
