import { getSoulseekBrowseDownload } from 'officerdb';
import { authHeaders, getSlskdConfig } from './upstream';

// Enqueueing downloads out of a cached share tree.
//
// slskd's own enqueue endpoint takes a flat list of {filename, size}, which is fine for search results —
// they arrive as individual files with full paths. A browsed folder is neither: it's a path, and what the
// user means by clicking it is "everything under here". Expanding that into a file list needs the cache,
// so it happens HERE rather than in the browser, which would otherwise have to walk the tree one level
// request at a time and reconstruct paths it only half knows.

/**
 * A folder can be enormous — the root of one measured peer is 284,166 files. Enqueueing that would be a
 * misclick that takes the slskd instance down with it, so it's refused with the count rather than
 * truncated to a silent partial download.
 */
export const MAX_ENQUEUE = 10_000;

export class DownloadError extends Error {
  constructor(
    message: string,
    readonly status: number,
  ) {
    super(message);
  }
}

type EnqueueParams = { userId: number; username: string; path: string; file?: string };

/** Queue one file, or every file beneath one folder, from the cached tree. Returns how many were sent. */
export async function enqueueFromCache({ userId, username, path, file }: EnqueueParams): Promise<number> {
  const cfg = await getSlskdConfig(userId);
  if (!cfg) throw new DownloadError('slskd upstream not configured', 503);

  const files = await getSoulseekBrowseDownload({ userId, username, path, file });
  if (!files.length) throw new DownloadError('nothing to download at that path', 404);
  if (files.length > MAX_ENQUEUE) {
    throw new DownloadError(
      `${files.length.toLocaleString()} files is over the ${MAX_ENQUEUE.toLocaleString()} limit`,
      413,
    );
  }

  const res = await fetch(`${cfg.base}/api/v0/transfers/downloads/${encodeURIComponent(username)}`, {
    method: 'POST',
    headers: { 'content-type': 'application/json', ...authHeaders(cfg) },
    body: JSON.stringify(files),
  });
  if (!res.ok) {
    const detail = (await res.text().catch(() => '')).slice(0, 200);
    throw new DownloadError(`slskd returned ${res.status}${detail ? `: ${detail}` : ''}`, 502);
  }

  console.log(`[slskd] queued ${files.length} file(s) from ${username}: ${file ?? path}`);
  return files.length;
}
