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

const db = new PrismaClient();

// Map to store worker addresses by project ID
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,
			}),
		);
	} 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();
	}
};

const handleSavedGet: express.Handler = 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);
		} else {
			resp.status(200);
			resp.header("content-type", "application/json");
			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;
		}
		const r = await axios.request({
			url: `http://appmanager.hgrz-appmanager.svc.cluster.local/api/instance/${p.instanceId}/remove`,
			method: "post",
		});
		if (r.status === 200) {
			await db.project.delete({
				where: {
					id: projectId,
				},
			});
		}
		resp.status(200);
	} catch (e) {
		console.log(e);
		resp.status(500);
	} finally {
		resp.end();
	}
};

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,
			},
		});
		if (p === null) {
			resp.status(404);
			return;
		}
		await db.project.update({
			where: {
				id: projectId,
			},
			data: {
				draft: state,
			},
		});
		let r: { status: number; data: { id: string; deployKey: string } };
		if (p.instanceId == null) {
			r = await axios.request({
				url: "http://appmanager.hgrz-appmanager.svc.cluster.local/api/dodo-app",
				method: "post",
				data: {
					config: req.body.config,
				},
			});
			if (r.status === 200) {
				await db.project.update({
					where: {
						id: projectId,
					},
					data: {
						state,
						draft: null,
						instanceId: r.data.id,
						deployKey: r.data.deployKey,
					},
				});

				if (p.githubToken && r.data.deployKey) {
					const stateObj = JSON.parse(JSON.parse(state.toString()));
					const githubNodes = stateObj.nodes.filter(
						// eslint-disable-next-line @typescript-eslint/no-explicit-any
						(n: any) => n.type === "github" && n.data?.repository?.id,
					);

					const github = new GithubClient(p.githubToken);
					for (const node of githubNodes) {
						try {
							await github.addDeployKey(node.data.repository.sshURL, r.data.deployKey);
						} catch (error) {
							console.error(
								`Failed to add deploy key to repository ${node.data.repository.sshURL}:`,
								error,
							);
						}
					}
				}
			}
		} else {
			r = await axios.request({
				url: `http://appmanager.hgrz-appmanager.svc.cluster.local/api/dodo-app/${p.instanceId}`,
				method: "put",
				data: {
					config: req.body.config,
				},
			});
			if (r.status === 200) {
				await db.project.update({
					where: {
						id: projectId,
					},
					data: {
						state,
						draft: null,
					},
				});
			}
		}
	} 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;
		}
		const r = await axios.request({
			url: `http://appmanager.hgrz-appmanager.svc.cluster.local/api/instance/${p.instanceId}/status`,
			method: "get",
		});
		resp.status(r.status);
		if (r.status === 200) {
			resp.write(JSON.stringify(r.data));
		}
	} 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,
			}),
		);
	} 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;

		// Get existing workers or initialize empty array
		const projectWorkers = workers.get(projectId) || [];

		// Add new worker if not already present
		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");
	if (userId === undefined) {
		resp.status(401);
		resp.write("Unauthorized");
		resp.end();
		return;
	}
	resp.locals.userId = userId;
	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", handleSavedGet);
	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);

	// Start both servers
	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();
