#!/usr/bin/env node
// Generates latest.json for the Tauri updater from a GitHub release.
// Reads .sig files uploaded by tauri-action, assembles the manifest, writes latest.json.
//
// macOS-only for now — Windows + Linux are added once their signing pipelines
// (Certum cert for Windows, native package managers for Linux) are wired up.
//
// Required env vars: VERSION, GITHUB_TOKEN
// Usage: node scripts/generate-update-manifest.js

const { execSync } = require('child_process');
const fs = require('fs');

const VERSION = process.env.VERSION;
const REPO = 'Psychotoxical/psysonic';
const TAG = `app-v${VERSION}`;

if (!VERSION) {
  console.error('VERSION env var required');
  process.exit(1);
}

// Platform → update bundle filename (produced by tauri-action with updater plugin)
const PLATFORM_FILES = {
  'darwin-aarch64': 'Psysonic_aarch64.app.tar.gz',
  'darwin-x86_64':  'Psysonic_x64.app.tar.gz',
};

const platforms = {};

// A real minisign .sig file is multi-line and ~200+ chars.
// A public key (RWTxxx... single line, ~56 chars) must never appear here.
function validateSignature(sig, platform, sigFile) {
  if (/^RWT[A-Za-z0-9+/]{10,}={0,2}$/.test(sig)) {
    throw new Error(
      `${platform}: .sig file "${sigFile}" contains a PUBLIC KEY instead of a signature.\n` +
      `  Got: ${sig}\n` +
      `  TAURI_SIGNING_PRIVATE_KEY must be the private key, not the public one.`
    );
  }
  if (sig.length < 80) {
    throw new Error(
      `${platform}: .sig file "${sigFile}" looks too short (${sig.length} chars) to be a valid signature.`
    );
  }
}

for (const [platform, filename] of Object.entries(PLATFORM_FILES)) {
  const sigFile = `${filename}.sig`;
  try {
    execSync(
      `gh release download "${TAG}" --repo "${REPO}" -p "${sigFile}" --clobber`,
      { stdio: 'pipe' }
    );
    const signature = fs.readFileSync(sigFile, 'utf8').trim();
    validateSignature(signature, platform, sigFile);
    const url = `https://github.com/${REPO}/releases/download/${TAG}/${filename}`;
    platforms[platform] = { signature, url };
    console.log(`✓ ${platform}`);
  } catch (e) {
    console.warn(`⚠ Skipping ${platform}: ${e.message}`);
  }
}

if (Object.keys(platforms).length === 0) {
  console.error('No platforms found — aborting manifest generation');
  process.exit(1);
}

let notes = '';
try {
  const raw = execSync(
    `gh release view "${TAG}" --repo "${REPO}" --json body`,
    { stdio: 'pipe' }
  ).toString();
  notes = JSON.parse(raw).body ?? '';
} catch {
  console.warn('Could not fetch release notes');
}

const manifest = {
  version: VERSION,
  notes,
  pub_date: new Date().toISOString(),
  platforms,
};

fs.writeFileSync('latest.json', JSON.stringify(manifest, null, 2));
console.log(`\nWrote latest.json for v${VERSION} with platforms: ${Object.keys(platforms).join(', ')}`);
