import { Application } from 'express';
import { Resource } from 'express-automatic-routes';
import { Req, Res } from '#interfaces/IApi';
import { ValidationError } from '#interfaces/error';
import verify from '#middlewares/auth';
import { validateZod } from '#middlewares/validators';
import { NotificationPreferenceUpdateSchema } from '#contracts/notification/schema';
import { NotificationPreferenceProvider } from '#providers/NotificationPreferenceProvider';
import { sendSuccess } from '#utils/responseUtils';

export default (_express: Application) => {
	const preferenceProvider = NotificationPreferenceProvider.getInstance();
	return <Resource>{
		get: {
			middleware: [verify],
			handler: async (req: Req, res: Res) => {
				try {
					const userId = req.user?.id as string;

					// P-03: Pass sortField/sortOrder so DB handles ordering instead of in-memory sort
					const preferences = await preferenceProvider.getAll({
						where: {
							user_id: userId,
						},
						sortField: 'notification_type',
						sortOrder: 'ASC',
					});

					return sendSuccess(
						res,
						preferences.rows.map((p: any) => p.toJSON()),
					);
				} catch (error) {
					return res.error(error);
				}
			},
		},
		put: {
			middleware: [verify, validateZod(NotificationPreferenceUpdateSchema)],
			handler: async (req: Req, res: Res) => {
				try {
					const userId = req.user?.id as string;
					const preferences = req.body;

					if (!Array.isArray(preferences)) {
						throw new ValidationError([
							{
								field: '',
								code: 'INVALID_TYPE',
								message: {
									vi: 'Request body phải là một mảng',
									en: 'Request body must be an array',
								},
							},
						]);
					}

					// Q-09: Run upserts concurrently instead of sequential loop (already using Promise.all)
					// For better performance, could use bulk upsert if DB supports it
					const updatedPreferences = await Promise.all(
						preferences.map(async (pref: any) => {
							const { notification_type, channel, is_enabled, quiet_hours_start, quiet_hours_end } = pref;

							// Check if preference exists
							const existing = await preferenceProvider.getOne({
								where: {
									user_id: userId,
									notification_type,
									channel,
								},
							});

							if (existing) {
								return preferenceProvider.put(existing.id, {
									is_enabled: is_enabled !== undefined ? is_enabled : existing.is_enabled,
									quiet_hours_start: quiet_hours_start !== undefined ? quiet_hours_start : existing.quiet_hours_start,
									quiet_hours_end: quiet_hours_end !== undefined ? quiet_hours_end : existing.quiet_hours_end,
									updated_at: new Date(),
								} as any);
							}

							return preferenceProvider.create({
								id: crypto.randomUUID(),
								user_id: userId,
								notification_type,
								channel,
								is_enabled: is_enabled !== undefined ? is_enabled : true,
								quiet_hours_start,
								quiet_hours_end,
								created_at: new Date(),
								updated_at: new Date(),
							});
						}),
					);

					return sendSuccess(
						res,
						updatedPreferences.map((p: any) => p.toJSON()),
					);
				} catch (error) {
					return res.error(error);
				}
			},
		},
	};
};
