/**
 * Auto-updater: checks GitHub Releases API for newer versions.
 *
 * Electrobun doesn't have a built-in updater mechanism yet, so this module
 * only detects available updates and returns metadata — no download/install.
 */

import { settingsDb } from "./settings-db.ts";

// ── Config ──────────────────────────────────────────────────────────────────

const GITHUB_OWNER = "DexterFromLab";
const GITHUB_REPO = "agents-orchestrator";
const RELEASES_URL = `https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPO}/releases/latest`;

/** Minimum interval between automatic checks (1 hour). */
const MIN_CHECK_INTERVAL_MS = 60 * 60 * 1000;

const SETTINGS_KEY_LAST_CHECK = "updater_last_check";
const SETTINGS_KEY_LAST_VERSION = "updater_last_version";

// ── Types ───────────────────────────────────────────────────────────────────

export interface UpdateCheckResult {
  available: boolean;
  version: string;
  downloadUrl: string;
  releaseNotes: string;
  checkedAt: number;
}

interface GitHubRelease {
  tag_name: string;
  html_url: string;
  body: string | null;
  assets: Array<{
    name: string;
    browser_download_url: string;
  }>;
}

// ── Semver comparison ───────────────────────────────────────────────────────

function parseSemver(v: string): [number, number, number] {
  const clean = v.replace(/^v/, "");
  const parts = clean.split("-")[0].split(".");
  return [
    parseInt(parts[0] ?? "0", 10),
    parseInt(parts[1] ?? "0", 10),
    parseInt(parts[2] ?? "0", 10),
  ];
}

function isNewer(remote: string, local: string): boolean {
  const [rMaj, rMin, rPatch] = parseSemver(remote);
  const [lMaj, lMin, lPatch] = parseSemver(local);

  if (rMaj !== lMaj) return rMaj > lMaj;
  if (rMin !== lMin) return rMin > lMin;
  return rPatch > lPatch;
}

// ── Core ────────────────────────────────────────────────────────────────────

/**
 * Check GitHub Releases API for a newer version.
 * Returns update metadata (never downloads or installs anything).
 */
export async function checkForUpdates(
  currentVersion: string,
): Promise<UpdateCheckResult> {
  const now = Date.now();

  const resp = await fetch(RELEASES_URL, {
    headers: {
      Accept: "application/vnd.github.v3+json",
      "User-Agent": "AgentOrchestrator-Updater",
    },
    signal: AbortSignal.timeout(10_000),
  });

  if (!resp.ok) {
    throw new Error(`GitHub API returned ${resp.status}: ${resp.statusText}`);
  }

  const release: GitHubRelease = await resp.json();
  const remoteVersion = release.tag_name.replace(/^v/, "");

  // Find a .deb or .AppImage asset as download URL, fallback to release page
  const linuxAsset = release.assets.find(
    (a) => a.name.endsWith(".deb") || a.name.endsWith(".AppImage"),
  );
  const downloadUrl = linuxAsset?.browser_download_url ?? release.html_url;

  // Persist check timestamp
  settingsDb.setSetting(SETTINGS_KEY_LAST_CHECK, String(now));
  settingsDb.setSetting(SETTINGS_KEY_LAST_VERSION, remoteVersion);

  return {
    available: isNewer(remoteVersion, currentVersion),
    version: remoteVersion,
    downloadUrl,
    releaseNotes: release.body ?? "",
    checkedAt: now,
  };
}

/** Return the timestamp of the last update check (0 if never). */
export function getLastCheckTimestamp(): number {
  const val = settingsDb.getSetting(SETTINGS_KEY_LAST_CHECK);
  return val ? parseInt(val, 10) || 0 : 0;
}

