/**
 * IPFS Client — Server-side pinning and gateway access via Kubo API.
 *
 * No encryption here — backups are already encrypted by the client,
 * and generated files are intentionally public.
 */

const IPFS_API_URL = process.env.IPFS_API_URL || "http://collab-server-ipfs-1:5001";
const IPFS_GATEWAY_URL =
	process.env.IPFS_GATEWAY_URL || "https://ipfs.jeffemmett.com";

/** Returns true if IPFS_API_URL is configured (always true with default). */
export function isIPFSEnabled(): boolean {
	return !!IPFS_API_URL;
}

/** Public gateway URL for a CID. */
export function ipfsGatewayUrl(cid: string): string {
	return `${IPFS_GATEWAY_URL}/ipfs/${cid}`;
}

/**
 * Pin a blob to IPFS via Kubo's /api/v0/add endpoint.
 * Returns the CID (content hash).
 */
export async function pinToIPFS(
	data: Uint8Array,
	filename: string,
): Promise<string> {
	const formData = new FormData();
	formData.append(
		"file",
		new Blob([data.buffer as ArrayBuffer]),
		filename,
	);

	const res = await fetch(`${IPFS_API_URL}/api/v0/add?pin=true`, {
		method: "POST",
		body: formData,
	});

	if (!res.ok) {
		const err = await res.text();
		throw new Error(`IPFS pin failed (${res.status}): ${err}`);
	}

	const result = (await res.json()) as { Hash: string; Size: string };
	return result.Hash;
}

/**
 * Unpin a CID from the local Kubo node.
 */
export async function unpinFromIPFS(cid: string): Promise<void> {
	const res = await fetch(
		`${IPFS_API_URL}/api/v0/pin/rm?arg=${encodeURIComponent(cid)}`,
		{ method: "POST" },
	);
	// 500 with "not pinned" is fine — idempotent unpin
	if (!res.ok) {
		const err = await res.text();
		if (!err.includes("not pinned")) {
			throw new Error(`IPFS unpin failed (${res.status}): ${err}`);
		}
	}
}

/**
 * Fetch content from IPFS by CID (via gateway).
 */
export async function fetchFromIPFS(cid: string): Promise<Response> {
	return fetch(`${IPFS_GATEWAY_URL}/ipfs/${cid}`);
}

/**
 * Get IPFS node status — peer ID, repo size, number of objects.
 */
export async function getIPFSStatus(): Promise<{
	peerId: string;
	repoSize: number;
	numObjects: number;
}> {
	const [idRes, statRes] = await Promise.all([
		fetch(`${IPFS_API_URL}/api/v0/id`, { method: "POST" }),
		fetch(`${IPFS_API_URL}/api/v0/repo/stat`, { method: "POST" }),
	]);

	if (!idRes.ok) throw new Error(`IPFS id failed: ${idRes.status}`);
	if (!statRes.ok) throw new Error(`IPFS repo/stat failed: ${statRes.status}`);

	const id = (await idRes.json()) as { ID: string };
	const stat = (await statRes.json()) as {
		RepoSize: number;
		NumObjects: number;
	};

	return {
		peerId: id.ID,
		repoSize: stat.RepoSize,
		numObjects: stat.NumObjects,
	};
}
