const { Op } = require('sequelize');
const { deleteFile } = require('../../helpers');
const {
	Posts,
	PostImages,
	sequelize,
	PostLikes,
	PostComments,
	CommentLikes,
	PostTags,
	Members,
	Notifications,
} = require('../../models');
const { errorHandler } = require('../../util');
const { formatImage, formatCase, parseJsonSafe } = require('../../util/formatter');
const { moveFilesFromFileServer, deleteFilesFromFileServer, deleteFiles } = require('../../util/file-handlers');

const formatPostTags = (tags) => {
	if (!tags || !Array.isArray(tags)) return [];
	return tags.map((tag) => ({
		id: tag.member_id,
		first_name: tag.member && tag.member.first_name ? tag.member.first_name : 'Unknown',
		last_name: tag.member && tag.member.last_name ? tag.member.last_name : 'User',
	}));
};

const formatPostImages = (images) => {
	if (!images || !Array.isArray(images)) return [];
	return images.map((img) => ({
		...img,
		image: formatImage(img.image, 'post-uploads'),
	}));
};

const POST_DEFAULT_INCLUDE = [
	{
		model: Members,
		as: 'member',
		attributes: ['id', 'first_name', 'last_name', 'profile_image'],
	},
	{
		model: PostImages,
		as: 'images',
		attributes: ['image'],
	},
	{
		model: PostTags,
		as: 'tags',
		attributes: ['member_id'],
		include: [
			{
				model: Members,
				as: 'member',
				attributes: ['first_name', 'last_name'],
			},
		],
		where: { status: 'Accepted' },
		required: false,
	},
	{
		model: Members,
		as: 'member',
		attributes: ['id', 'first_name', 'last_name', 'profile_image'],
	},
	{
		model: PostImages,
		as: 'images',
		attributes: ['image'],
	},
	{
		model: PostTags,
		as: 'tags',
		attributes: ['member_id'],
		include: [
			{
				model: Members,
				as: 'member',
				attributes: ['first_name', 'last_name'],
			},
		],
		where: { status: 'Accepted' },
		required: false,
	},
];

const POST_DEFAULT_ATTRIBUTES_INCLUDE = (memberId) => {
	return [
		[
			sequelize.literal(`(
						SELECT COUNT(*)
						FROM post_comments AS c
						WHERE c.post_id = Posts.id
						)`),
			'comments',
		],
		[
			sequelize.literal(`(
						SELECT COUNT(*)
						FROM post_likes AS l
						WHERE l.post_id = Posts.id
						)`),
			'likes',
		],
		[
			sequelize.literal(`(
						SELECT COUNT(*)
						FROM posts AS p
						WHERE p.original_post_id = Posts.id
						)`),
			'shares',
		],
		[
			sequelize.literal(`(
							SELECT COUNT(*)
							FROM post_likes AS l
							WHERE l.post_id = Posts.id
								AND l.member_id = "${memberId}"
						)`),
			'isLiked',
		],
	];
};

exports.getAllPosts = async (req, res, next) => {
	try {
		const page = req.query.page ? parseInt(req.query.page, 10) : null;
		const limit = req.query.limit ? parseInt(req.query.limit, 10) : null;
		const offset = page && limit ? (page - 1) * limit : undefined;

		const findOptions = {
			attributes: {
				include: POST_DEFAULT_ATTRIBUTES_INCLUDE(req.memberId),
				exclude: ['member_id'],
			},
			include: [
				...POST_DEFAULT_INCLUDE,
				{
					model: Posts,
					as: 'originalPost',
					attributes: {
						include: [
							[
								sequelize.literal(`(
							SELECT COUNT(*)
							FROM posts AS p
							WHERE p.original_post_id = originalPost.id
						)`),
								'shares',
							],
						],
					},
					include: [
						{
							model: Members,
							as: 'member',
							attributes: ['id', 'first_name', 'last_name', 'profile_image'],
						},
						{
							model: PostImages,
							as: 'images',
							attributes: ['image'],
						},
						{
							model: PostTags,
							as: 'tags',
							attributes: ['member_id'],
							include: [
								{
									model: Members,
									as: 'member',
									attributes: ['first_name', 'last_name'],
								},
							],
							where: { status: 'Accepted' },
							required: false,
						},
					],
				},
			],
			order: [['createdAt', 'DESC']],
			distinct: true,
		};

		if (page && limit) {
			findOptions.limit = limit;
			findOptions.offset = offset;
		}

		let { count, rows: posts } = await Posts.findAndCountAll(findOptions);

		posts = posts.map((item) => {
			const post = item.get({ plain: true });

			post.tags = formatPostTags(post.tags);
			post.images = formatPostImages(post.images);

			if (post.originalPost) {
				post.originalPost.tags = formatPostTags(post.originalPost.tags);
				post.originalPost.images = formatPostImages(post.originalPost.images);
				post.originalPost.member.profile_image = formatImage(post.originalPost.member.profile_image, 'profile-uploads');
			}

			post.member.profile_image = formatImage(post?.member?.profile_image, 'profile-uploads');

			return post;
		});

		posts = formatCase(posts);

		const response = {
			success: true,
			data: posts,
		};

		if (page && limit) {
			response.pagination = {
				total: count,
				page,
				limit,
				pages: Math.ceil(count / limit),
			};
		}

		return res.status(200).json(response);
	} catch (error) {
		next(error);
	}
};

