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 } 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,
	AppNode,
	ConfigWithInput,
	configToGraph,
	Network,
	GithubRepository,
} from "config";
import { Instant, DateTimeFormatter, ZoneId } from "@js-joda/core";
import LogStore from "./log.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 projectMonitors = new Map<number, ProjectMonitor>();

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();
	}
};

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

function handleSavedGet(state: "deploy" | "draft"): express.Handler {
	return async (req, resp) => {
		try {
			const r = await db.project.findUnique({
				where: {
					id: Number(req.params["projectId"]),
					userId: resp.locals.userId,
				},
				select: {
					state: true,
					draft: true,
				},
			});
			if (r == null) {
				resp.status(404);
				return;
			}
			resp.status(200);
			resp.header("content-type", "application/json");
			let currentState: Record<string, unknown> | null = null;
			if (state === "deploy") {
				if (r.state == null) {
					currentState = {
						nodes: [],
						edges: [],
						viewport: { x: 0, y: 0, zoom: 1 },
					};
				} else {
					currentState = JSON.parse(Buffer.from(r.state).toString("utf8"));
				}
			} else {
				if (r.draft == null) {
					if (r.state == null) {
						currentState = {
							nodes: [],
							edges: [],
							viewport: { x: 0, y: 0, zoom: 1 },
						};
					} else {
						currentState = JSON.parse(Buffer.from(r.state).toString("utf8"));
					}
				} else {
					currentState = JSON.parse(Buffer.from(r.draft).toString("utf8"));
				}
			}
			const env = await getEnv(Number(req.params["projectId"]), resp.locals.userId, resp.locals.username);
			if (currentState) {
				const config = generateDodoConfig(
					req.params["projectId"].toString(),
					currentState.nodes as AppNode[],
					env,
				);
				resp.send({
					state: currentState,
					config,
				});
			}
		} catch (e) {
			console.log(e);
			resp.status(500);
		} finally {
			resp.end();
		}
	};
}

const projectDeleteReqSchema = z.object({
	state: z.optional(z.nullable(z.string())),
});

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;
		}
		const parseResult = projectDeleteReqSchema.safeParse(req.body);
		if (!parseResult.success) {
			resp.status(400);
			resp.write(JSON.stringify({ error: "Invalid request body", issues: parseResult.error.format() }));
			return;
		}
		if (p.githubToken && p.deployKeyPublic) {
			const allRepos = [
				...new Set([
					...extractGithubRepos(p.state),
					...extractGithubRepos(p.draft),
					...extractGithubRepos(parseResult.data.state),
				]),
			];
			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 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,
				geminiApiKey: true,
				anthropicApiKey: true,
			},
		});
		if (p === null) {
			resp.status(404);
			return;
		}
		const config = ConfigSchema.safeParse(req.body.config);
		if (!config.success) {
			resp.status(400);
			resp.write(JSON.stringify({ error: "Invalid configuration", issues: config.error.format() }));
			return;
		}
		let repos: GithubRepository[] = [];
		if (p.githubToken) {
			const github = new GithubClient(p.githubToken);
			repos = await github.getRepositories();
		}
		const state = req.body.state
			? JSON.stringify(req.body.state)
			: JSON.stringify(
					configToGraph(
						config.data,
						getNetworks(resp.locals.username),
						repos,
						p.state ? JSON.parse(Buffer.from(p.state).toString("utf8")) : null,
					),
				);
		await db.project.update({
			where: {
				id: projectId,
			},
			data: {
				draft: state,
			},
		});
		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.data,
			input: {
				appId: projectId.toString(),
				managerAddr: env.INTERNAL_API_ADDR!,
				key: {
					public: deployKeyPublic!,
					private: deployKey!,
				},
				geminiApiKey: p.geminiApiKey ?? undefined,
				anthropicApiKey: p.anthropicApiKey ?? undefined,
			},
		};
		try {
			if (p.instanceId == null) {
				const deployResponse = await appManager.deploy(cfg);
				await db.project.update({
					where: {
						id: projectId,
					},
					data: {
						state,
						draft: null,
						instanceId: deployResponse.id,
						access: JSON.stringify(deployResponse.access),
					},
				});
				diff = { toAdd: extractGithubRepos(state) };
			} else {
				const deployResponse = await appManager.update(p.instanceId, cfg);
				diff = calculateRepoDiff(extractGithubRepos(p.state), extractGithubRepos(state));
				await db.project.update({
					where: {
						id: projectId,
					},
					data: {
						state,
						draft: null,
						access: JSON.stringify(deployResponse.access),
					},
				});
			}
			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 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 = JSON.parse(Buffer.from(project.state).toString("utf8"));
		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 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();
	}
};

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)) || [];
		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) {
				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 { data } = await axios.get(`http://${workerAddress}/reload`);
				return data.every((s: { status: string }) => s.status === "ok");
			} 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 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 = "1";
	resp.locals.username = "gio";
	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,
				},
			},
		});
		// TODO(gio): This should run in background
		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);
		});
		// eslint-disable-next-line @typescript-eslint/no-explicit-any
	} catch (error: any) {
		console.error(error);
		resp.status(500);
	}
};

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();
	}
};

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);

	// Authenticated project routes
	const projectRouter = express.Router();
	projectRouter.use(auth);
	projectRouter.post("/:projectId/analyze", handleAnalyzeRepo);
	projectRouter.post("/:projectId/saved", handleSave);
	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/reload", handleReload);
	projectRouter.get("/:projectId/logs/:service/:workerId", handleServiceLogs);
	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/deploy", handleDeploy);
	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);
	});
}

start();
