import { desc, eq, sql } from "drizzle-orm";
import { Router } from "express";
import z from "zod";
import { db } from "../db/db.controller.js";
import {
	type NewOpendockArticleSetup,
	opendockArticleSetup,
} from "../db/schema/opendock_articleSetup.js";
import { opendockDockSetup } from "../db/schema/opendock_docks.js";
import { prodQuery } from "../prodSql/prodSqlQuery.controller.js";
import {
	type SqlQuery,
	sqlQuerySelector,
} from "../prodSql/prodSqlQuerySelector.utils.js";
import { apiReturn } from "../utils/returnHelper.utils.js";
import { tryCatch } from "../utils/trycatch.utils.js";

const r = Router();

const newArticleLink = z.object({
	av: z.number().int(),
	description: z.string(),
	customer: z.string().min(1).max(32),
	customerDescription: z.string().min(2).max(100),
	loadType: z
		.enum(["drop", "live"])
		.optional()
		.describe("What roles are available to use."),
	dock: z
		//.record(z.string(), z.unknown())
		.string()
		.optional()
		.describe(
			"This allows us to add extra fields to the data to parse against",
		),
});

const newDockLink = z.object({
	name: z.string(),
	dockID: z.string(),
});

r.post("/", async (req, res) => {
	try {
		const validated = newArticleLink.parse(req.body) as NewOpendockArticleSetup;

		const newLink = await db
			.insert(opendockArticleSetup)
			.values({
				av: validated.av,
				description: validated.description,
				customer: validated.customer,
				customerDescription: validated.customerDescription,
				loadType: validated.loadType,
				dock: validated.dock,
				add_user: req.user?.username ?? "lst_user",
			})
			.returning();

		return apiReturn(res, {
			success: true,
			level: "info",
			module: "opendock",
			subModule: "articleCheck",
			message: `${validated.av} was just added `,
			data: newLink as any,
			status: 200,
		});
	} catch (err) {
		if (err instanceof z.ZodError) {
			const flattened = z.flattenError(err);
			// return res.status(400).json({
			// 	error: "Validation failed",
			// 	details: flattened,
			// });

			return apiReturn(res, {
				success: false,
				level: "error", //connect.success ? "info" : "error",
				module: "opendock",
				subModule: "articleCheck",
				message: "Validation failed",
				data: [flattened.fieldErrors],
				status: 400, //connect.success ? 200 : 400,
			});
		}

		return apiReturn(res, {
			success: false,
			level: "error", //connect.success ? "info" : "error",
			module: "opendock",
			subModule: "articleCheck",
			message: "Internal Server Error adding article link",
			data: [err],
			status: 400, //connect.success ? 200 : 400,
		});
	}
});

r.patch("/:id", async (req, res) => {
	const { id } = req.params;
	const updates: Record<string, unknown | null> = {};

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

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

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

	const updatedSetting = await db
		.update(opendockArticleSetup)
		.set(updates)
		.where(eq(opendockArticleSetup.id, id))
		.returning();

	return apiReturn(res, {
		success: true,
		level: "info",
		module: "opendock",
		subModule: "articleCheck",
		message: `${updatedSetting[0]?.av} was just updated. `,
		data: updatedSetting,
		status: 200,
	});
});

r.delete("/:id", async (req, res) => {
	const { id } = req.params;

	const removeLink = await db
		.delete(opendockArticleSetup)
		.where(eq(opendockArticleSetup.id, id))
		.returning();
	return apiReturn(res, {
		success: true,
		level: "info", //connect.success ? "info" : "error",
		module: "opendock",
		subModule: "articleCheck",
		message: "Article link was deleted",
		data: removeLink,
		status: 200, //connect.success ? 200 : 400,
	});
});

r.get("/", async (_, res) => {
	const { data } = await tryCatch(
		db
			.select()
			.from(opendockArticleSetup)
			.orderBy(desc(opendockArticleSetup.customer))
			.limit(1500),
	);

	return apiReturn(res, {
		success: true,
		level: "info",
		module: "opendock",
		subModule: "articleCheck",
		message: `All links`,
		data: data ?? [],
		status: 200,
	});
});

r.get("/customers/:av", async (req, res) => {
	const { av } = req.params;

	const avSQLQuery = sqlQuerySelector(`opendock.addressLink`) as SqlQuery;

	if (!avSQLQuery.success) {
		return apiReturn(res, {
			success: true,
			level: "error",
			module: "opendock",
			subModule: "articleCheck",
			message: avSQLQuery.message,
			data: [],
			status: 200,
		});
	}
	const { data } = await tryCatch(
		prodQuery(
			avSQLQuery.query.replace("[articleCheck]", av),
			"openDock addressLink",
		),
	);

	return apiReturn(res, {
		success: true,
		level: "info",
		module: "opendock",
		subModule: "articleCheck",
		message: `All customers linked to av: ${av}`,
		data: data?.data ?? ([] as any),
		status: 200,
	});
});

r.post("/dock", async (req, res) => {
	try {
		const validated = newDockLink.parse(req.body) as any;

		const newLink = await db
			.insert(opendockDockSetup)
			.values({
				name: validated.name,
				dockID: validated.dockID,
				add_user: req.user?.username ?? "lst_user",
			})
			.returning();

		return apiReturn(res, {
			success: true,
			level: "info",
			module: "opendock",
			subModule: "articleCheck",
			message: `${validated.name} was just added `,
			data: newLink as any,
			status: 200,
		});
	} catch (err) {
		if (err instanceof z.ZodError) {
			const flattened = z.flattenError(err);
			// return res.status(400).json({
			// 	error: "Validation failed",
			// 	details: flattened,
			// });

			return apiReturn(res, {
				success: false,
				level: "error", //connect.success ? "info" : "error",
				module: "opendock",
				subModule: "articleCheck",
				message: "Validation failed",
				data: [flattened.fieldErrors],
				status: 400, //connect.success ? 200 : 400,
			});
		}

		return apiReturn(res, {
			success: false,
			level: "error", //connect.success ? "info" : "error",
			module: "opendock",
			subModule: "articleCheck",
			message: "Internal Server Error adding dock link",
			data: [err],
			status: 400, //connect.success ? 200 : 400,
		});
	}
});

r.get("/dock", async (_, res) => {
	const { data } = await tryCatch(
		db
			.select()
			.from(opendockDockSetup)
			.orderBy(desc(opendockDockSetup.name))
			.limit(1500),
	);

	return apiReturn(res, {
		success: true,
		level: "info",
		module: "opendock",
		subModule: "articleCheck",
		message: `All dock links`,
		data: data ?? [],
		status: 200,
	});
});

export default r;