exports.getPost = async (req, res, next) => {
	try {
		const post = await Posts.findOne({
			where: { id: req.params.id },
			attributes: {
				include: POST_DEFAULT_ATTRIBUTES_INCLUDE(req.memberId),
				exclude: ['member_id'],
			},
			include: [...POST_DEFAULT_INCLUDE],
		});

		if (!post) return res.status(404).json({ success: false, message: 'Post not found' });

		let result = post.get({ plain: true });

		result.tags = formatPostTags(result.tags);
		result.images = formatPostImages(result.images);

		post.member.profile_image = formatImage(post?.member?.profile_image, 'profile-uploads');

		result = formatCase(result);

		return res.status(200).json({ success: true, data: result });
	} catch (error) {
		next(error);
	}
};

exports.createPost = async (req, res, next) => {
	try {
		const body = formatCase(req.body, 'snake');
		let post = await Posts.create({ ...body, member_id: req.memberId });
		post = post.get({ plain: true });

		let tags = req.body.tags || [];
		if (typeof tags === 'string') {
			try {
				tags = JSON.parse(tags);
			} catch (e) {
				return errorHandler('Invalid tags format', 400);
			}
		}

		if (tags.length > 0) {
			const members = await Promise.all(
				tags.map(async (member_id) => {
					const member = await Members.findByPk(member_id);
					return member ? null : member_id;
				}),
			);

			if (members.some((id) => id !== null)) {
				return errorHandler('One or more member IDs are invalid', 400);
			}

			post.tags = await PostTags.bulkCreate(
				tags.map((member_id) => ({
					post_id: post.id,
					member_id,
				})),
			);

			await Notifications.bulkCreate(
				tags.map((member_id) => ({
					member_id,
					post_id: post.id,
					description: `You are seen in the post by one of the attendee of the event. Review it and reshare.`,
					type: 'PostTag',
				})),
			);
		}

		let images;
		if (process.env.USE_EXTERNAL_FILE_SERVER === 'true') {
			let postImgs = parseJsonSafe(req.body.postImgs);

			if (Array.isArray(postImgs) && postImgs.length > 0) {
				images = postImgs.map((filename) => ({ post_id: post.id, image: filename }));
				images = await PostImages.bulkCreate(images);
				await moveFilesFromFileServer(postImgs, 'post-uploads');
			}
		} else if (req.files && req.files.postImgs) {
			images = req.files.postImgs.map((file) => ({
				post_id: post.id,
				image: file.filename,
			}));

			images = await PostImages.bulkCreate(images);
		}

		post.images = images
			? images.map((img) => ({
					...img.get({ plain: true }),
					image: formatImage(img.image, 'post-uploads'),
				}))
			: [];
		return res.status(201).json({ success: true, data: post });
	} catch (error) {
		next(error);
	}
};

