#!/usr/bin/env node

const { execSync } = require("node:child_process");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");

const appDir = path.join(__dirname, "..", "app");
const betterSqlitePath = path.join(appDir, "node_modules", "better-sqlite3");
const defaultMitmRouterBaseUrl = "http://localhost:20502";
const portMigrationNoticeName = "port-migration.json";
const legacyMitmRouterBaseUrls = new Set([
  "http://localhost:20128",
  "http://127.0.0.1:20128",
]);

function getDataDir() {
  return process.platform === "win32"
    ? path.join(process.env.APPDATA || os.homedir(), "openrouterx")
    : path.join(os.homedir(), ".openrouterx");
}

function normalizeMitmRouterBaseUrl(value) {
  const raw = String(value || "").trim().replace(/\/+$/, "");
  if (!raw || legacyMitmRouterBaseUrls.has(raw)) return defaultMitmRouterBaseUrl;
  return raw;
}

function refreshJsonSettings(dataDir) {
  const filePath = path.join(dataDir, "db.json");
  if (!fs.existsSync(filePath)) return false;
  try {
    const data = JSON.parse(fs.readFileSync(filePath, "utf8"));
    if (!data || typeof data !== "object") return false;
    if (!data.settings || typeof data.settings !== "object" || Array.isArray(data.settings)) {
      data.settings = {};
    }
    const next = normalizeMitmRouterBaseUrl(data.settings.mitmRouterBaseUrl);
    if (data.settings.mitmRouterBaseUrl === next) return false;
    data.settings.mitmRouterBaseUrl = next;
    fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n");
    return true;
  } catch {
    return false;
  }
}

function refreshSqliteSettings(dataDir) {
  const filePath = path.join(dataDir, "db", "data.sqlite");
  if (!fs.existsSync(filePath)) return false;
  let Database;
  try {
    Database = require(path.join(appDir, "node_modules", "better-sqlite3"));
  } catch {
    try { Database = require("better-sqlite3"); } catch { return false; }
  }

  let db;
  try {
    db = new Database(filePath);
    const table = db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'settings'").get();
    if (!table) return false;
    const row = db.prepare("SELECT id, data FROM settings WHERE id = 1").get();
    if (!row) return false;
    const settings = JSON.parse(row.data || "{}");
    const next = normalizeMitmRouterBaseUrl(settings.mitmRouterBaseUrl);
    if (settings.mitmRouterBaseUrl === next) return false;
    settings.mitmRouterBaseUrl = next;
    db.prepare("UPDATE settings SET data = ? WHERE id = ?").run(JSON.stringify(settings), row.id);
    return true;
  } catch {
    return false;
  } finally {
    try { db?.close(); } catch {}
  }
}

function refreshRuntimePortSettings() {
  const dataDir = getDataDir();
  const changed = [];
  if (refreshJsonSettings(dataDir)) changed.push("db.json");
  if (refreshSqliteSettings(dataDir)) changed.push("data.sqlite");
  if (changed.length > 0) {
    const noticeDir = path.join(dataDir, "notices");
    fs.mkdirSync(noticeDir, { recursive: true });
    fs.writeFileSync(path.join(noticeDir, portMigrationNoticeName), JSON.stringify({
      id: "port-migration-20128-20502",
      type: "port-migration",
      fromPort: 20128,
      toPort: 20502,
      fromBaseUrl: "http://localhost:20128",
      toBaseUrl: defaultMitmRouterBaseUrl,
      stores: changed,
      createdAt: new Date().toISOString(),
    }, null, 2) + "\n");
    console.log("refreshed MITM router port settings: " + changed.join(", ") + " -> " + defaultMitmRouterBaseUrl);
  }
}

refreshRuntimePortSettings();

function isValidBinary() {
  try {
    const Database = require(betterSqlitePath);
    const db = new Database(":memory:");
    db.close();
    return true;
  } catch {
    return false;
  }
}

function getBetterSqliteVersion() {
  try {
    const appPkg = JSON.parse(fs.readFileSync(path.join(appDir, "package.json"), "utf8"));
    return appPkg.optionalDependencies?.["better-sqlite3"]
      || appPkg.dependencies?.["better-sqlite3"]
      || "latest";
  } catch {
    return "latest";
  }
}

if (isValidBinary()) {
  console.log("better-sqlite3 can open a database with this Node runtime, skipping repair");
  process.exit(0);
}

console.log("Repairing better-sqlite3 for current Node runtime...");

try {
  fs.rmSync(betterSqlitePath, { recursive: true, force: true });
  execSync("npm install better-sqlite3@" + getBetterSqliteVersion() + " --save-optional --ignore-scripts=false --force", {
    cwd: appDir,
    stdio: "inherit",
    timeout: 120000,
  });
  if (!isValidBinary()) {
    throw new Error("better-sqlite3 still cannot open a database after repair");
  }
  console.log("better-sqlite3 repaired successfully");
} catch (error) {
  console.warn("Failed to repair better-sqlite3. The app may not work correctly.");
  console.warn("Make sure you have build tools installed (python, make, gcc/node-gyp)");
  console.warn("Error:", error.message);
  process.exit(0);
}
