import { PrismaClient } from "@prisma/client";
import express from "express";
import fs from "node:fs";
import { env } from "node:process";
import axios from "axios";
import { GithubClient } from "./github.js";
import { AppManager, DeployResponse } from "./app_manager.js";
import { z } from "zod";
import { ProjectMonitor, WorkerSchema, LogItem } from "./project_monitor.js";
import tmp from "tmp";
import { NodeJSAnalyzer } from "./lib/nodejs.js";
import shell from "shelljs";
import { RealFileSystem } from "./lib/fs.js";
import path from "node:path";
import {
	Env,
	generateDodoConfig,
	ConfigSchema,
	Config,
	ConfigWithInput,
	configToGraph,
	Network,
	GithubRepository,
	Graph,
} from "config";
import { Instant, DateTimeFormatter, ZoneId } from "@js-joda/core";
import LogStore from "./log.js";
import { GraphOrConfigSchema, GraphSchema, GraphConfigOrDraft, AgentAccess } from "config/dist/graph.js";
import { MachineManager } from "./machine_manager.js";

async function generateKey(root: string): Promise<[string, string]> {
	const privKeyPath = path.join(root, "key");
	const pubKeyPath = path.join(root, "key.pub");
	if (shell.exec(`ssh-keygen -t ed25519 -f ${privKeyPath} -N ""`).code !== 0) {
		throw new Error("Failed to generate SSH key pair");
	}
	const publicKey = await fs.promises.readFile(pubKeyPath, "utf8");
	const privateKey = await fs.promises.readFile(privKeyPath, "utf8");
	return [publicKey, privateKey];
}

const db = new PrismaClient();
const logStore = new LogStore(db);
const appManager = new AppManager();
const machineManager = new MachineManager(env.VPN_API_ADDR!);

const projectMonitors = new Map<number, ProjectMonitor>();

function parseGraph(data: string | null | undefined) {
	if (data == null) {
		return null;
	}
	return GraphSchema.safeParse(JSON.parse(data));
}

