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 handleProjectCreate: express.Handler = async (req, resp) => {
	try {
		const { id } = await db.project.create({
			data: {
				userId: "gio", // req.get("x-forwarded-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: "gio", // req.get("x-forwarded-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"]),
			},
			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"]),
			},
			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,
			},
			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,
			},
			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,
				},
			});
			console.log(r);
			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(
						(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,
			},
			select: {
				instanceId: true,
			},
		});
		console.log(projectId, p);
		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 },
			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 },
			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 },
			select: {
				deployKey: true,
				githubToken: true,
			},
		});

		if (!project) {
			resp.status(404);
			resp.write(JSON.stringify({ error: "Project not found" }));
			return;
		}

		resp.status(200);
		resp.write(
			JSON.stringify({
				// TODO(gio): get from env or command line flags
				managerAddr: "http://10.42.0.239:8080",
				deployKey: project.deployKey,
				integrations: {
					github: !!project.githubToken,
				},
				networks: [
					{
						name: "Public",
						domain: "v1.dodo.cloud",
					},
					{
						name: "Private",
						domain: "p.v1.dodo.cloud",
					},
				],
			}),
		);
	} catch (error) {
		console.error("Error checking integrations:", error);
		resp.status(500);
		resp.write(JSON.stringify({ error: "Internal server error" }));
	} finally {
		resp.end();
	}
};

const WorkerSchema = z.object({
	address: z.string().url(),
});

const handleRegisterWorker: express.Handler = async (req, resp) => {
	try {
		const projectId = Number(req.params["projectId"]);

		const result = WorkerSchema.safeParse(req.body);
		console.log(result);
		if (!result.success) {
			resp.status(400);
			resp.write(
				JSON.stringify({
					error: "Invalid request data",
					details: result.error.format(),
				}),
			);
			return;
		}

		const { address } = 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);

		resp.status(200);
		resp.write(
			JSON.stringify({
				success: true,
				workers: projectWorkers,
			}),
		);
	} 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) || [];

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

async function start() {
	await db.$connect();
	const app = express();
	app.use(express.json());
	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/workers", handleRegisterWorker);
	app.post("/api/project/:projectId/reload", handleReload);
	app.use("/", express.static("../front/dist"));
	app.listen(env.DODO_PORT_WEB, () => {
		console.log("started");
	});
}

start();