exports.updatePost = async (req, res, next) => {
	try {
		const post = await Posts.findByPk(req.params.id);
		if (!post) return res.status(404).json({ success: false, message: 'Post not found' });

		await post.update(req.body);

		let tags = parseJsonSafe(req.body?.tags);
		if (tags !== undefined) {
			if (tags.length > 0) {
				const foundMembers = await Members.findAll({
					where: { id: { [Op.in]: tags } },
					attributes: ['id'],
				});

				if (foundMembers.length !== tags.length) {
					return errorHandler('One or more member IDs are invalid', 400);
				}
			}
			await PostTags.destroy({ where: { post_id: post.id } });
			if (tags.length > 0) {
				await PostTags.bulkCreate(
					tags.map((member_id) => ({
						post_id: post.id,
						member_id,
					})),
				);
			}
		}

		let images;
		if (process.env.USE_EXTERNAL_FILE_SERVER === 'true') {
			let postImgs = parseJsonSafe(req.body.postImgs);

			if (Array.isArray(postImgs) && postImgs.length > 0) {
				const existingImages = await PostImages.findAll({ where: { post_id: post.id } });
				const filenamesToDelete = existingImages.map((img) => img.image);

				if (filenamesToDelete.length > 0) {
					await deleteFilesFromFileServer(filenamesToDelete, 'post-uploads');
					await PostImages.destroy({ where: { post_id: post.id } });
				}

				images = postImgs.map((filename) => ({ post_id: post.id, image: filename }));
				images = await PostImages.bulkCreate(images);

				await moveFilesFromFileServer(postImgs, 'post-uploads');

				post.images = images.map((img) => ({
					...img.get({ plain: true }),
					image: formatImage(img.image, 'post-uploads'),
				}));
			}
		} else if (req.files && req.files.postImgs) {
			const existingImages = await PostImages.findAll({ where: { post_id: post.id } });
			const filenamesToDelete = existingImages.map((img) => img.image);

			if (filenamesToDelete.length > 0) {
				await deleteFiles(filenamesToDelete, 'image', 'post-uploads');
			}

			await PostImages.destroy({ where: { post_id: post.id } });

			images = req.files.postImgs.map((file) => ({
				post_id: post.id,
				image: file.filename,
			}));

			images = await PostImages.bulkCreate(images);

			post.images = images.map((img) => ({
				...img.get({ plain: true }),
				image: formatImage(img.image, 'post-uploads'),
			}));
		}

		return res.status(200).json({ success: true, data: post });
	} catch (error) {
		next(error);
	}
};

exports.deletePost = async (req, res, next) => {
	const transaction = await sequelize.transaction();
	try {
		const post = await Posts.findByPk(req.params.id);
		if (!post) return errorHandler('Post not found', 404);

		const images = await PostImages.findAll({ where: { post_id: post.id } });
		const filenamesToDelete = images.map((img) => img.image);

		await PostImages.destroy({ where: { post_id: post.id }, transaction });
		await PostLikes.destroy({ where: { post_id: post.id }, transaction });
		const comments = await PostComments.findAll({ where: { post_id: post.id } });
		for (const comment of comments) {
			await CommentLikes.destroy({ where: { comment_id: comment.id }, transaction });
		}
		await PostComments.destroy({ where: { post_id: post.id }, transaction });
		await PostTags.destroy({ where: { post_id: post.id }, transaction });

		await post.destroy({ transaction });

		await transaction.commit();

		if (filenamesToDelete.length > 0) {
			if (process.env.USE_EXTERNAL_FILE_SERVER === 'true') {
				await deleteFilesFromFileServer(filenamesToDelete, 'post-uploads');
			} else {
				await deleteFiles(filenamesToDelete, 'image', 'post-uploads');
			}
		}

		return res.status(200).json({ success: true, message: 'Post and all related data deleted' });
	} catch (error) {
		await transaction.rollback();
		next(error);
	}
};

exports.createPostComment = async (req, res, next) => {
	try {
		const { comment } = req.body;
		const post_id = req.params.postId;
		const member_id = req.memberId;

		const postComment = await PostComments.create({ post_id, member_id, comment });

		return res.status(201).json({ success: true, data: postComment });
	} catch (error) {
		next(error);
	}
};

exports.updatePostComment = async (req, res, next) => {
	try {
		const { comment } = req.body;
		const postComment = await PostComments.findByPk(req.params.id);
		if (!postComment) return errorHandler('Comment not found', 404);
		await postComment.update({ comment });
		return res.status(200).json({ success: true, data: postComment });
	} catch (error) {
		next(error);
	}
};

exports.deletePostComment = async (req, res, next) => {
	try {
		const postComment = await PostComments.findByPk(req.params.id);
		if (!postComment) return errorHandler('Comment not found', 404);
		await postComment.destroy();
		return res.status(200).json({ success: true, message: 'Comment deleted' });
	} catch (error) {
		next(error);
	}
};