const handleProjectCreate: express.Handler = async (req, resp) => {
	try {
		const tmpDir = tmp.dirSync().name;
		const [publicKey, privateKey] = await generateKey(tmpDir);
		const { id } = await db.project.create({
			data: {
				userId: resp.locals.userId,
				name: req.body.name,
				deployKey: privateKey,
				deployKeyPublic: publicKey,
			},
		});
		resp.status(200);
		resp.header("Content-Type", "application/json");
		resp.write(
			JSON.stringify({
				id: id.toString(),
			}),
		);
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

const handleProjectAll: express.Handler = async (req, resp) => {
	try {
		const r = await db.project.findMany({
			where: {
				userId: resp.locals.userId,
			},
		});
		resp.status(200);
		resp.header("Content-Type", "application/json");
		resp.write(
			JSON.stringify(
				r.map((p) => ({
					id: p.id.toString(),
					name: p.name,
				})),
			),
		);
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

async function getState(projectId: number, userId: string, state: "deploy" | "draft"): Promise<Graph | null> {
	const r = await db.project.findUnique({
		where: {
			id: projectId,
			userId: userId,
		},
		select: {
			state: true,
			draft: true,
		},
	});
	if (r == null) {
		return null;
	}
	let currentState: Graph | null = null;
	if (state === "deploy") {
		if (r.state != null) {
			currentState = parseGraph(r.state)!.data!;
		}
	} else {
		if (r.draft == null) {
			if (r.state == null) {
				currentState = {
					nodes: [],
					edges: [],
					viewport: { x: 0, y: 0, zoom: 1 },
				};
			} else {
				currentState = parseGraph(r.state)!.data!;
			}
		} else {
			currentState = parseGraph(r.draft)!.data!;
		}
	}
	return currentState;
}

function handleSavedGet(state: "deploy" | "draft"): express.Handler {
	return async (req, resp) => {
		try {
			const projectId = Number(req.params["projectId"]);
			const graph = await getState(projectId, resp.locals.userId, state);
			if (graph == null) {
				resp.status(404);
				return;
			}
			const env = await getEnv(projectId, resp.locals.userId, resp.locals.username);
			const config = generateDodoConfig(projectId.toString(), graph.nodes, env);
			resp.status(200);
			resp.header("content-type", "application/json");
			resp.write(
				JSON.stringify({
					state: graph,
					config,
				}),
			);
		} catch (e) {
			console.log(e);
			resp.status(500);
		} finally {
			resp.end();
		}
	};
}

const handleProjectDelete: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const p = await db.project.findUnique({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
			select: {
				instanceId: true,
				githubToken: true,
				deployKeyPublic: true,
				state: true,
				draft: true,
			},
		});
		if (p === null) {
			resp.status(404);
			return;
		}
		if (p.githubToken && p.deployKeyPublic) {
			const allRepos = [...new Set([...extractGithubRepos(p.state), ...extractGithubRepos(p.draft)])];
			if (allRepos.length > 0) {
				const diff: RepoDiff = { toDelete: allRepos, toAdd: [] };
				const github = new GithubClient(p.githubToken);
				await manageGithubRepos(github, diff, p.deployKeyPublic, env.PUBLIC_ADDR);
				console.log(
					`Attempted to remove deploy keys for project ${projectId} from associated GitHub repositories.`,
				);
			}
		}
		if (p.instanceId !== null) {
			if (!(await appManager.removeInstance(p.instanceId))) {
				resp.status(500);
				resp.write(JSON.stringify({ error: "Failed to remove deployment from cluster" }));
				return;
			}
		}
		await db.project.delete({
			where: {
				id: projectId,
			},
		});
		resp.status(200);
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

function extractGithubRepos(serializedState: string | null | undefined): string[] {
	if (!serializedState) {
		return [];
	}
	try {
		const stateObj = JSON.parse(serializedState);
		const githubNodes = stateObj.nodes.filter(
			// eslint-disable-next-line @typescript-eslint/no-explicit-any
			(n: any) => n.type === "github" && n.data?.repository?.id,
		);
		// eslint-disable-next-line @typescript-eslint/no-explicit-any
		return githubNodes.map((n: any) => n.data.repository.sshURL);
	} catch (error) {
		console.error("Failed to parse state or extract GitHub repos:", error);
		return [];
	}
}

type RepoDiff = {
	toAdd?: string[];
	toDelete?: string[];
};

function calculateRepoDiff(oldRepos: string[], newRepos: string[]): RepoDiff {
	const toAdd = newRepos.filter((repo) => !oldRepos.includes(repo));
	const toDelete = oldRepos.filter((repo) => !newRepos.includes(repo));
	return { toAdd, toDelete };
}

async function manageGithubRepos(
	github: GithubClient,
	diff: RepoDiff,
	deployKey: string,
	publicAddr?: string,
): Promise<void> {
	for (const repoUrl of diff.toDelete ?? []) {
		try {
			await github.removeDeployKey(repoUrl, deployKey);
			console.log(`Removed deploy key from repository ${repoUrl}`);
			if (publicAddr) {
				const webhookCallbackUrl = `${publicAddr}/api/webhook/github/push`;
				await github.removePushWebhook(repoUrl, webhookCallbackUrl);
				console.log(`Removed push webhook from repository ${repoUrl}`);
			}
		} catch (error) {
			console.error(`Failed to remove deploy key from repository ${repoUrl}:`, error);
		}
	}
	for (const repoUrl of diff.toAdd ?? []) {
		try {
			await github.addDeployKey(repoUrl, deployKey);
			console.log(`Added deploy key to repository ${repoUrl}`);
			if (publicAddr) {
				const webhookCallbackUrl = `${publicAddr}/api/webhook/github/push`;
				await github.addPushWebhook(repoUrl, webhookCallbackUrl);
				console.log(`Added push webhook to repository ${repoUrl}`);
			}
		} catch (error) {
			console.error(`Failed to add deploy key from repository ${repoUrl}:`, error);
		}
	}
}

const handleDeploy: express.Handler = async (req, resp) => {
	try {
		const reqParsed = GraphConfigOrDraft.safeParse(req.body);
		if (!reqParsed.success) {
			resp.status(400);
			resp.write(JSON.stringify({ error: "Invalid request body", issues: reqParsed.error.format() }));
			return;
		}
		const projectId = Number(req.params["projectId"]);
		const p = await db.project.findUnique({
			where: {
				id: projectId,
				// userId: resp.locals.userId, TODO(gio): validate
			},
			select: {
				instanceId: true,
				githubToken: true,
				deployKey: true,
				deployKeyPublic: true,
				state: true,
				draft: true,
				geminiApiKey: true,
				anthropicApiKey: true,
			},
		});
		if (p === null) {
			resp.status(404);
			return;
		}
		let graph: Graph | null = null;
		let config: Config | null = null;
		if (reqParsed.data.type === "config") {
			const parsed = ConfigSchema.safeParse(reqParsed.data.config);
			if (parsed.success) {
				config = parsed.data;
			} else {
				resp.status(400);
				resp.write(JSON.stringify({ error: "Invalid configuration", issues: parsed.error.format() }));
				return;
			}
			let oldGraph: Graph | undefined = undefined;
			if (p.state != null) {
				oldGraph = parseGraph(p.state)!.data;
			} else if (p.draft != null) {
				oldGraph = parseGraph(p.draft)!.data;
			}
			let repos: GithubRepository[] = [];
			if (p.githubToken) {
				const github = new GithubClient(p.githubToken);
				repos = await github.getRepositories();
			}
			graph = configToGraph(config, getNetworks(resp.locals.username), repos, oldGraph);
		} else if (reqParsed.data.type === "graph") {
			graph = reqParsed.data.graph;
			const env = await getEnv(projectId, resp.locals.userId, resp.locals.username);
			config = generateDodoConfig(projectId.toString(), graph?.nodes || [], env);
		} else if (reqParsed.data.type === "draft") {
			if (p.draft == null) {
				resp.status(400);
				resp.write(JSON.stringify({ error: "Invalid request body" }));
				return;
			}
			graph = parseGraph(p.draft)!.data!;
			const env = await getEnv(projectId, resp.locals.userId, resp.locals.username);
			config = generateDodoConfig(projectId.toString(), graph?.nodes || [], env);
		}
		if (config == null || graph == null) {
			resp.status(500);
			resp.write(JSON.stringify({ error: "Failed to generate configuration" }));
			return;
		}
		await db.project.update({
			where: {
				id: projectId,
			},
			data: {
				draft: JSON.stringify(graph),
			},
		});
		let deployKey: string | null = p.deployKey;
		let deployKeyPublic: string | null = p.deployKeyPublic;
		if (deployKeyPublic == null) {
			[deployKeyPublic, deployKey] = await generateKey(tmp.dirSync().name);
			await db.project.update({
				where: { id: projectId },
				data: { deployKeyPublic, deployKey },
			});
		}
		let diff: RepoDiff | null = null;
		const cfg: ConfigWithInput = {
			...config,
			input: {
				appId: projectId.toString(),
				managerAddr: env.INTERNAL_API_ADDR!,
				key: {
					public: deployKeyPublic!,
					private: deployKey!,
				},
				geminiApiKey: p.geminiApiKey ?? undefined,
				anthropicApiKey: p.anthropicApiKey ?? undefined,
			},
		};
		try {
			let deployResponse: DeployResponse | null = null;
			if (p.instanceId == null) {
				deployResponse = await appManager.deploy(cfg);
				diff = { toAdd: extractGithubRepos(JSON.stringify(graph)) };
			} else {
				deployResponse = await appManager.update(p.instanceId, cfg);
				diff = calculateRepoDiff(extractGithubRepos(p.state), extractGithubRepos(JSON.stringify(graph)));
			}
			if (deployResponse == null) {
				resp.status(500);
				resp.write(JSON.stringify({ error: "Failed to deploy" }));
				return;
			}
			await db.project.update({
				where: {
					id: projectId,
				},
				data: {
					state: JSON.stringify(graph),
					draft: null,
					instanceId: deployResponse.id,
					access: JSON.stringify(deployResponse.access),
					envVars: JSON.stringify(deployResponse.envVars),
				},
			});
			if (diff && p.githubToken && deployKey) {
				const github = new GithubClient(p.githubToken);
				await manageGithubRepos(github, diff, deployKeyPublic!, env.PUBLIC_ADDR);
			}
			resp.status(200);
		} catch (error) {
			console.error("Deployment error:", error);
			resp.status(500);
			resp.write(JSON.stringify({ error: "Deployment failed" }));
		}
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

const handleSave: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const p = await db.project.findUnique({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
			select: {
				instanceId: true,
				githubToken: true,
				deployKey: true,
				deployKeyPublic: true,
				state: true,
				geminiApiKey: true,
				anthropicApiKey: true,
			},
		});
		if (p === null) {
			resp.status(404);
			return;
		}
		const gc = GraphOrConfigSchema.safeParse(req.body);
		if (!gc.success) {
			resp.status(400);
			resp.write(JSON.stringify({ error: "Invalid configuration", issues: gc.error.format() }));
			return;
		}
		if (gc.data.type === "graph") {
			await db.project.update({
				where: { id: projectId },
				data: { draft: JSON.stringify(gc.data.graph) },
			});
			resp.status(200);
			return;
		}
		let repos: GithubRepository[] = [];
		if (p.githubToken) {
			const github = new GithubClient(p.githubToken);
			repos = await github.getRepositories();
		}
		const state = JSON.stringify(
			configToGraph(
				gc.data.config,
				getNetworks(resp.locals.username),
				repos,
				p.state ? parseGraph(p.state)!.data! : undefined,
			),
		);
		await db.project.update({
			where: { id: projectId },
			data: { draft: state },
		});
		resp.status(200);
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

const handleStatus: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const p = await db.project.findUnique({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
			select: {
				instanceId: true,
			},
		});
		if (p === null) {
			resp.status(404);
			return;
		}
		if (p.instanceId == null) {
			resp.status(404);
			return;
		}
		try {
			const status = await appManager.getStatus(p.instanceId);
			resp.status(200);
			resp.write(JSON.stringify(status));
		} catch (error) {
			console.error("Error getting status:", error);
			resp.status(500);
		}
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

const handleConfigGet: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const project = await db.project.findUnique({
			where: {
				id: projectId,
			},
			select: {
				state: true,
			},
		});

		if (!project || !project.state) {
			resp.status(404).send({ error: "No deployed configuration found." });
			return;
		}

		const state = parseGraph(project.state)!.data!;
		const env = await getEnv(projectId, resp.locals.userId, resp.locals.username);
		const config = generateDodoConfig(projectId.toString(), state.nodes, env);

		if (!config) {
			resp.status(500).send({ error: "Failed to generate configuration." });
			return;
		}
		resp.status(200).json(config);
	} catch (e) {
		console.log(e);
		resp.status(500).send({ error: "Internal server error" });
	} finally {
		console.log("config get done");
		resp.end();
	}
};

const handleRemoveDeployment: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const p = await db.project.findUnique({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
			select: {
				instanceId: true,
				githubToken: true,
				deployKeyPublic: true,
				state: true,
				draft: true,
			},
		});
		if (p === null) {
			resp.status(404);
			resp.write(JSON.stringify({ error: "Project not found" }));
			return;
		}
		if (p.instanceId == null) {
			resp.status(400);
			resp.write(JSON.stringify({ error: "Project not deployed" }));
			return;
		}
		const removed = await appManager.removeInstance(p.instanceId);
		if (!removed) {
			resp.status(500);
			resp.write(JSON.stringify({ error: "Failed to remove deployment from cluster" }));
			return;
		}
		if (p.githubToken && p.deployKeyPublic && p.state) {
			try {
				const github = new GithubClient(p.githubToken);
				const repos = extractGithubRepos(p.state);
				const diff = { toDelete: repos, toAdd: [] };
				await manageGithubRepos(github, diff, p.deployKeyPublic, env.PUBLIC_ADDR);
			} catch (error) {
				console.error("Error removing GitHub deploy keys:", error);
			}
		}
		await db.project.update({
			where: {
				id: projectId,
			},
			data: {
				instanceId: null,
				deployKeyPublic: null,
				access: null,
				state: null,
				draft: p.draft ?? p.state,
			},
		});
		resp.status(200);
		resp.write(JSON.stringify({ success: true }));
	} catch (e) {
		console.error("Error removing deployment:", e);
		resp.status(500);
		resp.write(JSON.stringify({ error: "Internal server error" }));
	} finally {
		resp.end();
	}
};

const handleGithubRepos: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const project = await db.project.findUnique({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
			select: {
				githubToken: true,
			},
		});
		if (!project?.githubToken) {
			resp.status(400);
			resp.write(JSON.stringify({ error: "GitHub token not configured" }));
			return;
		}
		const github = new GithubClient(project.githubToken);
		const repositories = await github.getRepositories();
		resp.status(200);
		resp.header("Content-Type", "application/json");
		resp.write(JSON.stringify(repositories));
	} catch (e) {
		console.log(e);
		resp.status(500);
		resp.write(JSON.stringify({ error: "Failed to fetch repositories" }));
	} finally {
		resp.end();
	}
};

