import type { Response } from "express";
import { createLogger } from "../logger/logger.controller.js";

export interface ReturnHelper<T = unknown[]> {
	success: boolean;
	module:
		| "system"
		| "ocp"
		| "routes"
		| "datamart"
		| "utils"
		| "opendock"
		| "notification"
		| "email"
		| "purchase"
		| "tcp"
		| "logistics"
		| "admin"
		| "mobile"
		| "dockdoor"
		| "eom"
		| "dm";
	subModule: string;

	level: "info" | "error" | "debug" | "fatal" | "warn";
	message: string;
	room?: string;
	data?: T;
	notify?: boolean;
}

/**
 * This dose the return process and log at the same time, vs needing to log and return at the same time.
 * When to use.
 *  APIs
 *  actual returns and needing to stop.
 * Example Data
 * success:true
 * module: system | printers | etc
 * submodule: sql connection | printer test | etc
 * level "info" | "error" | "debug" | "fatal"
 * message: "short description of the return"
 * data: [] the data that will be passed back
 * notify: false by default this is to send a notification to a users email to alert them of an issue.
 */
export const returnFunc = (data: ReturnHelper) => {
	const notify = data.notify ? data.notify : false;
	const room = data.room ?? data.room;
	const log = createLogger({ module: data.module, subModule: data.subModule });
	// handle the logging part
	switch (data.level) {
		case "info":
			log.info({ notify: notify, room }, data.message);
			break;
		case "error":
			log.error({ notify: notify, stack: data.data ?? [], room }, data.message);

			break;
		case "debug":
			log.debug({ notify: notify, stack: data.data ?? [], room }, data.message);
			break;
		case "fatal":
			log.fatal({ notify: notify, stack: data.data ?? [], room }, data.message);
	}

	// api section to return
	return {
		success: data.success,
		message: data.message,
		level: data.level,
		module: data.module,
		subModule: data.subModule,
		data: data.data || [],
	};
};

export function apiReturn(
	res: Response,
	opts: ReturnHelper & { status?: number },
	optional?: unknown, // leave this as unknown so we can pass an object or an array over.
): Response {
	const result = returnFunc(opts);
	const code = opts.status ?? (opts.success ? 200 : 500);
	if (optional) {
		return res
			.status(code ?? (opts.success ? 200 : 500))
			.json({ ...result, optional });
	}
	return res.status(code ?? (opts.success ? 200 : 500)).json(result);
}
