import { PrismaClient } from "@prisma/client";
import express from "express";
import { env } from "node:process";
import axios from "axios";
import { GithubClient } from "./github";
import { AppManager } from "./app_manager";
import { z } from "zod";

const db = new PrismaClient();
const appManager = new AppManager();

const workers = new Map<number, string[]>();
const logs = new Map<number, Map<string, string>>();

const handleProjectCreate: express.Handler = async (req, resp) => {
	try {
		const { id } = await db.project.create({
			data: {
				userId: resp.locals.userId,
				name: req.body.name,
			},
		});
		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: Buffer.from(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");
			if (state === "deploy") {
				if (r.state == null) {
					resp.send({
						nodes: [],
						edges: [],
						viewport: { x: 0, y: 0, zoom: 1 },
					});
				} else {
					resp.send(JSON.parse(Buffer.from(r.state).toString("utf8")));
				}
			} else {
				if (r.draft == null) {
					if (r.state == null) {
						resp.send({
							nodes: [],
							edges: [],
							viewport: { x: 0, y: 0, zoom: 1 },
						});
					} else {
						resp.send(JSON.parse(Buffer.from(r.state).toString("utf8")));
					}
				} else {
					resp.send(JSON.parse(Buffer.from(r.draft).toString("utf8")));
				}
			}
		} catch (e) {
			console.log(e);
			resp.status(500);
		} finally {
			resp.end();
		}
	};
}

const handleDelete: 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;
		}
		let ok = false;
		if (p.instanceId === null) {
			ok = true;
		} else {
			ok = await appManager.removeInstance(p.instanceId);
		}
		if (ok) {
			await db.project.delete({
				where: {
					id: projectId,
				},
			});
		}
		resp.status(200);
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