exports.getPostComments = async (req, res, next) => {
	try {
		let comments = await PostComments.findAll({
			where: { post_id: req.params.postId },
			include: [
				{
					model: Members,
					as: 'member',
					attributes: ['id', 'first_name', 'last_name', 'profile_image'],
				},
			],
			attributes: {
				include: [
					[
						sequelize.literal('(SELECT COUNT(*) FROM comment_likes WHERE comment_likes.comment_id = PostComments.id)'),
						'likes',
					],
					[
						sequelize.literal(`(
							SELECT COUNT(*)
							FROM comment_likes
							WHERE comment_likes.comment_id = PostComments.id
								AND comment_likes.member_id = "${req.memberId}"
						)`),
						'isLiked',
					],
				],
				exclude: ['post_id', 'member_id'],
			},
			order: [['createdAt', 'DESC']],
		});

		comments = comments.map((item) => {
			const comment = item.get({ plain: true });
			comment.member.profile_image = comment.member.profile_image
				? formatImage(comment.member.profile_image, 'profile-uploads')
				: null;
			return comment;
		});

		return res.status(200).json({ success: true, data: comments });
	} catch (error) {
		next(error);
	}
};

exports.handlePostLike = async (req, res, next) => {
	try {
		const member_id = req.memberId;
		const { postId, like } = req.body;

		const post = await Posts.findByPk(postId);
		if (!post) return errorHandler('Post not found', 404);

		if (like) {
			const existingLike = await PostLikes.findOne({
				where: { post_id: postId, member_id },
			});
			if (existingLike) {
				return res.status(200).json({ success: true, data: existingLike });
			}
			const createdLike = await PostLikes.create({ post_id: postId, member_id });
			return res.status(201).json({ success: true, data: createdLike });
		} else {
			await PostLikes.destroy({
				where: { post_id: postId, member_id },
			});
			return res.status(200).json({ success: true, message: 'Like removed' });
		}
	} catch (error) {
		next(error);
	}
};

exports.getPostLikes = async (req, res, next) => {
	try {
		let likes = await PostLikes.findAll({
			where: { post_id: req.params.postId },
			include: [{ model: Members, as: 'member', attributes: ['id', 'first_name', 'last_name', 'profile_image'] }],
		});

		likes = likes.map((item) => {
			const like = item.get({ plain: true });
			like.member.profile_image = like.member.profile_image
				? formatImage(like.member.profile_image, 'profile-uploads')
				: null;
			return like.member;
		});

		return res.status(200).json({ success: true, data: likes });
	} catch (error) {
		next(error);
	}
};

exports.handleCommentLike = async (req, res, next) => {
	try {
		const member_id = req.memberId;
		const { commentId, like } = req.body;

		const comment = await PostComments.findByPk(commentId);
		if (!comment) return errorHandler('Comment not found', 404);

		if (like) {
			const existingLike = await CommentLikes.findOne({
				where: { comment_id: commentId, member_id },
			});
			if (existingLike) {
				return res.status(200).json({ success: true, data: existingLike });
			}
			const createdLike = await CommentLikes.create({ comment_id: commentId, member_id });
			return res.status(201).json({ success: true, data: createdLike });
		} else {
			await CommentLikes.destroy({
				where: { comment_id: commentId, member_id },
			});
			return res.status(200).json({ success: true, message: 'Like removed' });
		}
	} catch (error) {
		next(error);
	}
};

exports.getCommentLikes = async (req, res, next) => {
	try {
		let likes = await CommentLikes.findAll({
			where: { comment_id: req.params.commentId },
			attributes: ['id'],
			include: [{ model: Members, as: 'member', attributes: ['id', 'first_name', 'last_name', 'profile_image'] }],
		});

		likes = likes.map((item) => {
			const like = item.get({ plain: true });
			like.member.profile_image = like.member.profile_image
				? formatImage(like.member.profile_image, 'profile-uploads')
				: null;
			return like.member;
		});

		return res.status(200).json({ success: true, data: likes });
	} catch (error) {
		next(error);
	}
};

exports.sharePost = async (req, res, next) => {
	try {
		const { postId, shareContent, shareTags } = req.body;
		const member_id = req.memberId;

		const post = await Posts.findByPk(postId);
		if (!post) return errorHandler('Post not found', 404);

		const sharedPost = await Posts.create({
			member_id,
			content: shareContent,
			original_post_id: post.id,
			is_shared: true,
		});

		let postTags = [];
		if (shareTags && shareTags.length > 0) {
			const foundMembers = await Members.findAll({
				where: { id: shareTags },
				attributes: ['id'],
			});
			if (foundMembers.length !== shareTags.length) {
				return errorHandler('One or more member IDs in shareTags are invalid', 400);
			}

			postTags = await PostTags.bulkCreate(
				shareTags.map((tag) => ({
					post_id: sharedPost.id,
					member_id: tag,
				})),
			);
		}

		return res.status(201).json({ success: true, data: sharedPost, postTags });
	} catch (error) {
		next(error);
	}
};

