import { Application } from 'express';
import { Resource } from 'express-automatic-routes';
import { Req, Res } from '#interfaces/IApi';
import { validateZod } from '#middlewares/validators';
import { sendSuccess } from '#utils/responseUtils';
import NotificationService from '#services/notification/notificationService';
import IdempotencyService from '#services/notification/idempotencyService';
import TemplateEngineService from '#services/notification/templateEngineService';
import { z } from 'zod';

// Schema for order-created event
const OrderCreatedEventSchema = z.object({
	order_id: z.string(),
	user_id: z.string(),
	customer_name: z.string().optional(),
	order_code: z.string().optional(),
	total_amount: z.number().optional(),
	currency: z.string().optional(),
});

// Schema for payment-failed event
const PaymentFailedEventSchema = z.object({
	payment_id: z.string(),
	user_id: z.string(),
	order_id: z.string().optional(),
	amount: z.number().optional(),
	error_code: z.string().optional(),
	error_message: z.string().optional(),
});

// Schema for chat-message event
const ChatMessageEventSchema = z.object({
	conversation_id: z.string(),
	sender_id: z.string(),
	receiver_id: z.string(),
	message: z.string(),
});

// Schema for security-alert event
const SecurityAlertEventSchema = z.object({
	user_id: z.string(),
	alert_type: z.enum(['login_from_new_device', 'password_changed', 'account_compromised', 'suspicious_activity']),
	ip_address: z.string().optional(),
	device_id: z.string().optional(),
	metadata: z.record(z.string(), z.any()).optional(),
});

export default (_express: Application) => {
	const notificationService = NotificationService.getInstance();
	const idempotencyService = IdempotencyService.getInstance();
	const templateEngine = TemplateEngineService.getInstance();

	return <Resource>{
		// Handle POST /internal/events/:eventType
		'/:eventType': {
			post: {
				middleware: [validateZod(z.any())],
				handler: async (req: Req, res: Res) => {
					try {
						const eventType = req.params.eventType;
						const idempotencyKey = req.headers['x-idempotency-key'] as string;
						const traceId = crypto.randomUUID();

						// Check idempotency key
						if (idempotencyKey) {
							const existing = await idempotencyService.check(idempotencyKey);
							if (existing) {
								const responseData = JSON.parse(existing.response_data);
								return sendSuccess(
									res,
									{
										success: true,
										idempotent: true,
										messageId: responseData.messageId,
										traceId: responseData.traceId,
									},
									'Event already processed (idempotent)',
									'Event already processed (idempotent)',
								);
							}
						}

						let notificationParams: any = {};

						switch (eventType) {
							case 'order-created': {
								const validated = OrderCreatedEventSchema.parse(req.body);
								// Use template engine (Phase 1.1)
								const locale = req.headers['accept-language']?.startsWith('vi') ? 'vi' : 'en';
								const template = await templateEngine.render({
									template_key: 'order_created',
									channel: 'in_app',
									variables: {
										customer_name: validated.customer_name || 'bạn',
										order_code: validated.order_code || validated.order_id,
										total_amount: validated.total_amount,
										currency: validated.currency || 'VND',
									},
									locale,
								});
								notificationParams = {
									userId: validated.user_id,
									title: template.title,
									body: template.body,
									type: 'order_created',
									channel: 'in_app',
									data: validated,
								};
								break;
							}

							case 'payment-failed': {
								const validated = PaymentFailedEventSchema.parse(req.body);
								const locale = req.headers['accept-language']?.startsWith('vi') ? 'vi' : 'en';
								const template = await templateEngine.render({
									template_key: 'payment_failed',
									channel: 'in_app',
									variables: {
										order_id: validated.order_id,
										amount: validated.amount,
										error_code: validated.error_code,
										error_message: validated.error_message,
									},
									locale,
								});
								notificationParams = {
									userId: validated.user_id,
									title: template.title,
									body: template.body,
									type: 'payment_failed',
									channel: 'in_app',
									priority: 1,
									data: validated,
								};
								break;
							}

							case 'chat-message': {
								const validated = ChatMessageEventSchema.parse(req.body);
								const locale = req.headers['accept-language']?.startsWith('vi') ? 'vi' : 'en';
								const template = await templateEngine.render({
									template_key: 'chat_message',
									channel: 'in_app',
									variables: {
										message: validated.message,
									},
									locale,
								});
								notificationParams = {
									userId: validated.receiver_id,
									title: template.title,
									body: template.body,
									type: 'chat_message',
									channel: 'in_app',
									data: validated,
								};
								break;
							}

							case 'security-alert': {
								const validated = SecurityAlertEventSchema.parse(req.body);
								const locale = req.headers['accept-language']?.startsWith('vi') ? 'vi' : 'en';
								const template = await templateEngine.render({
									template_key: 'security_alert',
									channel: 'in_app',
									variables: {
										alert_type: validated.alert_type,
										ip_address: validated.ip_address,
									},
									locale,
								});
								notificationParams = {
									userId: validated.user_id,
									title: template.title,
									body: template.body,
									type: 'security_alert',
									channel: 'in_app',
									priority: 1,
									data: validated,
								};
								break;
							}

							default:
								return res.status(400).json({
									success: false,
									message: `Unknown event type: ${eventType}`,
								});
						}

						notificationParams.traceId = traceId;

						// Create and queue notification
						const messages = await notificationService.createAndSend(notificationParams);

						if (!messages || messages.length === 0) {
							return res.status(500).json({
								success: false,
								message: 'Failed to create notification',
							});
						}

						// Store idempotency key
						if (idempotencyKey) {
							await idempotencyService.store(idempotencyKey, {
								messageId: messages[0]?.id,
								traceId,
							});
						}

						return sendSuccess(
							res,
							{
								success: true,
								messageId: messages[0]?.id,
								traceId,
								idempotent: false,
							},
							'Event processed successfully',
							'Event processed successfully',
						);
					} catch (error) {
						return res.error(error);
					}
				},
			},
		},
	};
};
