import {
	getPublicUser,
	HpgValidationState,
	MissionAlertLog,
	MissionSdsLog,
	MissionStationLog,
	NotificationPayload,
	Prisma,
	prisma,
	User,
} from "@repo/db";
import { Router } from "express";
import { io } from "../index";
import { sendNtfyMission } from "modules/ntfy";
import { sendAlert } from "modules/mission";
import { userInfo } from "os";

const router: Router = Router();

// Get all missions
router.post("/", async (req, res) => {
	try {
		const filter = req.body?.filter || {};
		const missions = await prisma.mission.findMany({
			where: filter,
		});
		res.json(missions);
	} catch (error) {
		console.error(error);
		res.status(500).json({ error: "Failed to fetch missions" });
	}
});

// Get a single mission by ID
router.get("/:id", async (req, res) => {
	const { id } = req.params;
	try {
		const mission = await prisma.mission.findUnique({
			where: { id: Number(id) },
		});
		if (mission) {
			res.json(mission);
		} else {
			res.status(404).json({ error: "Mission not found" });
		}
	} catch (error) {
		console.error(error);
		res.status(500).json({ error: "Failed to fetch mission" });
	}
});

// Create a new mission
router.put("/", async (req, res) => {
	try {
		const startOfToday = new Date();
		startOfToday.setHours(0, 0, 0, 0);

		const missionsTodayCount = await prisma.mission.count({
			where: {
				createdAt: {
					gte: startOfToday,
				},
			},
		});

		const date = new Date();
		const year = date.getFullYear();
		const month = String(date.getMonth() + 1).padStart(2, "0"); // Months are zero-based
		const day = String(date.getDate()).padStart(2, "0");

		const publicId = `__${year}${month}${day}${missionsTodayCount ? missionsTodayCount + 1 : 1}`;
		const newMission = await prisma.mission.create({
			data: {
				...req.body,
				publicId,
			},
		});
		io.to("dispatchers").emit("new-mission", { newMission });
		res.status(201).json(newMission);
	} catch (error) {
		res.status(500).json({ error: "Failed to create mission" });
	}
});

// Update a mission by ID
router.patch("/:id", async (req, res) => {
	const { id } = req.params;
	try {
		const updatedMission = await prisma.mission.update({
			where: { id: Number(id) },
			data: req.body,
		});
		io.to("dispatchers").emit("update-mission", updatedMission);
		res.json(updatedMission);
	} catch (error) {
		console.error(error);
		res.status(500).json({ error: "Failed to update mission" });
	}
});

// Delete a mission by ID
router.delete("/:id", async (req, res) => {
	const { id } = req.params;
	try {
		await prisma.mission.delete({
			where: { id: Number(id) },
		});
		io.to("dispatchers").emit("delete-mission", id);
		res.status(204).send();
	} catch (error) {
		console.error(error);
		res.status(500).json({ error: "Failed to delete mission" });
	}
});

// Send mission

router.post("/:id/send-alert", async (req, res) => {
	const { id } = req.params;
	const { stationId, vehicleName } = req.body as {
		stationId?: number;
		vehicleName?: "ambulance" | "police" | "firebrigade";
	};

	if (!req.user) {
		res.status(401).json({ error: "Unauthorized" });
		return;
	}

	try {
		if (vehicleName) {
			const hpgAircrafts = await prisma.connectedAircraft.findMany({
				where: {
					stationId: Number(id),
					logoutTime: null,
					posH145active: true,
				},
			});

			const newMission = await prisma.mission.update({
				where: {
					id: Number(id),
				},
				data: {
					hpgAmbulanceState: vehicleName === "ambulance" ? "DISPATCHED" : undefined,
					hpgFireEngineState: vehicleName === "firebrigade" ? "DISPATCHED" : undefined,
					hpgPoliceState: vehicleName === "police" ? "DISPATCHED" : undefined,
					missionLog: {
						push: {
							type: "alert-log",
							auto: false,
							timeStamp: new Date().toISOString(),
							data: {
								vehicle: vehicleName,
								user: getPublicUser(req.user as User),
							},
						} as any,
					},
				},
			});
			hpgAircrafts.forEach((aircraft) => {
				io.to(`desktop:${aircraft.userId}`).emit("hpg-vehicle-update", {
					missionId: id,
					vehicleData: {
						ambulanceState: newMission.hpgAmbulanceState,
						fireEngineState: newMission.hpgFireEngineState,
						policeState: newMission.hpgPoliceState,
					},
				});
			});

			res.status(200).json({
				message: `Rettungsmittel disponiert (${hpgAircrafts.length} Nutzer)`,
			});
			io.to("dispatchers").emit("update-mission", newMission);
			return;
		}
		const { connectedAircrafts, mission } = await sendAlert(
			Number(id),
			{
				stationId,
			},
			req.user,
		);

		res.status(200).json({
			message: `Einsatz gesendet (${connectedAircrafts.length} Nutzer) `,
		});
		io.to("dispatchers").emit("update-mission", mission);
	} catch (error) {
		console.error(error);
		res.status(500).json({ error: "Failed to send mission" });
	}
});