function extractGithubRepos(serializedState: Buffer | Uint8Array | null): string[] {
	if (!serializedState) {
		return [];
	}
	try {
		const stateObj = JSON.parse(serializedState.toString());
		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 manageGithubKeys(github: GithubClient, deployKey: string, diff: RepoDiff): Promise<void> {
	for (const repoUrl of diff.toDelete ?? []) {
		try {
			await github.removeDeployKey(repoUrl, deployKey);
			console.log(`Removed deploy key 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}`);
		} 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 state = Buffer.from(JSON.stringify(req.body.state));
		const p = await db.project.findUnique({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
			select: {
				instanceId: true,
				githubToken: true,
				deployKey: true,
				state: true,
			},
		});
		if (p === null) {
			resp.status(404);
			return;
		}
		await db.project.update({
			where: {
				id: projectId,
			},
			data: {
				draft: state,
			},
		});
		let diff: RepoDiff | null = null;
		let deployKey: string | null = null;
		try {
			if (p.instanceId == null) {
				const deployResponse = await appManager.deploy(req.body.config);
				await db.project.update({
					where: {
						id: projectId,
					},
					data: {
						state,
						draft: null,
						instanceId: deployResponse.id,
						deployKey: deployResponse.deployKey,
					},
				});
				diff = { toAdd: extractGithubRepos(state) };
				deployKey = deployResponse.deployKey;
			} else {
				const success = await appManager.update(p.instanceId, req.body.config);
				if (success) {
					diff = calculateRepoDiff(extractGithubRepos(p.state), extractGithubRepos(state));
					deployKey = p.deployKey;
					await db.project.update({
						where: {
							id: projectId,
						},
						data: {
							state,
							draft: null,
						},
					});
				} else {
					resp.status(500);
					resp.write(JSON.stringify({ error: "Failed to update deployment" }));
					return;
				}
			}
			if (diff && p.githubToken && deployKey) {
				const github = new GithubClient(p.githubToken);
				await manageGithubKeys(github, deployKey, diff);
			}
			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 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 handleEnv: express.Handler = async (req, resp) => {
	const projectId = Number(req.params["projectId"]);
	try {
		const project = await db.project.findUnique({
			where: {
				id: projectId,
				userId: resp.locals.userId,
			},
			select: {
				deployKey: true,
				githubToken: true,
			},
		});
		if (!project) {
			resp.status(404);
			resp.write(JSON.stringify({ error: "Project not found" }));
			return;
		}
		const projectLogs = logs.get(projectId) || new Map();
		const services = Array.from(projectLogs.keys());
		resp.status(200);
		resp.write(
			JSON.stringify({
				// TODO(gio): get from env or command line flags
				managerAddr: "http://10.42.0.211:8081",
				deployKey: project.deployKey,
				integrations: {
					github: !!project.githubToken,
				},
				networks: [
					{
						name: "Public",
						domain: "v1.dodo.cloud",
					},
					{
						name: "Private",
						domain: "p.v1.dodo.cloud",
					},
				],
				services,
				user: {
					id: resp.locals.userId,
					username: resp.locals.username,
				},
			}),
		);
	} catch (error) {
		console.error("Error checking integrations:", 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 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 projectLogs = logs.get(projectId);
		if (!projectLogs) {
			resp.status(404);
			resp.write(JSON.stringify({ error: "No logs found for this project" }));
			return;
		}
		const serviceLog = projectLogs.get(service);
		if (!serviceLog) {
			resp.status(404);
			resp.write(JSON.stringify({ error: "No logs found for this service" }));
			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 WorkerSchema = z.object({
	service: z.string(),
	address: z.string().url(),
	logs: z.optional(z.string()),
});

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;
		}
		const { service, address, logs: log } = result.data;
		const projectWorkers = workers.get(projectId) || [];
		if (!projectWorkers.includes(address)) {
			projectWorkers.push(address);
		}
		workers.set(projectId, projectWorkers);
		if (log) {
			const svcLogs: Map<string, string> = logs.get(projectId) || new Map();
			svcLogs.set(service, log);
			logs.set(projectId, svcLogs);
		}
		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();
	}
};

const handleReload: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);
		const projectWorkers = workers.get(projectId) || [];
		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;
		}
		if (projectWorkers.length === 0) {
			resp.status(404);
			resp.write(JSON.stringify({ error: "No workers registered for this project" }));
			return;
		}
		await Promise.all(
			projectWorkers.map(async (workerAddress) => {
				try {
					const updateEndpoint = `${workerAddress}/update`;
					await axios.post(updateEndpoint);
					// eslint-disable-next-line @typescript-eslint/no-explicit-any
				} catch (error: any) {
					console.log(`Failed to update worker ${workerAddress}: ${error.message || "Unknown error"}`);
				}
			}),
		);
		resp.status(200);
		resp.write(JSON.stringify({ success: true }));
	} catch (e) {
		console.log(e);
		resp.status(500);
		resp.write(JSON.stringify({ error: "Failed to reload workers" }));
	} finally {
		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();
};

async function start() {
	await db.$connect();
	const app = express();
	app.use(express.json());
	app.use(auth);
	app.post("/api/project/:projectId/saved", handleSave);
	app.get("/api/project/:projectId/saved/deploy", handleSavedGet("deploy"));
	app.get("/api/project/:projectId/saved/draft", handleSavedGet("draft"));
	app.post("/api/project/:projectId/deploy", handleDeploy);
	app.get("/api/project/:projectId/status", handleStatus);
	app.delete("/api/project/:projectId", handleDelete);
	app.get("/api/project", handleProjectAll);
	app.post("/api/project", handleProjectCreate);
	app.get("/api/project/:projectId/repos/github", handleGithubRepos);
	app.post("/api/project/:projectId/github-token", handleUpdateGithubToken);
	app.get("/api/project/:projectId/env", handleEnv);
	app.post("/api/project/:projectId/reload", handleReload);
	app.get("/api/project/:projectId/logs/:service", handleServiceLogs);
	app.use("/", express.static("../front/dist"));

	const api = express();
	api.use(express.json());
	api.post("/api/project/:projectId/workers", handleRegisterWorker);

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

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

start();
