const MessageModel = require('../model/message');
const UserModel = require('../model/user');
const ChatModel = require('../model/chat');
const fs = require('fs').promises;
const path = require('path');
const createFolderIsExist = require('../helpers/create-directory');
const DIR_FILES = process.env.DIR_FILES;
require('dotenv').config();

const listMessages = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const messages = await MessageModel.getList({ owner: userId }, req.query);
		return res.json({
			status: 'success',
			code: 200,
			data: messages,
		});
	} catch (e) {
		next(e);
	}
};

const removeMessage = async (req, res, next) => {
	try {
		const id = req.params.id;
		const userId = req.user.id;
		const userMessage = await MessageModel.remove(id, userId);
		await MessageModel.removeByFields(
			userId,
			userMessage.idTime,
			userMessage.companionId
		);
		if (userMessage.type !== 'text')
			await fs.unlink(path.join(DIR_FILES, userMessage.message));

		const isChat = await ChatModel.getByField(userMessage.companionId, userId);
		const isCompanionChat = await ChatModel.getByField(
			userId,
			userMessage.companionId
		);
		const { total } = await MessageModel.getList(
			{ owner: userId, companionId: userMessage.companionId },
			{}
		);
		const { total: Total } = await MessageModel.getList(
			{ owner: userMessage.companionId, companionId: userId },
			{}
		);
		await ChatModel.update(isChat._id, userId, {
			total: total,
			seen: total - isChat.seen > 0 ? isChat.seen : total,
			watched: false,
		});
		await ChatModel.update(isCompanionChat._id, userMessage.companionId, {
			total: Total,
			seen: Total - isCompanionChat.seen > 0 ? isCompanionChat.seen : Total,
			watched: true,
		});
		return res.json({
			status: 'success',
			code: 200,
			data: {},
		});
	} catch (e) {
		next(e);
	}
};

const listMessagesById = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const companionId = req.params.companionId;
		const messages = await MessageModel.getList(
			{ owner: userId, companionId },
			{}
		);
		return res.json({
			status: 'success',
			code: 200,
			data: messages,
		});
	} catch (e) {
		next(e);
	}
};