router.post("/send-sds", async (req, res) => {
	const { sdsMessage, missionId } = req.body as {
		missionId?: number;
		sdsMessage: MissionSdsLog;
	};

	io.to(`station:${sdsMessage.data.stationId}`).emit("sds-message", sdsMessage);
	if (missionId) {
		const newMission = await prisma.mission.update({
			where: {
				id: Number(missionId),
			},
			data: {
				missionLog: {
					push: sdsMessage as any,
				},
			},
		});

		res.json({
			message: "SDS message sent",
			mission: newMission,
		});
		io.to("dispatchers").emit("update-mission", newMission);
	} else {
		res.json({
			message: "SDS message sent",
		});
	}
});

router.post("/:id/hpg-validation-result", async (req, res) => {
	try {
		const missionId = req.params.id;
		const result = req.body as {
			state: HpgValidationState;
			lat: number;
			lng: number;
			alertWhenValid?: boolean;
			userId?: number;
		};

		if (!result) return;

		const newMission = await prisma.mission.update({
			where: { id: Number(missionId) },
			data: {
				// save position of new mission
				addressLat: result.state === "POSITION_AMANDED" ? result.lat : undefined,
				addressLng: result.state === "POSITION_AMANDED" ? result.lng : undefined,
				hpgLocationLat: result.lat,
				hpgLocationLng: result.lng,
				hpgValidationState: result.state,
			},
		});
		io.to("dispatchers").emit("update-mission", newMission);

		const noActionRequired = result.state === "VALID";
		if (noActionRequired) {
			io.to(`user:${result.userId}`).emit("notification", {
				type: "hpg-validation",
				status: "success",
				message: `HPG Validierung erfolgreich`,
			} as NotificationPayload);

			if (result.alertWhenValid) {
				if (!req.user) return;
				sendAlert(Number(missionId), {}, req.user);
			}
		} else {
			io.to(`user:${result.userId}`).emit("notification", {
				type: "hpg-validation",
				status: "failed",
				message: result.state,
			} as NotificationPayload);
		}
		res.json({
			message: `HPG Validation result processed`,
		});
	} catch (error) {
		console.error("Error in HPG validation result:", error);
		res.status(500).json({ error: "Failed to process HPG validation result" });
		return;
	}
});

router.post("/:id/validate-hpg", async (req, res) => {
	try {
		const { id } = req.params;
		const config = req.body as
			| {
					alertWhenValid?: boolean;
			  }
			| undefined;
		const mission = await prisma.mission.findFirstOrThrow({
			where: {
				id: Number(id),
			},
		});

		const activeAircraftinMission = await prisma.connectedAircraft.findFirst({
			where: {
				stationId: {
					in: mission?.missionStationIds,
				},
				posH145active: true,
				logoutTime: null,
			},
			include: {
				Station: true,
			},
		});
		const user = await prisma.user.findFirst({
			where: {
				id: activeAircraftinMission?.userId,
			},
		});

		const clients = await io.in(`desktop:${activeAircraftinMission?.userId}`).fetchSockets();
		if (!clients.length) {
			res.status(400).json({
				error: `Keine Desktop Verbindung für ${user?.publicId} gefunden`,
			});
			return;
		}

		const newMission = await prisma.mission.update({
			where: {
				id: Number(id),
			},
			data: {
				hpgValidationState: "PENDING",
			},
		});
		io.to("dispatchers").emit("update-mission", newMission);

		res.json({
			message: "HPG validierung gestartet",
		});
		console.log(
			`HPG Validation for ${user?.publicId} (${mission?.hpgSelectedMissionString}) started`,
		);
		io.to(`desktop:${activeAircraftinMission?.userId}`).emit("hpg-validation", {
			missionId: parseInt(id),
			userId: req.user?.id,
			alertWhenValid: config?.alertWhenValid || false,
		});
	} catch (error) {
		console.error(error);
		res.json({ error: (error as Error).message || "Failed to validate HPG" });
	}
});

export default router;