exports.getProfilePosts = async (req, res, next) => {
	try {
		const page = req.query.page ? parseInt(req.query.page, 10) : null;
		const limit = req.query.limit ? parseInt(req.query.limit, 10) : null;
		const offset = page && limit ? (page - 1) * limit : undefined;
		const type = req.query.type || 'all';

		const memberId = req.memberId;

		let where;

		switch (type) {
			case 'taggedPhoto':
				where = {
					[Op.and]: [
						sequelize.literal(`EXISTS (
								SELECT 1 FROM post_tags 
								WHERE post_tags.post_id = Posts.id 
								AND post_tags.member_id = '${memberId}'
							)`),
					],
				};
				break;
			case 'accepted':
				where = {
					[Op.and]: [
						sequelize.literal(`EXISTS (
								SELECT 1 FROM post_tags 
								WHERE post_tags.post_id = Posts.id 
								AND post_tags.member_id = '${memberId}'
								AND post_tags.status = 'Accepted'
							)`),
					],
				};
				break;
			case 'rejected':
				where = {
					[Op.and]: [
						sequelize.literal(`EXISTS (
								SELECT 1 FROM post_tags 
								WHERE post_tags.post_id = Posts.id 
								AND post_tags.member_id = '${memberId}'
								AND post_tags.status = 'Rejected'
							)`),
					],
				};
				break;
			default:
				where = {
					[Op.or]: [
						{ member_id: memberId },
						sequelize.literal(`EXISTS (
						SELECT 1 FROM post_tags 
						WHERE post_tags.post_id = Posts.id 
						AND post_tags.member_id = '${memberId}'
					)`),
					],
				};
				break;
		}

		const findOptions = {
			where,
			attributes: {
				include: [
					...POST_DEFAULT_ATTRIBUTES_INCLUDE(memberId),
					[
						sequelize.literal(`(
										SELECT status
										FROM post_tags
										WHERE post_tags.post_id = Posts.id
										AND post_tags.member_id = '${memberId}'
										LIMIT 1
									)`),
						'tagStatus',
					],
				],
				exclude: ['member_id'],
			},
			include: [
				...POST_DEFAULT_INCLUDE,
				{
					model: Posts,
					as: 'originalPost',
					attributes: {
						include: [
							[
								sequelize.literal(`(
							SELECT COUNT(*)
							FROM posts AS p
							WHERE p.original_post_id = originalPost.id
						)`),
								'shares',
							],
						],
					},
					include: [
						{
							model: Members,
							as: 'member',
							attributes: ['id', 'first_name', 'last_name', 'profile_image'],
						},
						{
							model: PostImages,
							as: 'images',
							attributes: ['image'],
						},
						{
							model: PostTags,
							as: 'tags',
							attributes: ['member_id'],
							include: [
								{
									model: Members,
									as: 'member',
									attributes: ['first_name', 'last_name'],
								},
							],
							where: { status: 'Accepted' },
							required: false,
						},
					],
				},
			],
			order: [['createdAt', 'DESC']],
			distinct: true,
		};

		if (page && limit) {
			findOptions.limit = limit;
			findOptions.offset = offset;
		}

		let { count, rows: posts } = await Posts.findAndCountAll(findOptions);

		posts = posts.map((item) => {
			const post = item.get({ plain: true });

			post.tags = formatPostTags(post.tags);
			post.images = formatPostImages(post.images);

			if (post.originalPost) {
				post.originalPost.tags = formatPostTags(post.originalPost.tags);
				post.originalPost.images = formatPostImages(post.originalPost.images);
				post.originalPost.member.profile_image = formatImage(post.originalPost.member.profile_image, 'profile-uploads');
			}

			post.member.profile_image = formatImage(post?.member?.profile_image, 'profile-uploads');

			return post;
		});

		posts = formatCase(posts);

		const response = {
			success: true,
			data: posts,
		};

		if (page && limit) {
			response.pagination = {
				total: count,
				page,
				limit,
				pages: Math.ceil(count / limit),
			};
		}

		return res.status(200).json(response);
	} catch (error) {
		next(error);
	}
};

