import { Request, Response, NextFunction } from "express";
import fs from "fs";
import path from "path";
import formidable from "formidable";
import sharp from "sharp";
import _ from "lodash";

import { executeQuery } from "../lib/db";
import { getImagePathBase, getFullSuitPathBase, isLinuxServer } from "~/functions/isLinuxServer";
import svcCore from "~/services/core";

import cache from "~/functions/cache";

function getBasePath() {
	return isLinuxServer() ? "/var/www/html/armory/api/" : "g:\\websites\\armory-vite\\api\\";
}

async function parseFormFields(req) {
	const basePath = getBasePath();
	const formToParse = new formidable.IncomingForm();

	formToParse.uploadDir = path.join(basePath, `./temp/`);

	const form = await new Promise(function (resolve, reject) {
		formToParse.parse(req, async function (err, fields, files) {
			if (err) {
				reject(`UNABLE TO PARSE THE FORM!\n\n${err}`);
			}

			resolve({
				fields,
				files,
			});
		});
	});

	return form;
}

// ITEMS
export async function itemPhotosUpload(req: Request) {
	const form = await parseFormFields(req);
	const folderName = getImagePathBase(form.fields.itemID);
	const basePath = getBasePath();

	for (let fileCounter = 0; fileCounter < form.fields.fileCount; fileCounter++) {
		const thisFile = form.files[`file${fileCounter}`];

		const oldpath = thisFile.filepath;

		let basepath = `${basePath}\\static\\photos\\items\\${form.fields.itemID}`;
		let largepath = `${basepath}\\large\\${thisFile.originalFilename}`;
		let thumbpath = `${basepath}\\thumb\\${thisFile.originalFilename}`;

		if (isLinuxServer() === true) {
			basepath = basePath + `/static/photos/items/${form.fields.itemID}`;
			largepath = basepath + "/large/" + thisFile.originalFilename;
			thumbpath = basepath + "/thumb/" + thisFile.originalFilename;
		}

		// create folder if it is first upload
		try {
			if (!fs.existsSync(folderName)) {
				fs.mkdirSync(folderName);
				fs.mkdirSync(folderName + "/thumb");
				fs.mkdirSync(folderName + "/large");
			}
		} catch (err) {
			console.error(err);
		}

		// move to the main folder
		fs.renameSync(oldpath, largepath);

		// resize and create a thumbnail
		await new Promise(function (resolve, reject) {
			sharp(largepath)
				.resize(480, 270)
				.toFile(thumbpath)
				.then(() => {
					resolve();
				});
		});

		await executeQuery({
			query: `
				insert into item_photos(
					itemID, filename
				) values (
					${form.fields.itemID}, '${thisFile.originalFilename}'
				)
			`,
		});
	}

	cache.del(`itemsPhotos_${form.fields.itemID}`);
	// categorized now; wipe out all cache
	cache.del(`itemsList_0`);
	cache.del(`itemsList_1`);
	cache.del(`itemsList_2`);
	cache.del(`itemsList_3`);
	cache.del(`itemsList_4`);

	return "success";
}

// ITEM PHOTOS REORDERING
export async function itemPhotosReorder(list) {
	await _.forEach(list, (photo) => {
		const sql = `
			update	item_photos
			set		sortOrder=${photo.sortOrder}
			where	itemID=${photo.itemID}
					and filename='${photo.filename}'
		`;

		executeQuery({ query: sql });
	});

	// force cache busting
	cache.del(`itemsPhotos_${list[0].itemID}`);
	cache.del(`itemsList`);

	return "success";
}

// FULL SUITS; ONE PHOTO ONLY
export async function fullSuitPhotoUpload(req: Request) {
	const form = await parseFormFields(req);
	const currentPath = getBasePath();
	const fullsuitID = form.fields.fullsuitID;
	const photo = form.files.filename;
	const oldpath = photo.filepath;

	const basepath = isLinuxServer()
		? `${currentPath}/static/photos/fullsuits/${fullsuitID}/`
		: `${currentPath}\\static\\photos\\fullsuits\\${fullsuitID}\\`;

	// create folder if it is first upload
	try {
		if (!fs.existsSync(basepath)) {
			fs.mkdirSync(basepath);
		}
	} catch (err) {
		console.error(err);
	}

	// move to the main folder
	fs.renameSync(oldpath, `${basepath}large.jpg`);

	// resize and create a thumbnail
	await new Promise(function (resolve) {
		sharp(`${basepath}large.jpg`)
			.resize(63, 112)
			.toFile(`${basepath}thumb.jpg`)
			.then(() => {
				resolve();
			});
	});

	await svcCore.patch({
		table: "fullsuit",
		whereClause: `fullsuitID=${fullsuitID}`,
		patchBody: [
			{
				col: "hasPhoto",
				type: "integer",
				value: 1,
			},
		],
	});

	return "success";
}
