const ChatModel = require('../model/chat');
const UserModel = require('../model/user');
const MessageModel = require('../model/message');

const listChats = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const { total, limit, page, chats } = await ChatModel.getList(
			userId,
			req.query
		);

		const messages = await MessageModel.getLastMessagesList(userId);

		const lastOnline = await chats.reduce(async (acc, { companionId }) => {
			const { _id, online, updatedAt } = await UserModel.findById(companionId);
			acc.push({ _id, online, updatedAt });
			return acc;
		}, []);

		const lastMessages = await messages.reduce(
			(acc, { message, companionId, createdAt, updatedAt }) => {
				const obj = {
					message,
					companionId,
					createdAt,
					updatedAt,
				};
				if (acc.length === 0) {
					acc.push(obj);
					return acc;
				}
				if (acc.some((el) => el.companionId === companionId)) {
					const i = acc.findIndex((el) => {
						return el.companionId === companionId;
					});
					acc[i] = obj;
					return acc;
				}
				acc.push(obj);
				return acc;
			},
			[]
		);

		return res.json({
			status: 'success',
			code: 200,
			data: {
				total,
				limit,
				page,
				chats,
				lastMessages,
				lastOnline,
			},
		});
	} 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, avatarUrl, color, online, number } = companion;
		const {
			name: Name,
			lastName: LastName,
			avatarUrl: AvatarUrl,
			color: Color,
			online: Online,
			number: Number,
		} = user;
		if (companion && (isUser || isCompanion)) {
			await ChatModel.update(isUser._id, {
				name,
				lastName,
				avatarUrl,
				color,
				online,
				number,
			});
			await ChatModel.update(isCompanion._id, {
				name: Name,
				lastName: LastName,
				avatarUrl: AvatarUrl,
				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,
				avatarUrl,
				color,
				online,
				number,
				companionId: id,
				owner: userId,
			});
			await ChatModel.add({
				name: Name,
				lastName: LastName,
				avatarUrl: AvatarUrl,
				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 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, { mute: !mute });
			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 isMessage = await MessageModel.getList(userId, {});
		if (isChat && isMessage && isCompanionChat) {
			const { total } = isMessage;
			await ChatModel.update(isChat._id, { seen: total, watched: false });
			await ChatModel.update(isCompanionChat._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, { typing });
			return res.status(200).json({
				status: 'success',
				code: 200,
				data: {},
			});
		}
	} catch (e) {
		next(e);
	}
};

const chatById = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const companionId = req.params.companionId;
		const { online } = await UserModel.findById(companionId);
		const isChat = await ChatModel.getByField(companionId, userId);
		if (isChat) {
			const {
				name,
				lastName,
				avatarUrl,
				color,
				mute,
				seen,
				total,
				watched,
				typing,
				number,
				_id,
				companionId,
				owner,
				createdAt,
				updatedAt,
				__v,
			} = isChat;
			return res.json({
				status: 'success',
				code: 200,
				data: {
					name,
					lastName,
					avatarUrl,
					color,
					online,
					mute,
					seen,
					total,
					watched,
					typing,
					number,
					_id,
					companionId,
					owner,
					createdAt,
					updatedAt,
					__v,
				},
			});
		}
	} catch (e) {
		next(e);
	}
};

module.exports = {
	listChats,
	startChat,
	muteChat,
	seenChat,
	typingChat,
	chatById,
};
