#!/usr/bin/env node
import {
  getConfigDir
} from "./chunk-AWATD46W.js";

// src/registry.ts
import fs from "fs";
import path from "path";
var REGISTRY_URL = "https://codevator.dev/sounds.json";
var FETCH_TIMEOUT_MS = 15e3;
function fetchWithTimeout(url) {
  const controller = new AbortController();
  const id = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
  return fetch(url, { signal: controller.signal }).finally(() => clearTimeout(id));
}
function isValidManifest(m) {
  return typeof m === "object" && m !== null && typeof m.baseUrl === "string" && m.baseUrl.length > 0 && Array.isArray(m.sounds);
}
function getSoundsDir() {
  return path.join(getConfigDir(), "sounds");
}
function getManifestCache() {
  return path.join(getConfigDir(), "sounds.json");
}
async function fetchManifest() {
  try {
    const res = await fetchWithTimeout(REGISTRY_URL);
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const raw = await res.json();
    if (!isValidManifest(raw)) throw new Error("Invalid manifest format");
    const manifest = raw;
    const dir = getConfigDir();
    fs.mkdirSync(dir, { recursive: true });
    fs.writeFileSync(getManifestCache(), JSON.stringify(manifest, null, 2));
    return manifest;
  } catch {
    try {
      const cached = JSON.parse(fs.readFileSync(getManifestCache(), "utf-8"));
      if (!isValidManifest(cached)) throw new Error("Invalid cached manifest");
      return cached;
    } catch {
      throw new Error("Could not fetch sound registry and no local cache found");
    }
  }
}
function getCachedManifest() {
  try {
    const raw = JSON.parse(fs.readFileSync(getManifestCache(), "utf-8"));
    return isValidManifest(raw) ? raw : null;
  } catch {
    return null;
  }
}
async function downloadFile(baseUrl, filename, soundsDir) {
  const dest = path.join(soundsDir, `${filename}.mp3`);
  if (!dest.startsWith(soundsDir + path.sep)) throw new Error("Invalid sound name");
  if (fs.existsSync(dest)) return dest;
  const url = `${baseUrl}/${filename}.mp3`;
  const res = await fetchWithTimeout(url);
  if (!res.ok) throw new Error(`Failed to download: HTTP ${res.status}`);
  fs.writeFileSync(dest, Buffer.from(await res.arrayBuffer()));
  return dest;
}
async function downloadSound(name, manifest) {
  const m = manifest ?? await fetchManifest();
  const entry = m.sounds.find((s) => s.name === name);
  if (!entry) throw new Error(`Sound '${name}' not found in registry`);
  const soundsDir = getSoundsDir();
  fs.mkdirSync(soundsDir, { recursive: true });
  const dest = await downloadFile(m.baseUrl, name, soundsDir);
  const fileCount = entry.files ?? 1;
  if (fileCount > 1) {
    await Promise.all(
      Array.from(
        { length: fileCount - 1 },
        (_, i) => downloadFile(m.baseUrl, `${name}-${i + 2}`, soundsDir).catch(() => {
        })
      )
    );
  }
  return dest;
}
function isInstalled(name) {
  const soundsDir = getSoundsDir();
  const filePath = path.join(soundsDir, `${name}.mp3`);
  if (!filePath.startsWith(soundsDir + path.sep)) return false;
  return fs.existsSync(filePath);
}
var SOUND_EXTENSIONS = [".mp3", ".wav", ".ogg", ".m4a"];
function listInstalled() {
  const dir = getSoundsDir();
  try {
    const names = /* @__PURE__ */ new Set();
    for (const f of fs.readdirSync(dir)) {
      const ext = path.extname(f);
      if (!SOUND_EXTENSIONS.includes(ext)) continue;
      const base = f.slice(0, -ext.length);
      if (/^.+-\d+$/.test(base)) continue;
      names.add(base);
    }
    return [...names];
  } catch {
    return [];
  }
}

export {
  fetchManifest,
  getCachedManifest,
  downloadSound,
  isInstalled,
  listInstalled
};
