import { Request, Response } from 'express'
import { IUser } from '../users/models'
import { ILike, Like } from './models'
import { IReel, Reel } from '../reels/models'
import { Comment, IComment } from '../comments/models'
import services from '../../utils/services'

async function postLike(req: Request, res: Response) {
	interface Payload {
		reel?: string
		comment?: string
	}
	try {
		const user = res.locals.user as IUser
		const { reel: reelId, comment: commentId } = req.body as Payload

		let reel: IReel, comment: IComment, commentUser: IUser
		if (reelId) {
			reel = await Reel.findById(reelId).populate('user') as IReel
			if (!reel) {
				return res.status(404).json({ message: 'reel not found' })
			}
		} else {
			// @ts-ignore
			comment = await Comment.findById(commentId).populate('user') as IComment
			if (!comment) {
				return res.status(404).json({ message: 'comment not found' })
			}
			// @ts-ignore
			commentUser = comment.user as IUser
			reel = await Reel.findById(comment.reel) as IReel
			if (!reel) {
				return res.status(404).json({ message: 'reel not found' })
			}
		}

		const query = reelId ? { reel: reel._id } : { comment: comment!._id }
		let like = await Like.findOne({ user: user._id, ...query }) as ILike
		if (like) {
			return res.status(200).json({ message: 'already liked' })
		}

		// @ts-ignore
		like = await Like.create({ user: user._id, ...query });

		(async () => {
			try {
				const count = await Like.countDocuments({ ...query })
				if (reelId) {
					reel.likes = count
					await reel.save()
				} else {
					comment!.likes = count
					await comment!.save()
				}
			} catch (error) {
				console.log(error)
			}
		})()

		if (reelId && `${reel.user._id}` !== `${user._id}`) {
			await services.notifyUser({
				title: 'Your vibe got a new like',
				description: `${user.username} liked your vibe`,
				event: 'reel-liked',
				user: reel.user as unknown as IUser,
				from: user._id,
				reel: reel._id,
				like: like._id
			})
		}
		// @ts-ignore
		if (commentId && `${commentUser._id}` !== `${user._id}`) {
			await services.notifyUser({
				title: 'Your comment got a new like',
				description: `${user.username} liked your comment`,
				event: 'comment-liked',
				user: commentUser!,
				from: user._id,
				reel: reel._id,
				comment: comment!._id,
				like: like._id
			})
		}

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

async function deleteLike(req: Request, res: Response) {
	interface Payload {
		reel?: string
		comment?: string
	}
	try {
		const user = res.locals.user as IUser
		const { reel: reelId, comment: commentId } = req.body as Payload

		let reel: IReel, comment: IComment
		if (reelId) {
			reel = await Reel.findById(reelId) as IReel
			if (!reel) {
				return res.status(404).json({ message: 'reel not found' })
			}
		} else {
			comment = await Comment.findById(commentId) as IComment
			if (!comment) {
				return res.status(404).json({ message: 'comment not found' })
			}
			reel = await Reel.findById(comment.reel) as IReel
			if (!reel) {
				return res.status(404).json({ message: 'reel not found' })
			}
		}

		const query = reelId ? { reel: reel._id } : { comment: comment!._id }
		const like = await Like.findOne({ user: user._id, ...query }) as ILike
		if (!like) {
			return res.status(200).json({ message: 'already un-liked' })
		}

		(async () => {
			try {
				await like.deleteOne()
				const count = await Like.countDocuments({ ...query })
				if (reelId) {
					reel.likes = count
					await reel.save()
				} else {
					comment!.likes = count
					await comment!.save()
				}
			} catch (error) {
				console.log(error)
			}
		})()

		return res.json({ message: 'un-liked successfully' })
	} catch (error) {
		console.log(error)
		return res.status(500).json({ message: 'server error' })
	}
}

const controllers = {
	postLike,
	deleteLike
}

export default controllers
