import { spawn } from "child_process";

interface StreamProcess {
	process: ReturnType<typeof spawn> | null;
	rtspUrl: string;
	startedAt: Date;
	clients: Set<string>;
}

const activeStreams = new Map<string, StreamProcess>();

export function startStream(
	streamId: string,
	rtspUrl: string,
): { success: boolean; error?: string } {
	// Kill existing stream if it's running
	if (activeStreams.has(streamId)) {
		stopStream(streamId);
	}

	try {
		const args = [
			"-rtsp_transport",
			"tcp",
			"-i",
			rtspUrl,
			// Scale video to 1920x1080 (Full HD)
			"-vf",
			"scale=1920:1080",
			// Video output - MJPEG format
			"-c:v",
			"mjpeg",
			"-q:v",
			"5",
			"-f",
			"mjpeg",
			"-fflags",
			"nobuffer",
			// Disable audio
			"-an",
			// Output to stdout
			"pipe:1",
		];

		const ffmpegProcess = spawn("ffmpeg", args);

		ffmpegProcess.on("error", (err: Error) => {
			console.error(`[${streamId}] FFmpeg error:`, err);
			activeStreams.delete(streamId);
		});

		ffmpegProcess.on("close", (code: number | null) => {
			activeStreams.delete(streamId);
		});

		activeStreams.set(streamId, {
			process: ffmpegProcess,
			rtspUrl,
			startedAt: new Date(),
			clients: new Set(),
		});

		return {
			success: true,
		};
	} catch (error) {
		console.error(`[${streamId}] Failed to start stream:`, error);
		return {
			success: false,
			error: `Failed to start stream: ${error instanceof Error ? error.message : "Unknown error"}`,
		};
	}
}

export function stopStream(streamId: string): void {
	const stream = activeStreams.get(streamId);
	if (stream && stream.process) {
		stream.process.kill("SIGTERM");
		stream.clients.clear();
		activeStreams.delete(streamId);
	}
}

export function getStreamProcess(streamId: string) {
	return activeStreams.get(streamId);
}

export function addStreamClient(streamId: string, client: string): boolean {
	const stream = activeStreams.get(streamId);
	if (!stream) {
		return false;
	}
	stream.clients.add(client);
	return true;
}

export function removeStreamClient(streamId: string, client: string): void {
	const stream = activeStreams.get(streamId);
	if (stream) {
		stream.clients.delete(client);

		// Auto-stop stream if no clients remain
		if (stream.clients.size === 0) {
			stopStream(streamId);
		}
	}
}

export function getStreamStatus(streamId: string) {
	const stream = activeStreams.get(streamId);
	if (!stream) {
		return null;
	}

	return {
		streamId,
		rtspUrl: stream.rtspUrl,
		startedAt: stream.startedAt,
		isRunning: stream.process !== null,
		clientCount: stream.clients.size,
	};
}

export function getAllStreams() {
	return Array.from(activeStreams.entries()).map(([streamId, stream]) => ({
		streamId,
		rtspUrl: stream.rtspUrl,
		startedAt: stream.startedAt,
		isRunning: stream.process !== null,
		clientCount: stream.clients.size,
	}));
}

export function stopAllStreams(): void {
	activeStreams.forEach((stream, streamId) => {
		stopStream(streamId);
	});
}
