import { Application } from 'express';
import { Resource } from 'express-automatic-routes';
import { PostProvider } from '#providers/PostProvider';
import { Req, Res } from '#interfaces/IApi';
import verify, { requireAdmin } from '#middlewares/auth';
import { validateId, validateZod } from '#middlewares/validators';
import { PostUpdateBodySchema } from '#contracts/post/schema';
import { Errors } from '#interfaces/error';
import { sendSuccess } from '#utils/responseUtils';
import { AuditLogService } from '#services/audit/auditLogService';

export default (_express: Application) => {
	const postProvider = new PostProvider();

	return <Resource>{
		get: {
			middleware: [verify, validateId],
			handler: async (req: Req, res: Res) => {
				try {
					const data = await postProvider.getByIdOptimized(req.params.id!);
					if (!data) throw Errors.notFound('Post');
					return sendSuccess(res, data);
				} catch (error) {
					return res.error(error);
				}
			},
		},

		put: {
			middleware: [verify, requireAdmin, validateId, validateZod(PostUpdateBodySchema)],
			handler: async (req: Req, res: Res) => {
				try {
					const { title, content, thumbnailId, targetType, targetIds, isFeatured, status, publishedAt } = req.body;

					const updated = await postProvider.updateWithTargets(req.params.id!, {
						...(title !== undefined && { title }),
						...(content !== undefined && { content }),
						...(thumbnailId !== undefined && { thumbnail_id: thumbnailId }),
						...(targetType !== undefined && { target_type: targetType }),
						...(targetIds !== undefined && { target_ids: targetIds }),
						...(isFeatured !== undefined && { is_featured: isFeatured }),
						...(status !== undefined && { status }),
						...(publishedAt !== undefined && { published_at: publishedAt ? new Date(publishedAt) : null }),
						updated_by: req.user?.id ?? null,
					});

					if (!updated) throw Errors.notFound('Post');

					await AuditLogService.enqueueEntityChangeFromRequest(req, {
						entityType: 'Post',
						entityId: req.params.id!,
						changeType: 'UPDATE',
						payload: {
							before: null,
							after: updated.toJSON(),
							changed_fields: Object.keys(req.body),
						},
						reason: `Updated post: ${updated.title}`,
					});

					const detail = await postProvider.getByIdOptimized(req.params.id!);
					return sendSuccess(res, detail);
				} catch (error) {
					return res.error(error);
				}
			},
		},

		delete: {
			middleware: [verify, requireAdmin, validateId],
			handler: async (req: Req, res: Res) => {
				try {
					const post = await postProvider.getByIdOptimized(req.params.id!);
					if (!post) throw Errors.notFound('Post');

					await postProvider.softDelete(req.params.id!, req.user?.id ?? null);

					await AuditLogService.enqueueEntityChangeFromRequest(req, {
						entityType: 'Post',
						entityId: req.params.id!,
						changeType: 'DELETE',
						payload: {
							before: post,
							after: null,
							changed_fields: [],
						},
						reason: `Deleted post: ${post.title}`,
					});

					return sendSuccess(res, null);
				} catch (error) {
					return res.error(error);
				}
			},
		},
	};
};