exports.getProfilePostById = async (req, res, next) => {
	try {
		const { id } = req.params;
		const memberId = req.memberId;

		const post = await Posts.findOne({
			where: {
				id,
				[Op.or]: [
					{ member_id: memberId },
					sequelize.literal(`EXISTS (
						SELECT 1 FROM post_tags 
						WHERE post_tags.post_id = Posts.id 
						AND post_tags.member_id = '${memberId}'
					)`),
				],
			},
			attributes: {
				include: [
					...POST_DEFAULT_ATTRIBUTES_INCLUDE(memberId),
					[
						sequelize.literal(`(
							SELECT status
							FROM post_tags
							WHERE post_tags.post_id = Posts.id
							AND post_tags.member_id = '${memberId}'
							LIMIT 1
						)`),
						'tagStatus',
					],
				],
				exclude: ['member_id'],
			},
			include: [
				...POST_DEFAULT_INCLUDE,
				{
					model: Posts,
					as: 'originalPost',
					attributes: {
						include: [
							[
								sequelize.literal(`(
									SELECT COUNT(*)
									FROM posts AS p
									WHERE p.original_post_id = originalPost.id
								)`),
								'shares',
							],
						],
					},
					include: [
						{
							model: Members,
							as: 'member',
							attributes: ['id', 'first_name', 'last_name', 'profile_image'],
						},
						{
							model: PostImages,
							as: 'images',
							attributes: ['image'],
						},
						{
							model: PostTags,
							as: 'tags',
							attributes: ['member_id'],
							include: [
								{
									model: Members,
									as: 'member',
									attributes: ['first_name', 'last_name'],
								},
							],
							where: { status: 'Accepted' },
							required: false,
						},
					],
				},
			],
		});

		if (!post) {
			return res.status(404).json({ success: false, message: 'Post not found' });
		}

		let result = post.get({ plain: true });

		result.tags = formatPostTags(result.tags);
		result.images = formatPostImages(result.images);

		if (result.originalPost) {
			result.originalPost.tags = formatPostTags(result.originalPost.tags);
			result.originalPost.images = formatPostImages(result.originalPost.images);
			result.originalPost.member.profile_image = formatImage(
				result.originalPost.member.profile_image,
				'profile-uploads',
			);
		}

		result.member.profile_image = formatImage(result?.member?.profile_image, 'profile-uploads');

		result = formatCase(result);

		return res.status(200).json({ success: true, data: result });
	} catch (error) {
		next(error);
	}
};

exports.handlePostTag = async (req, res, next) => {
	try {
		const { postId, status } = req.body;
		const { memberId } = req;

		const postTag = await PostTags.findOne({
			where: { post_id: postId, member_id: memberId },
		});

		if (!postTag) return errorHandler('Post tag not found', 404);

		await postTag.update({ status });

		return res.status(200).json({ success: true, data: postTag, message: 'Post tag updated successfully' });
	} catch (error) {
		next(error);
	}
};

exports.taggedPhotos = async (req, res, next) => {
	try {
		const { memberId } = req;
		const page = req.query.page ? parseInt(req.query.page, 10) : null;
		const limit = req.query.limit ? parseInt(req.query.limit, 10) : null;
		const offset = page && limit ? (page - 1) * limit : undefined;

		const where = {
			[Op.and]: [
				sequelize.literal(`EXISTS (
					SELECT 1 FROM post_tags 
					WHERE post_tags.post_id = PostImages.post_id 
					AND post_tags.member_id = '${memberId}'
					AND post_tags.status = 'Accepted'
				)`),
			],
		};

		const findOptions = {
			where,
			include: [
				{
					model: Posts,
					as: 'post',
					attributes: ['id', 'createdAt'],
				},
			],
			order: [[{ model: Posts, as: 'post' }, 'createdAt', 'DESC']],
			distinct: true,
		};

		if (page && limit) {
			findOptions.limit = limit;
			findOptions.offset = offset;
		}

		const { count, rows: images } = await PostImages.findAndCountAll(findOptions);

		const formattedImages = images.map((img) => formatImage(img.image, 'post-uploads'));

		const response = {
			success: true,
			data: formattedImages,
		};

		if (page && limit) {
			response.pagination = {
				total: count,
				page,
				limit,
				pages: Math.ceil(count / limit),
			};
		}

		return res.status(200).json(response);
	} catch (error) {
		next(error);
	}
};
