import { Request, Response } from 'express'
import { IUser, User } from '../users/models'
import { Blocking } from './models'
import { Chat } from '../chats/models'
import { Follower } from '../followers/models'

async function getBlockings(req: Request, res: Response) {
	interface Payload {
		limit?: string | number
		page?: string | number
	}

	try {
		const user = res.locals.user as IUser
		let { limit = '10', page = '1' } = req.query as unknown as Payload
		limit = +limit
		page = +page

		const match: any = { blockedBy: user._id }

		const blockings = await Blocking.find(match)
			.sort({ createdAt: -1 })
			.skip((page - 1) * limit)
			.limit(limit)
			.populate({ path: 'user', select: { name: 1, username: 1, photo: 1 } })
		const count = await Blocking.countDocuments(match)

		return res.json({ blockings, count })
	} catch (error) {
		console.error(error)
		return res.status(500).json({ message: 'server error' })
	}
}

async function postBlocking(req: Request, res: Response) {
	try {
		const user = res.locals.user as IUser
		const userId = req.params.userId

		const b = await Blocking.findOne({ user: userId, blockedBy: user._id })
		if (b) {
			return res.status(409).json({ message: 'blocking already exist' })
		}

		const u = await User.findById(userId)
		if (!u) {
			return res.status(404).json({ message: 'user not found' })
		}

		const blocking = await Blocking.create({
			user: u._id,
			blockedBy: user._id
		});

		(async () => {
			try {
				// updating chat.blocked for one to one chat
				const chats = await Chat.find({
					participants: {
						$all: [
							{ $elemMatch: { user: u._id } },
							{ $elemMatch: { user: user._id } }
						]
					}
				})
				for(const chat of chats) {
					if(chat.isGroup) {
						continue
					}
					let flag = false
					const p1 = `${chat.participants[0].user}`
					const p2 = `${chat.participants[1].user}`
					if((p1 === `${u._id}` && p2 === `${user._id}`) || (p1 === `${user._id}` && p2 === `${u._id}`)) {
						chat.blocked = true
						flag = true
					}
					if(flag) {
						await chat.save()
					}
				}
			} catch (error) {
				console.log(error)
			}
		})()

		return res.status(201).json({ blocking })
	} catch (error) {
		console.log(error)
		return res.status(500).json({ message: 'server error' })
	}
}

async function deleteBlocking(req: Request, res: Response) {
	try {
		const user = res.locals.user as IUser
		const userId = req.params.userId

		const blocking = await Blocking.findOne({ user: userId, blockedBy: user._id })
		if (!blocking) {
			return res.status(404).json({ message: 'blocking not found' })
		}

		await blocking.deleteOne();

		(async () => {
			try {
				// updating chat.blocked for one to one chat
				const chats = await Chat.find({
					participants: {
						$all: [
							{ $elemMatch: { user: userId } },
							{ $elemMatch: { user: user._id } }
						]
					}
				})
				for(const chat of chats) {
					if(chat.isGroup) {
						continue
					}
					let flag = false
					const p1 = `${chat.participants[0].user}`
					const p2 = `${chat.participants[1].user}`
					if((p1 === `${userId}` && p2 === `${user._id}`) || (p1 === `${user._id}` && p2 === `${userId}`) && chat.blocked) {
						chat.blocked = undefined
						flag = true
					}
					if(flag) {
						await chat.save()
					}
				}
			} catch (error) {
				console.log(error)
			}
		})()

		return res.json({ message: 'blocking deleted successfully' })
	} catch (error) {
		console.log(error)
		return res.status(500).json({ message: 'server error' })
	}
}

const controllers = {
	getBlockings,
	postBlocking,
	deleteBlocking
}

export default controllers
