import os from "node:os";
import { printNyanpasu } from "./utils";
import { archCheck } from "./utils/arch-check";
import { SIDECAR_HOST } from "./utils/consts";
import { colorize, consola } from "./utils/logger";
import { Resolve } from "./utils/resolve";

// force download
const FORCE = process.argv.includes("--force");

// cross platform build using
const ARCH = process.argv.includes("--arch")
  ? process.argv[process.argv.indexOf("--arch") + 1]
  : undefined;

// cross platform build support
if (!SIDECAR_HOST) {
  consola.fatal(colorize`{red.bold SIDECAR_HOST} not found`);
  process.exit(1);
} else {
  consola.debug(colorize`sidecar-host {yellow ${SIDECAR_HOST}}`);
}

const platform = process.platform;

const arch = (ARCH ? ARCH : process.arch) as NodeJS.Architecture | "armel";

archCheck(platform, arch);

const resolve = new Resolve({
  platform,
  arch,
  sidecarHost: SIDECAR_HOST!,
  force: FORCE,
});

const tasks: {
  name: string;
  func: () => Promise<void>;
  retry: number;
  winOnly?: boolean;
}[] = [
  { name: "clash", func: () => resolve.clash(), retry: 5 },
  { name: "mihomo", func: () => resolve.clashMeta(), retry: 5 },
  { name: "mihomo-alpha", func: () => resolve.clashMetaAlpha(), retry: 5 },
  { name: "clash-rs", func: () => resolve.clashRust(), retry: 5 },
  { name: "clash-rs-alpha", func: () => resolve.clashRustAlpha(), retry: 5 },
  { name: "wintun", func: () => resolve.wintun(), retry: 5, winOnly: true },
  {
    name: "nyanpasu-service",
    func: () => resolve.service(),
    retry: 5,
  },
  { name: "mmdb", func: () => resolve.mmdb(), retry: 5 },
  { name: "geoip", func: () => resolve.geoip(), retry: 5 },
  { name: "geosite", func: () => resolve.geosite(), retry: 5 },
  {
    name: "enableLoopback",
    func: () => resolve.enableLoopback(),
    retry: 5,
    winOnly: true,
  },
];

async function runTask() {
  const task = tasks.shift();

  if (!task) return;

  if (task.winOnly && process.platform !== "win32") return runTask();

  for (let i = 0; i < task.retry; i++) {
    try {
      await task.func();

      break;
    } catch (err) {
      consola.warn(`task::${task.name} try ${i} ==`, err);

      if (i === task.retry - 1) {
        consola.fatal(`task::${task.name} failed`, err);
        process.exit(1);
      }
    }
  }

  return runTask();
}

consola.start("start check and download resources...");

const jobs = new Array(Math.ceil(os.cpus.length / 2) || 2)
  .fill(0)
  .map(() => runTask());

Promise.all(jobs).then(() => {
  printNyanpasu();

  consola.success("all resources download finished\n");

  const commands = [
    "pnpm dev - development with react dev tools",
    "pnpm dev:diff - deadlock development with react dev tools (recommend)",
    "pnpm tauri:diff - deadlock development",
  ];

  consola.log("  next command:\n");

  commands.forEach((text) => {
    consola.log(`    ${text}`);
  });
});
