import axios from "axios";
import { eq, sql } from "drizzle-orm";
import type { Request, Response } from "express";
import { Router } from "express";
import https from "https";
import { db } from "../../../../pkg/db/db.js";
import { modules } from "../../../../pkg/db/schema/modules.js";
import { serverData } from "../../../../pkg/db/schema/servers.js";
import { createLogger } from "../../../../pkg/logger/logger.js";
import { tryCatch } from "../../../../pkg/utils/tryCatch.js";

const router = Router();

router.patch("/:module", async (req: Request, res: Response) => {
	const log = createLogger({ module: "admin", subModule: "update module" });

	// when a server is updated and is posted from localhost or 127.0.0.1 we also want to post it to the test server so we can see it from there, we want to insert with update on conflict.
	const module = req.params.module;
	const updates: Record<string, any> = {};

	if (req.body?.active !== undefined) {
		updates.active = req.body.active;
	}

	if (req.body?.icon !== undefined) {
		updates.icon = req.body.icon;
	}

	if (req.body?.link !== undefined) {
		updates.link = req.body.link;
	}

	updates.upd_user = req.user!.username || "lst_user";
	updates.upd_date = sql`NOW()`;

	try {
		if (Object.keys(updates).length > 0) {
			await db.update(modules).set(updates).where(eq(modules.name, module));
		}

		// if we pass updateAll:true then we want to update all servers this will help kill all bad stuff if we have it.

		if (req.body?.updateAll) {
			const { data: serverInfo, error: errorData } = await tryCatch(
				db.select().from(serverData),
			);

			if (errorData) {
				log.error(
					{ error: errorData },
					"There was an error getting the serverData",
				);
				return;
			}

			for (const s of serverInfo) {
				try {
					const url = s.plantToken.includes("test")
						? `https://${s.serverDNS}.alpla.net`
						: `https://${s.plantToken}prod.alpla.net`;
					const axiosInstance = axios.create({
						httpsAgent: new https.Agent({ rejectUnauthorized: false }),
						withCredentials: true,
					});

					const loginRes = (await axiosInstance.post(
						`${url}/lst/api/auth/sign-in/username`,
						{
							username: process.env.MAIN_SERVER_USERNAME,
							password: process.env.MAIN_SERVER_PASSWORD,
						},
						{
							headers: { "Content-Type": "application/json" },
						},
					)) as any;

					const setCookie = loginRes?.headers["set-cookie"][0];

					//console.log(setCookie.split(";")[0].replace("__Secure-", ""));

					if (!setCookie) {
						throw new Error("Did not receive a Set-Cookie header from login");
					}

					const { data, error } = await tryCatch(
						axios.patch(`${url}/lst/api/system/modules/${module}`, updates, {
							headers: {
								"Content-Type": "application/json",
								Cookie: setCookie.split(";")[0],
							},
							withCredentials: true,
						}),
					);

					if (error) {
						//console.log(error);
						log.error(
							{ stack: error },
							"There was an error updating the system",
						);
						return res.status(400).json({
							message: `${module} encountered an error updating on the servers`,
						});
					}
					log.info({ stack: data?.data }, "module was just updated.");

					return res
						.status(200)
						.json({ message: `${module} was just updated on all servers` });
				} catch (e) {
					log.error(
						{ error: e },
						`There was an error updating the module setting on ${s.name}`,
					);
					return res.status(400).json({
						message: `${module} encountered an error updating on the servers`,
					});
				}
			}
		} else {
			return res
				.status(200)
				.json({ message: `${module}, was just updated to this server only` });
		}
	} catch (error) {
		console.log(error);
		res.status(400).json({ message: "Error Server updated", error });
	}
});

export default router;
