import { createLogger } from "../logger/logger.controller.js";
import { delay } from "../utils/delay.utils.js";
import { db } from "./db.controller.js";

type DBCount = {
	count: string;
};

const tableMap = {
	logs: "logs",
	jobs: "job_audit_log",
	opendockApt: "opendock_apt",
} as const;

type CleanupTable = keyof typeof tableMap;

/**
 * We will clean up the db based on age.
 * @param name database to run the cleanup on
 * @param daysToKeep optional default will be 90 days
 */
export const dbCleanup = async (name: CleanupTable, daysToKeep?: number) => {
	const log = createLogger({ module: "db", subModule: "cleanup" });
	// TODO: send backup of this to another server, via post or something maybe have to reduce the limit but well tackle that later.

	if (!daysToKeep) {
		daysToKeep = 90;
	}
	const limit = 1000;
	const delayTime = 250;
	let rowsDeleted: number;

	const dbCount = (await db.execute(
		`select count(*) from public.${tableMap[name]} WHERE created_at < NOW() - INTERVAL '${daysToKeep} days'`,
	)) as DBCount[];

	const loopCount = Math.ceil(
		parseInt(dbCount[0]?.count ?? `${limit}`, 10) / limit,
	);

	if (parseInt(dbCount[0]?.count ?? `${limit}`, 10) > 1) {
		log.info(
			`Table clean up for: ${name}, that are older than ${daysToKeep} day, will be removed, There is ${loopCount} loops to be completed, Approx time: ${((loopCount * delayTime) / 1000 / 60).toFixed(2)} min(s).`,
		);
	} else {
		log.info(`Table clean up for: ${name}, Currently has nothing to clean up.`);
		return;
	}

	do {
		// cleanup logs
		const deleted = await db.execute(`
            DELETE FROM public.${tableMap[name]}
            WHERE id IN (
                SELECT id
                FROM public.${tableMap[name]}
                WHERE created_at < NOW() - INTERVAL '${daysToKeep} days'
                ORDER BY created_at
                LIMIT ${limit}
            )
            RETURNING id;
        `);

		rowsDeleted = deleted.length;

		if (rowsDeleted > 0) {
			await delay(delayTime);
		}
	} while (rowsDeleted === limit);

	log.info(`Table clean up for: ${name}, Has completed.`);
};
