import { Request, Response } from 'express';
import db, { handlePrismaError } from '../../../../handlers/db.js'; // Database
import log from '../../../../handlers/log.js';
import { parseDynamicSortBy } from '../../../../helpers/prisma_helpers.js';
import { schema_get, schema_post, schema_patch, schema_del } from './user_schema.js';

// MARK: GET user
async function get(req: Request, res: Response) {
	const { error, value } = schema_get.validate(req.query);
	if (error) {
		log.api?.debug('GET user Error:', req.query, value, error.details[0].message);
		res.status(400).json({ status: 'ERROR', errorcode: 'VALIDATION_ERROR', message: error.details[0].message });
	} else {
		log.api?.debug('GET user Success:', req.query, value);

		if (value.search !== undefined || value.id !== undefined) {
			// if search or get by id
			await db
				.$transaction([
					// Same query for count and findMany
					db.user.count({
						where: {
							OR: [{ id: value.id }, { name: { search: value.search } }]
						},
						orderBy: parseDynamicSortBy(value.sort.toString(), value.order.toString()),
						skip: value.skip,
						take: value.take
					}),
					db.user.findMany({
						where: {
							OR: [{ id: value.id }, { name: { search: value.search } }]
						},
						orderBy: parseDynamicSortBy(value.sort.toString(), value.order.toString()),
						skip: value.skip,
						take: value.take
					})
				])
				.then(([count, result]) => {
					if (result.length !== 0) {
						result.forEach((element: { id: number; name: string; code: string | null | boolean }) => {
							// code-> true if code is set
							element.code = !(element.code === '' || element.code === null || element.code === undefined); // Check if nullish
						});
						res.status(200).json({ count, result });
					} else {
						res.status(404).json({ status: 'ERROR', errorcode: 'NOT_FOUND', message: 'Could not find specified user' });
					}
				})
				.catch((err) => {
					handlePrismaError(err, res, 'GET user');
				});
		} else {
			// get all
			await db
				.$transaction([
					// Same query for count and findMany
					db.user.count({
						orderBy: parseDynamicSortBy(value.sort.toString(), value.order.toString()),
						skip: value.skip,
						take: value.take
					}),
					db.user.findMany({
						orderBy: parseDynamicSortBy(value.sort.toString(), value.order.toString()),
						skip: value.skip,
						take: value.take
					})
				])
				.then(([count, result]) => {
					if (result.length !== 0) {
						result.forEach((element: { id: number; name: string; code: string | null | boolean }) => {
							// code-> true if code is set
							//log.api?.debug('"' + element.code + '"');
							//log.api?.debug(!(element.code === ''), !(element.code === null), !(element.code === undefined));
							element.code = !(element.code === '' || element.code === null || element.code === undefined); // Check if nullish
						});
						res.status(200).json({ count, result });
					} else {
						res.status(404).json({ status: 'ERROR', errorcode: 'NOT_FOUND', message: 'Could not find any users' });
					}
				})
				.catch((err) => {
					handlePrismaError(err, res, 'GET user');
				});
		}
	}
}

// MARK: CREATE user
async function post(req: Request, res: Response) {
	const { error, value } = schema_post.validate(req.body);
	if (error) {
		log.api?.debug('POST user Error:', req.body, value, error.details[0].message);
		res.status(400).json({ status: 'ERROR', errorcode: 'VALIDATION_ERROR', message: error.details[0].message });
	} else {
		log.api?.debug('POST user Success:', req.body, value);
		await db.user
			.create({
				data: {
					name: value.name,
					email: value.email,
					code: value.code === '0000' ? null : value.code
				},
				select: {
					id: true
				}
			})
			.then((result) => {
				res.status(201).json({ status: 'CREATED', message: 'Successfully created user', id: result.id });
			})
			.catch((err) => {
				handlePrismaError(err, res, 'POST user');
			});
	}
}

// MARK: UPDATE user
async function patch(req: Request, res: Response) {
	const { error, value } = schema_patch.validate(req.body);
	if (error) {
		log.api?.debug('PATCH user Error:', req.body, value, error.details[0].message);
		res.status(400).json({ status: 'ERROR', errorcode: 'VALIDATION_ERROR', message: error.details[0].message });
	} else {
		log.api?.debug('PATCH user Success:', req.body, value);
		await db.user
			.update({
				where: {
					id: value.id
				},
				data: {
					name: value.name,
					email: value.email,
					code: value.code === '0000' ? null : value.code
				},
				select: {
					id: true
				}
			})
			.then((result) => {
				res.status(200).json({ status: 'UPDATED', message: 'Successfully updated user', id: result.id });
			})
			.catch((err) => {
				handlePrismaError(err, res, 'PATCH user');
			});
	}
}

// MARK: DELETE user
async function del(req: Request, res: Response) {
	const { error, value } = schema_del.validate(req.body);
	if (error) {
		log.api?.debug('DEL user Error:', req.body, value, error.details[0].message);
		res.status(400).json({ status: 'ERROR', errorcode: 'VALIDATION_ERROR', message: error.details[0].message });
	} else {
		log.api?.debug('DEL user Success:', req.body, value);
		await db.user
			.delete({
				where: {
					id: value.id
				}
			})
			.then((result) => {
				res.status(200).json({ status: 'DELETED', message: 'Successfully deleted user', id: result.id });
			})
			.catch((err) => {
				handlePrismaError(err, res, 'DEL user');
			});
	}
}

export default { get, post, patch, del };
