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

const listChats = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const { total, limit, page, chats } = await ChatModel.getList(
			userId,
			req.query
		);
		return res.json({
			status: 'success',
			code: 200,
			data: {
				total,
				limit,
				page,
				chats,
			},
		});
	} catch (e) {
		next(e);
	}
};

const startChat = async (req, res, next) => {
	try {
		const id = req.body.id;
		const user = req.user;
		const userId = user.id;
		const companion = await UserModel.findById(id);
		const isUser = await ChatModel.getByField(id, userId);
		const isCompanion = await ChatModel.getByField(userId, id);
		const {
			name,
			lastName,
			originalName,
			originalLastName,
			avatarUrl,
			avatarsArr,
			color,
			online,
			number,
		} = companion;
		const {
			name: Name,
			lastName: LastName,
			originalName: OriginalName,
			originalLastName: OriginalLastName,
			avatarUrl: AvatarUrl,
			avatarsArr: AvatarsArr,
			color: Color,
			online: Online,
			number: Number,
		} = user;
		if (companion && isUser && isCompanion) {
			await ChatModel.update(isUser._id, userId, {
				originalName,
				originalLastName,
				avatarUrl,
				avatarsArr,
				color,
				online,
				number,
			});
			await ChatModel.update(isCompanion._id, id, {
				originalName: OriginalName,
				originalLastName: OriginalLastName,
				avatarUrl: AvatarUrl,
				avatarsArr: AvatarsArr,
				color: Color,
				online: Online,
				number: Number,
			});
			const updatedChat = await ChatModel.getByField(id, userId);
			return res.status(200).json({
				status: 'success',
				code: 200,
				data: updatedChat,
			});
		}

		if (companion && !isUser && !isCompanion) {
			const newChat = await ChatModel.add({
				name,
				lastName,
				originalName,
				originalLastName,
				avatarUrl,
				avatarsArr,
				color,
				online,
				number,
				companionId: id,
				owner: userId,
			});
			await ChatModel.add({
				name: Name,
				lastName: LastName,
				originalName: OriginalName,
				originalLastName: originalLastName,
				avatarUrl: AvatarUrl,
				avatarsArr: AvatarsArr,
				color: Color,
				online: Online,
				number: Number,
				companionId: userId,
				owner: id,
			});
			return res.status(201).json({
				status: 'success',
				code: 201,
				data: newChat,
			});
		}
	} catch (e) {
		next(e);
	}
};

const removeChatForBoth = async (req, res, next) => {
	try {
		const companionId = req.params.id;
		const userId = req.user.id;
		const isUserChat = await ChatModel.getByField(companionId, userId);
		const isCompanionChat = await ChatModel.getByField(userId, companionId);
		if (isUserChat && isCompanionChat) {
			const deleteFile = async (type, message) => {
				if (type !== 'text') await fs.unlink(path.join(DIR_FILES, message));
			};
			const { messages } = await MessageModel.getList(
				{ owner: userId, companionId },
				{}
			);
			await messages.forEach(
				async ({ type, message }) => await deleteFile(type, message)
			);
			await MessageModel.removeAll(companionId, userId);
			await MessageModel.removeAll(userId, companionId);
			await ChatModel.remove(isUserChat._id, userId);
			await ChatModel.remove(isCompanionChat._id, companionId);
			return res.json({
				status: 'success',
				code: 200,
				data: {},
			});
		} else {
			return res.status(404).json({
				status: 'error',
				code: 404,
				data: 'Not Found',
			});
		}
	} catch (e) {
		next(e);
	}
};

const muteChat = async (req, res, next) => {
	try {
		const id = req.body.id;
		const userId = req.user.id;
		const isChat = await ChatModel.getByField(id, userId);
		if (isChat) {
			const { _id, mute } = isChat;
			await ChatModel.update(_id, userId, { mute: !mute });
			return res.status(200).json({
				status: 'success',
				code: 200,
				data: {},
			});
		}
	} catch (e) {
		next(e);
	}
};

const sortChat = async (req, res, next) => {
	try {
		const id = req.body.id;
		const userId = req.user.id;
		const isChat = await ChatModel.getByField(id, userId);
		if (isChat) {
			const { _id, sort } = isChat;
			await ChatModel.update(_id, userId, { sort: !sort });
			return res.status(200).json({
				status: 'success',
				code: 200,
				data: {},
			});
		}
	} catch (e) {
		next(e);
	}
};

const seenChat = async (req, res, next) => {
	try {
		const id = req.body.id;
		const userId = req.user.id;
		const isChat = await ChatModel.getByField(id, userId);
		const isCompanionChat = await ChatModel.getByField(userId, id);
		const isMessages = await MessageModel.getList(
			{ owner: userId, companionId: id },
			{}
		);
		if (isChat && isMessages && isCompanionChat) {
			const { total } = isMessages;
			await ChatModel.update(isChat._id, userId, {
				seen: total,
				watched: false,
			});
			await ChatModel.update(isCompanionChat._id, id, { watched: true });
			return res.status(200).json({
				status: 'success',
				code: 200,
				data: {},
			});
		}
	} catch (e) {
		next(e);
	}
};

const typingChat = async (req, res, next) => {
	try {
		const { id, typing } = req.body;
		const userId = req.user.id;
		const isCompanionChat = await ChatModel.getByField(userId, id);
		if (isCompanionChat) {
			await ChatModel.update(isCompanionChat._id, id, { typing });
			return res.status(200).json({
				status: 'success',
				code: 200,
				data: {},
			});
		}
	} catch (e) {
		next(e);
	}
};

const getChatById = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const companionId = req.params.companionId;
		const isChat = await ChatModel.getByField(companionId, userId);
		if (isChat) {
			return res.json({
				status: 'success',
				code: 200,
				data: {
					...isChat,
				},
			});
		}
	} catch (e) {
		next(e);
	}
};

module.exports = {
	listChats,
	startChat,
	removeChatForBoth,
	muteChat,
	sortChat,
	seenChat,
	typingChat,
	getChatById,
};
