import {
	AdminMessage,
	ConnectedAircraft,
	getPublicUser,
	MissionLog,
	Prisma,
	prisma,
} from "@repo/db";
import { Router } from "express";
import { io } from "../index";

const router: Router = Router();

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

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

// Update a connectedAircraft by ID
router.patch("/:id", async (req, res) => {
	const { id } = req.params;
	const aircraftUpdate = req.body as Prisma.ConnectedAircraftUpdateInput;
	try {
		const oldConnectedAircraft = await prisma.connectedAircraft.findUnique({
			where: { id: Number(id) },
			include: {
				Station: true,
				User: true,
			},
		});
		const updatedConnectedAircraft = await prisma.connectedAircraft.update({
			where: { id: Number(id) },
			data: {
				...aircraftUpdate,
			},
		});

		const mission = await prisma.mission.findFirst({
			where: {
				state: "running",
				missionStationIds: {
					has: updatedConnectedAircraft.stationId,
				},
			},
		});
		if (
			mission &&
			aircraftUpdate.fmsStatus &&
			oldConnectedAircraft &&
			updatedConnectedAircraft &&
			oldConnectedAircraft.fmsStatus !== updatedConnectedAircraft.fmsStatus
		) {
			const newMissionLog = mission.missionLog as any as MissionLog[];
			newMissionLog.push({
				type: "station-log",
				auto: true,
				data: {
					oldFMSstatus: oldConnectedAircraft.fmsStatus,
					newFMSstatus: updatedConnectedAircraft.fmsStatus,
					station: oldConnectedAircraft.Station,
					stationId: updatedConnectedAircraft.stationId,
					user: getPublicUser(oldConnectedAircraft.User),
				},
				timeStamp: new Date().toISOString(),
			});
			await prisma.mission.update({
				where: { id: mission.id },
				data: {
					missionLog: newMissionLog as any,
				},
			});
		}

		res.json(updatedConnectedAircraft);
		// When change is only the estimated logout time, we don't need to emit an event
		if (Object.keys(aircraftUpdate).length === 1 && aircraftUpdate.esimatedLogoutTime) return;
		io.to("dispatchers").emit("update-connectedAircraft", updatedConnectedAircraft);

		io.to(`user:${updatedConnectedAircraft.userId}`).emit(
			"aircraft-update",
			updatedConnectedAircraft,
		);
	} catch (error) {
		console.error(error);
		res.status(500).json({ error: "Failed to update connectedAircraft" });
	}
});

// Kick a connectedAircraft by ID
router.delete("/:id", async (req, res) => {
	const { id } = req.params;
	const bann = req.body?.bann as boolean;

	const requiredPermission = bann ? "ADMIN_USER" : "ADMIN_KICK";

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

	if (!req.user.permissions.includes(requiredPermission)) {
		res.status(403).json({ error: "Forbidden" });
		return;
	}

	try {
		const aircraft = await prisma.connectedAircraft.update({
			where: { id: Number(id) },
			data: { logoutTime: new Date() },
			include: bann ? { User: true } : undefined,
		});

		if (!aircraft) {
			res.status(404).json({ error: "ConnectedAircraft not found" });
			return;
		}

		const status = bann ? "ban" : "kick";

		io.to(`user:${aircraft.userId}`).emit("notification", {
			type: "admin-message",
			message: "Verbindung durch einen Administrator getrennt",
			status,
			data: { admin: getPublicUser(req.user) },
		} as AdminMessage);

		io.in(`user:${aircraft.userId}`).disconnectSockets(true);

		if (bann) {
			await prisma.user.update({
				where: { id: aircraft.userId },
				data: {
					permissions: {
						set: req.user.permissions.filter((p) => p !== "PILOT"),
					},
				},
			});
		}

		res.status(204).send();
	} catch (error) {
		console.error(error);
		res.status(500).json({ error: "Failed to disconnect pilot" });
	}
});

export default router;