const sentMessage = async (req, res, next) => {
	try {
		const { id, message } = req.body;
		const idTime = Math.round(Date.now() / 1000);
		const user = req.user;
		const userId = user.id;
		const companion = await UserModel.findById(id);
		const isChat = await ChatModel.getByField(id, userId);
		const isCompanionChat = await ChatModel.getByField(userId, id);
		const { name, lastName, avatarUrl, color, number } = user;

		if (companion && isChat && isCompanionChat) {
			const newMessage = await MessageModel.add({
				message,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type: 'text',
				idTime,
				companionIdFlow: userId,
				companionId: id,
				owner: userId,
			});
			await MessageModel.add({
				message,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type: 'text',
				idTime,
				companionIdFlow: userId,
				companionId: userId,
				owner: id,
			});
			const { total } = await MessageModel.getList(
				{ owner: userId, companionId: id },
				{}
			);
			await ChatModel.update(isChat._id, userId, {
				total,
				seen: total,
				watched: false,
				lastMessage: message,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			const { total: Total } = await MessageModel.getList(
				{ owner: id, companionId: userId },
				{}
			);
			await ChatModel.update(isCompanionChat._id, id, {
				total: Total,
				lastMessage: message,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			return res.status(201).json({
				status: 'success',
				code: 201,
				data: newMessage,
			});
		}
	} catch (e) {
		next(e);
	}
};

const imageMessage = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const id = req.params.companionId;
		const idTime = Math.round(Date.now() / 1000);
		const isChat = await ChatModel.getByField(id, userId);
		const isCompanionChat = await ChatModel.getByField(userId, id);
		const originalName = req.file.originalname;
		const pathToFile = req.file.path;
		const newNameImg = `${Math.round(Date.now() / 1000)}${originalName}`;
		const fullType = req.file.mimetype;
		await createFolderIsExist(path.join(DIR_FILES, userId));
		await fs.rename(pathToFile, path.join(DIR_FILES, userId, newNameImg));
		const imgUrl = path.normalize(path.join(userId, newNameImg));
		if (isChat && isCompanionChat && imgUrl) {
			const { name, lastName, avatarUrl, color, number } = req.user;
			const newMessage = await MessageModel.add({
				message: imgUrl,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type: 'image',
				fullType,
				idTime,
				companionIdFlow: userId,
				companionId: id,
				owner: userId,
			});
			await MessageModel.add({
				message: imgUrl,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type: 'image',
				fullType,
				idTime,
				companionIdFlow: userId,
				companionId: userId,
				owner: id,
			});
			const { total } = await MessageModel.getList(
				{ owner: userId, companionId: id },
				{}
			);
			await ChatModel.update(isChat._id, userId, {
				total,
				seen: total,
				watched: false,
				lastMessage: imgUrl,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			const { total: Total } = await MessageModel.getList(
				{ owner: id, companionId: userId },
				{}
			);
			await ChatModel.update(isCompanionChat._id, id, {
				total: Total,
				lastMessage: imgUrl,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			return res.status(201).json({
				status: 'success',
				code: 201,
				data: newMessage,
			});
		}
	} catch (e) {
		next(e);
	}
};

const audioMessage = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const id = req.params.companionId;
		const idTime = Math.round(Date.now() / 1000);
		const isChat = await ChatModel.getByField(id, userId);
		const isCompanionChat = await ChatModel.getByField(userId, id);
		const originalName = req.file.originalname;
		const pathToFile = req.file.path;
		const newNameAudio = `${Math.round(Date.now() / 1000)}${originalName}`;
		const fullType = req.file.mimetype;
		await createFolderIsExist(path.join(DIR_FILES, userId));
		await fs.rename(pathToFile, path.join(DIR_FILES, userId, newNameAudio));
		const audioUrl = path.normalize(path.join(userId, newNameAudio));
		if (isChat && isCompanionChat && audioUrl) {
			const { name, lastName, avatarUrl, color, number } = req.user;
			const newMessage = await MessageModel.add({
				message: audioUrl,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type: 'audio',
				fullType,
				idTime,
				companionIdFlow: userId,
				companionId: id,
				owner: userId,
			});
			await MessageModel.add({
				message: audioUrl,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type: 'audio',
				fullType,
				idTime,
				companionIdFlow: userId,
				companionId: userId,
				owner: id,
			});
			const { total } = await MessageModel.getList(
				{ owner: userId, companionId: id },
				{}
			);
			await ChatModel.update(isChat._id, userId, {
				total,
				seen: total,
				watched: false,
				lastMessage: audioUrl,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			const { total: Total } = await MessageModel.getList(
				{ owner: id, companionId: userId },
				{}
			);
			await ChatModel.update(isCompanionChat._id, id, {
				total: Total,
				lastMessage: audioUrl,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			return res.status(201).json({
				status: 'success',
				code: 201,
				data: newMessage,
			});
		}
	} catch (e) {
		next(e);
	}
};

const videoMessage = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const id = req.params.companionId;
		const idTime = Math.round(Date.now() / 1000);
		const isChat = await ChatModel.getByField(id, userId);
		const isCompanionChat = await ChatModel.getByField(userId, id);
		const originalName = req.file.originalname;
		const pathToFile = req.file.path;
		const newNameVideo = `${Math.round(Date.now() / 1000)}${originalName}`;
		const fullType = req.file.mimetype;
		await createFolderIsExist(path.join(DIR_FILES, userId));
		await fs.rename(pathToFile, path.join(DIR_FILES, userId, newNameVideo));
		const videoUrl = path.normalize(path.join(userId, newNameVideo));
		if (isChat && isCompanionChat && videoUrl) {
			const { name, lastName, avatarUrl, color, number } = req.user;
			const newMessage = await MessageModel.add({
				message: videoUrl,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type: 'video',
				fullType,
				idTime,
				companionIdFlow: userId,
				companionId: id,
				owner: userId,
			});
			await MessageModel.add({
				message: videoUrl,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type: 'video',
				fullType,
				idTime,
				companionIdFlow: userId,
				companionId: userId,
				owner: id,
			});
			const { total } = await MessageModel.getList(
				{ owner: userId, companionId: id },
				{}
			);
			await ChatModel.update(isChat._id, userId, {
				total,
				seen: total,
				watched: false,
				lastMessage: videoUrl,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			const { total: Total } = await MessageModel.getList(
				{ owner: id, companionId: userId },
				{}
			);
			await ChatModel.update(isCompanionChat._id, id, {
				total: Total,
				lastMessage: videoUrl,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			return res.status(201).json({
				status: 'success',
				code: 201,
				data: newMessage,
			});
		}
	} catch (e) {
		next(e);
	}
};

const fileMessage = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const id = req.params.companionId;
		const idTime = Math.round(Date.now() / 1000);
		const isChat = await ChatModel.getByField(id, userId);
		const isCompanionChat = await ChatModel.getByField(userId, id);
		const originalName = req.file.originalname;
		const pathToFile = req.file.path;
		const fullType = req.file.mimetype;
		let type;
		switch (fullType) {
			case 'application/pdf':
				type = 'pdf';
				break;
			case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
				type = 'docx';
				break;
			case 'application/octet-stream':
				type = 'docx';
				break;
			default:
				break;
		}
		const newNameFile = `${Math.round(Date.now() / 1000)}file.${type}`;
		await createFolderIsExist(path.join(DIR_FILES, userId));
		await fs.rename(pathToFile, path.join(DIR_FILES, userId, newNameFile));
		const fileUrl = path.normalize(path.join(userId, newNameFile));
		if (isChat && isCompanionChat && fileUrl) {
			const { name, lastName, avatarUrl, color, number } = req.user;
			const newMessage = await MessageModel.add({
				message: fileUrl,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type,
				fullType,
				idTime,
				companionIdFlow: userId,
				companionId: id,
				owner: userId,
			});
			await MessageModel.add({
				message: fileUrl,
				name,
				lastName,
				avatarUrl,
				color,
				number,
				type,
				fullType,
				idTime,
				companionIdFlow: userId,
				companionId: userId,
				owner: id,
			});
			const { total } = await MessageModel.getList(
				{ owner: userId, companionId: id },
				{}
			);
			await ChatModel.update(isChat._id, userId, {
				total,
				seen: total,
				watched: false,
				lastMessage: fileUrl,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			const { total: Total } = await MessageModel.getList(
				{ owner: id, companionId: userId },
				{}
			);
			await ChatModel.update(isCompanionChat._id, id, {
				total: Total,
				lastMessage: fileUrl,
				lastMessageCreatedAt: newMessage.createdAt,
			});
			return res.status(201).json({
				status: 'success',
				code: 201,
				data: newMessage,
			});
		}
	} catch (e) {
		next(e);
	}
};

module.exports = {
	listMessages,
	removeMessage,
	listMessagesById,
	sentMessage,
	imageMessage,
	audioMessage,
	videoMessage,
	fileMessage,
};
