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 } 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";

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 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,
			},
		});
		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!,
				},
			},
		};
		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 {
		const projectId = Number(req.params["projectId"]);
		const { githubToken } = req.body;
		await db.project.update({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
			data: { githubToken },
		});
		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,
			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 {
		managerAddr: env.INTERNAL_API_ADDR,
		deployKeyPublic: project.deployKeyPublic == null ? undefined : project.deployKeyPublic,
		instanceId: project.instanceId == null ? undefined : project.instanceId,
		access: JSON.parse(project.access ?? "[]"),
		integrations: {
			github: !!project.githubToken,
		},
		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) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const service = req.params["service"];
		const workerId = req.params["workerId"];
		const project = await db.project.findUnique({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
		});
		if (project == null) {
			resp.status(404);
			resp.write(JSON.stringify({ error: "Project not found" }));
			return;
		}
		const monitor = projectMonitors.get(projectId);
		if (!monitor || !monitor.hasLogs()) {
			resp.status(404);
			resp.write(JSON.stringify({ error: "No logs found for this project" }));
			return;
		}
		const serviceLog = monitor.getWorkerLog(service, workerId);
		if (!serviceLog) {
			resp.status(404);
			resp.write(JSON.stringify({ error: "No logs found for this service/worker" }));
			return;
		}
		resp.status(200);
		resp.write(JSON.stringify({ logs: serviceLog }));
	} catch (e) {
		console.log(e);
		resp.status(500);
		resp.write(JSON.stringify({ error: "Failed to get service logs" }));
	} finally {
		resp.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);
		resp.status(200);
		resp.write(
			JSON.stringify({
				success: true,
			}),
		);
	} 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) => {
	const userId = req.get("x-forwarded-userid");
	const username = req.get("x-forwarded-user");
	if (userId == null || username == null) {
		resp.status(401);
		resp.write("Unauthorized");
		resp.end();
		return;
	}
	resp.locals.userId = userId;
	resp.locals.username = username;
	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.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();
