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