const handleUpdateGithubToken: express.Handler = async (req, resp) => {
	try {
		await db.project.update({
			where: {
				id: Number(req.params["projectId"]),
				userId: resp.locals.userId,
			},
			data: {
				githubToken: req.body.githubToken,
			},
		});
		resp.status(200);
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

const handleUpdateGeminiToken: express.Handler = async (req, resp) => {
	try {
		await db.project.update({
			where: {
				id: Number(req.params["projectId"]),
				userId: resp.locals.userId,
			},
			data: {
				geminiApiKey: req.body.geminiApiKey,
			},
		});
		resp.status(200);
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

const handleUpdateAnthropicToken: express.Handler = async (req, resp) => {
	try {
		await db.project.update({
			where: {
				id: Number(req.params["projectId"]),
				userId: resp.locals.userId,
			},
			data: {
				anthropicApiKey: req.body.anthropicApiKey,
			},
		});
		resp.status(200);
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

const getNetworks = (username?: string | undefined): Network[] => {
	return [
		{
			name: "Trial",
			domain: "trial.dodoapp.xyz",
			hasAuth: false,
		},
		// TODO(gio): Remove
	].concat(
		username === "gio" || 1 == 1
			? [
					{
						name: "Public",
						domain: "v1.dodo.cloud",
						hasAuth: true,
					},
					{
						name: "Private",
						domain: "p.v1.dodo.cloud",
						hasAuth: true,
					},
				]
			: [],
	);
};

const getEnv = async (projectId: number, userId: string, username: string): Promise<Env> => {
	const project = await db.project.findUnique({
		where: {
			id: projectId,
			userId,
		},
		select: {
			deployKeyPublic: true,
			githubToken: true,
			geminiApiKey: true,
			anthropicApiKey: true,
			access: true,
			instanceId: true,
		},
	});
	if (!project) {
		throw new Error("Project not found");
	}
	const monitor = projectMonitors.get(projectId);
	const serviceNames = monitor ? monitor.getAllServiceNames() : [];
	const services = serviceNames.map((name: string) => ({
		name,
		workers: [...(monitor ? monitor.getWorkerStatusesForService(name) : new Map()).entries()].map(
			([id, status]) => ({
				...status,
				id,
			}),
		),
	}));
	return {
		deployKeyPublic: project.deployKeyPublic == null ? undefined : project.deployKeyPublic,
		instanceId: project.instanceId == null ? undefined : project.instanceId,
		access: JSON.parse(project.access ?? "[]"),
		integrations: {
			github: !!project.githubToken,
			gemini: !!project.geminiApiKey,
			anthropic: !!project.anthropicApiKey,
		},
		networks: getNetworks(username),
		services,
		user: {
			id: userId,
			username: username,
		},
	};
};

const handleMachines: express.Handler = async (req, resp) => {
	try {
		const machines = await machineManager.getUserMachines(resp.locals.username);
		resp.status(200);
		resp.write(JSON.stringify(machines));
	} catch (error) {
		console.error("Error getting machines:", error);
		resp.status(500);
		resp.write(JSON.stringify({ error: "Internal server error" }));
	} finally {
		resp.end();
	}
};

const handleEnv: express.Handler = async (req, resp) => {
	const projectId = Number(req.params["projectId"]);
	try {
		const env = await getEnv(projectId, resp.locals.userId, resp.locals.username);
		resp.status(200);
		resp.write(JSON.stringify(env));
	} catch (error) {
		console.error("Error getting env:", error);
		resp.status(500);
		resp.write(JSON.stringify({ error: "Internal server error" }));
	} finally {
		resp.end();
	}
};

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const internalEnvSchema = z.object({
	githubToken: z.string().optional(),
	networks: z.array(
		z.object({
			name: z.string(),
			domain: z.string(),
			hasAuth: z.boolean(),
		}),
	),
	envVars: z.array(z.object({ name: z.string(), value: z.string() })),
});

type InternalEnv = z.infer<typeof internalEnvSchema>;

const handleInternalEnv: express.Handler = async (req, resp) => {
	try {
		console.log("getting internal env");
		const project = await db.project.findUnique({
			where: {
				id: Number(req.params["projectId"]),
				userId: resp.locals.userId,
			},
			select: {
				githubToken: true,
				envVars: true,
			},
		});
		const networks = getNetworks(resp.locals.username);
		const env: InternalEnv = {
			networks,
			githubToken: project?.githubToken ?? undefined,
			envVars: JSON.parse(project?.envVars ?? "[]"),
		};
		resp.status(200);
		resp.write(JSON.stringify(env));
	} catch (error) {
		console.error("Error getting env:", error);
		resp.status(500);
		resp.write(JSON.stringify({ error: "Internal server error" }));
	} finally {
		resp.end();
	}
};

const handleServiceLogs: express.Handler = async (req, resp) => {
	const projectId = Number(req.params["projectId"]);
	const service = req.params["service"];
	const workerId = req.params["workerId"];

	resp.setHeader("Content-Type", "text/event-stream");
	resp.setHeader("Cache-Control", "no-cache");
	resp.setHeader("Connection", "keep-alive");
	resp.flushHeaders();

	const timestampFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
	const sendLogs = (logs: LogItem[]) => {
		if (logs.length == 0) {
			return;
		}
		const logString = logs
			.map((l) => {
				const t = Instant.ofEpochMilli(l.timestampMilli);
				const formattedTimestamp = t.atZone(ZoneId.UTC).format(timestampFormat);
				return `\x1b[38;5;240m${formattedTimestamp}\x1b[0m ${l.contents}`;
			})
			.join("\n");
		resp.write("event: message\n");
		resp.write(`data: ${JSON.stringify({ logs: logString })}\n\n`);
	};

	try {
		const project = await db.project.findUnique({
			where: { id: projectId, userId: resp.locals.userId },
		});

		if (!project) {
			resp.status(404).end();
			return;
		}

		const monitor = projectMonitors.get(projectId);
		if (!monitor) {
			resp.status(404).end();
			return;
		}

		let lastLogId: number | undefined = undefined;
		const initialLogs = (await logStore.get(projectId, service, workerId)) || [];
		await sendLogs(initialLogs);
		if (initialLogs.length > 0) {
			lastLogId = initialLogs[initialLogs.length - 1].id;
		}
		resp.flushHeaders();

		const intervalId = setInterval(async () => {
			const currentLogs = (await logStore.get(projectId, service, workerId, lastLogId)) || [];
			if (currentLogs.length > 0) {
				await sendLogs(currentLogs);
				lastLogId = currentLogs[currentLogs.length - 1].id;
			}
		}, 500);

		req.on("close", () => {
			clearInterval(intervalId);
			resp.end();
		});
	} catch (e) {
		console.log(e);
		resp.status(500).end();
	}
};

const handleRegisterWorker: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const result = WorkerSchema.safeParse(req.body);
		if (!result.success) {
			console.log(JSON.stringify(result.error));
			resp.status(400);
			resp.write(
				JSON.stringify({
					error: "Invalid request data",
					details: result.error.format(),
				}),
			);
			return;
		}
		let monitor = projectMonitors.get(projectId);
		if (!monitor) {
			monitor = new ProjectMonitor();
			projectMonitors.set(projectId, monitor);
		}
		monitor.registerWorker(result.data);
		if (result.data.logs) {
			await logStore.store(projectId, result.data.service, result.data.id, result.data.logs);
		}
		resp.status(200);
		resp.write(
			JSON.stringify({
				success: true,
				logItemsConsumed: result.data.logs?.length ?? 0,
			}),
		);
	} catch (e) {
		console.log(e);
		resp.status(500);
		resp.write(JSON.stringify({ error: "Failed to register worker" }));
	} finally {
		resp.end();
	}
};

async function reloadProject(projectId: number): Promise<boolean> {
	const monitor = projectMonitors.get(projectId);
	const projectWorkers = monitor ? monitor.getWorkerAddresses() : [];
	const workerCount = projectWorkers.length;
	if (workerCount === 0) {
		return true;
	}
	const results = await Promise.all(
		projectWorkers.map(async (workerAddress: string) => {
			try {
				const resp = await axios.get(`${workerAddress}/update`);
				return resp.status === 200;
			} catch (error) {
				console.error(`Failed to reload worker ${workerAddress}:`, error);
				return false;
			}
		}),
	);
	return results.reduce((acc: boolean, curr: boolean) => acc && curr, true);
}

const handleReload: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const projectAuth = await db.project.findFirst({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
			select: { id: true },
		});
		if (!projectAuth) {
			resp.status(404);
			return;
		}
		const success = await reloadProject(projectId);
		if (success) {
			resp.status(200);
		} else {
			resp.status(500);
		}
	} catch (e) {
		console.error(e);
		resp.status(500);
	}
};

const handleQuitWorker: express.Handler = async (req, resp) => {
	const projectId = Number(req.params["projectId"]);
	const serviceName = req.params["serviceName"];
	const workerId = req.params["workerId"];

	const projectMonitor = projectMonitors.get(projectId);
	if (!projectMonitor) {
		resp.status(404).send({ error: "Project monitor not found" });
		return;
	}

	try {
		await projectMonitor.terminateWorker(serviceName, workerId);
		resp.status(200).send({ message: "Worker termination initiated" });
	} catch (error) {
		console.error(
			`Failed to terminate worker ${workerId} in service ${serviceName} for project ${projectId}:`,
			error,
		);
		const errorMessage = error instanceof Error ? error.message : "Unknown error";
		resp.status(500).send({ error: `Failed to terminate worker: ${errorMessage}` });
	}
};

const handleReloadWorker: express.Handler = async (req, resp) => {
	const projectId = Number(req.params["projectId"]);
	const serviceName = req.params["serviceName"];
	const workerId = req.params["workerId"];

	const projectMonitor = projectMonitors.get(projectId);
	if (!projectMonitor) {
		resp.status(404).send({ error: "Project monitor not found" });
		return;
	}

	try {
		await projectMonitor.reloadWorker(serviceName, workerId);
		resp.status(200).send({ message: "Worker reload initiated" });
	} catch (error) {
		console.error(`Failed to reload worker ${workerId} in service ${serviceName} for project ${projectId}:`, error);
		const errorMessage = error instanceof Error ? error.message : "Unknown error";
		resp.status(500).send({ error: `Failed to reload worker: ${errorMessage}` });
	}
};

const analyzeRepoReqSchema = z.object({
	address: z.string(),
});

const handleAnalyzeRepo: express.Handler = async (req, resp) => {
	const projectId = Number(req.params["projectId"]);
	const project = await db.project.findUnique({
		where: {
			id: projectId,
			userId: resp.locals.userId,
		},
		select: {
			githubToken: true,
			deployKey: true,
			deployKeyPublic: true,
		},
	});
	if (!project) {
		resp.status(404).send({ error: "Project not found" });
		return;
	}
	if (!project.githubToken) {
		resp.status(400).send({ error: "GitHub token not configured" });
		return;
	}
	let tmpDir: tmp.DirResult | null = null;
	try {
		let deployKey: string | null = project.deployKey;
		let deployKeyPublic: string | null = project.deployKeyPublic;
		if (!deployKeyPublic) {
			[deployKeyPublic, deployKey] = await generateKey(tmp.dirSync().name);
			await db.project.update({
				where: { id: projectId },
				data: {
					deployKeyPublic: deployKeyPublic,
					deployKey: deployKey,
				},
			});
		}
		const github = new GithubClient(project.githubToken);
		const result = analyzeRepoReqSchema.safeParse(req.body);
		if (!result.success) {
			resp.status(400).send({ error: "Invalid request data" });
			return;
		}
		const { address } = result.data;
		tmpDir = tmp.dirSync({
			unsafeCleanup: true,
		});
		await github.addDeployKey(address, deployKeyPublic);
		await fs.promises.writeFile(path.join(tmpDir.name, "key"), deployKey!, {
			mode: 0o600,
		});
		shell.exec(
			`GIT_SSH_COMMAND='ssh -i ${tmpDir.name}/key -o IdentitiesOnly=yes' git clone ${address} ${tmpDir.name}/code`,
		);
		const fsc = new RealFileSystem(`${tmpDir.name}/code`);
		const analyzer = new NodeJSAnalyzer();
		const info = await analyzer.analyze(fsc, "/");
		resp.status(200).send([info]);
	} catch (e) {
		console.error(e);
		resp.status(500).send({ error: "Failed to analyze repository" });
	} finally {
		if (tmpDir) {
			tmpDir.removeCallback();
		}
		resp.end();
	}
};

const auth = (req: express.Request, resp: express.Response, next: express.NextFunction) => {
	// Hardcoded user for development
	resp.locals.userId = req.headers["x-forwarded-userid"];
	resp.locals.username = req.headers["x-forwarded-user"];
	next();
};

const handleGithubPushWebhook: express.Handler = async (req, resp) => {
	try {
		// TODO(gio): Implement GitHub signature verification for security
		const webhookSchema = z.object({
			repository: z.object({
				ssh_url: z.string(),
			}),
		});

		const result = webhookSchema.safeParse(req.body);
		if (!result.success) {
			console.warn("GitHub webhook: Invalid payload:", result.error.issues);
			resp.status(400).json({ error: "Invalid webhook payload" });
			return;
		}
		const { ssh_url: addr } = result.data.repository;
		const allProjects = await db.project.findMany({
			select: {
				id: true,
				state: true,
			},
			where: {
				instanceId: {
					not: null,
				},
			},
		});
		new Promise<boolean>((resolve, reject) => {
			setTimeout(() => {
				const projectsToReloadIds: number[] = [];
				for (const project of allProjects) {
					if (project.state && project.state.length > 0) {
						const projectRepos = extractGithubRepos(project.state);
						if (projectRepos.includes(addr)) {
							projectsToReloadIds.push(project.id);
						}
					}
				}
				Promise.all(projectsToReloadIds.map((id) => reloadProject(id)))
					.then((results) => {
						resolve(results.reduce((acc, curr) => acc && curr, true));
					})
					// eslint-disable-next-line @typescript-eslint/no-explicit-any
					.catch((reason: any) => reject(reason));
			}, 10);
		});
		resp.status(200);
		// eslint-disable-next-line @typescript-eslint/no-explicit-any
	} catch (error: any) {
		console.error(error);
		resp.status(500);
	} finally {
		resp.end();
	}
};

const handleValidateConfig: express.Handler = async (req, resp) => {
	try {
		const validationResult = ConfigSchema.safeParse(req.body);
		if (!validationResult.success) {
			resp.status(400);
			resp.header("Content-Type", "application/json");
			resp.write(JSON.stringify({ success: false, errors: validationResult.error.flatten() }));
		} else {
			resp.status(200);
			resp.header("Content-Type", "application/json");
			resp.write(JSON.stringify({ success: true }));
		}
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

function handleStateGetStream(state: "deploy" | "draft"): express.Handler {
	return async (req, resp) => {
		resp.setHeader("Content-Type", "text/event-stream");
		resp.setHeader("Cache-Control", "no-cache");
		resp.setHeader("Connection", "keep-alive");
		resp.flushHeaders();

		try {
			let intervalId: NodeJS.Timeout | null = null;
			let lastState: Graph | null = null;
			const sendState = async () => {
				const currentState = await getState(Number(req.params["projectId"]), resp.locals.userId, state);
				if (currentState == null) {
					resp.status(404).end();
					return;
				}
				if (JSON.stringify(currentState) !== JSON.stringify(lastState)) {
					lastState = currentState;
					resp.write("event: message\n");
					resp.write(`data: ${JSON.stringify(currentState)}\n\n`);
				}
				intervalId = setTimeout(sendState, 500);
			};

			await sendState();

			req.on("close", () => {
				if (intervalId) {
					clearTimeout(intervalId);
				}
				resp.end();
			});
		} catch (e) {
			console.log(e);
			resp.end();
		}
	};
}

const handleAgentStatus: express.Handler = async (req, resp) => {
	const projectId = Number(req.params["projectId"]);
	const agentName = req.params["agentName"];
	try {
		const env = await getEnv(projectId, resp.locals.userId, resp.locals.username);
		const agent = env.access.find((a): a is AgentAccess => a.type === "https" && a.agentName === agentName);
		if (!agent) {
			resp.status(404).send({ status: 404 });
			return;
		}
		const agentResp = await axios.get(agent.address);
		resp.status(200).send({ status: agentResp.status });
	} catch {
		resp.status(200).send({ status: 500 });
	}
};

async function start() {
	await db.$connect();
	const app = express();
	app.set("json spaces", 2);
	app.use(express.json()); // Global JSON parsing

	// Public webhook route - no auth needed
	app.post("/api/webhook/github/push", handleGithubPushWebhook);

	// Public machines route - no auth needed
	app.get("/api/machines", auth, handleMachines);

	// Authenticated project routes
	const projectRouter = express.Router();
	projectRouter.use(auth);
	projectRouter.post("/:projectId/analyze", handleAnalyzeRepo);
	projectRouter.post("/:projectId/saved", handleSave);
	projectRouter.get("/:projectId/state/stream/deploy", handleStateGetStream("deploy"));
	projectRouter.get("/:projectId/state/stream/draft", handleStateGetStream("draft"));
	projectRouter.get("/:projectId/saved/deploy", handleSavedGet("deploy"));
	projectRouter.get("/:projectId/saved/draft", handleSavedGet("draft"));
	projectRouter.post("/:projectId/deploy", handleDeploy);
	projectRouter.get("/:projectId/status", handleStatus);
	projectRouter.get("/:projectId/config", handleConfigGet);
	projectRouter.delete("/:projectId", handleProjectDelete);
	projectRouter.get("/:projectId/repos/github", handleGithubRepos);
	projectRouter.post("/:projectId/github-token", handleUpdateGithubToken);
	projectRouter.post("/:projectId/gemini-token", handleUpdateGeminiToken);
	projectRouter.post("/:projectId/anthropic-token", handleUpdateAnthropicToken);
	projectRouter.get("/:projectId/env", handleEnv);
	projectRouter.post("/:projectId/reload/:serviceName/:workerId", handleReloadWorker);
	projectRouter.post("/:projectId/quitquitquit/:serviceName/:workerId", handleQuitWorker);
	projectRouter.post("/:projectId/reload", handleReload);
	projectRouter.get("/:projectId/logs/:service/:workerId", handleServiceLogs);
	projectRouter.get("/:projectId/agent/:agentName/status", handleAgentStatus);
	projectRouter.post("/:projectId/remove-deployment", handleRemoveDeployment);
	projectRouter.get("/", handleProjectAll);
	projectRouter.post("/", handleProjectCreate);

	app.use("/api/project", projectRouter); // Mount the authenticated router

	app.use("/", express.static("../front/dist"));

	const internalApi = express();
	internalApi.use(express.json());
	internalApi.post("/api/project/:projectId/workers", handleRegisterWorker);
	internalApi.get("/api/project/:projectId/config", handleConfigGet);
	internalApi.post("/api/project/:projectId/saved", handleSave);
	internalApi.post("/api/project/:projectId/deploy", handleDeploy);
	internalApi.get("/api/project/:projectId/env", handleInternalEnv);
	internalApi.post("/api/validate-config", handleValidateConfig);

	app.listen(env.DODO_PORT_WEB, () => {
		console.log("Web server started on port", env.DODO_PORT_WEB);
	});

	internalApi.listen(env.DODO_PORT_API, () => {
		console.log("Internal API server started on port", env.DODO_PORT_API);
	});
}

function cleanupWorkers() {
	const now = Date.now();
	projectMonitors.forEach((monitor) => {
		monitor.cleanupWorkers(now);
	});
	setTimeout(cleanupWorkers, 1000);
}

setTimeout(cleanupWorkers, 1000);

start();
