import { randomInt } from 'crypto';
import { Application } from 'express';
import { Resource } from 'express-automatic-routes';
import { Req, Res } from '#interfaces/IApi';
import verify from '#middlewares/auth';
import { createRateLimit } from '#middlewares/auth';
import { storeConfirmOtp } from '#middlewares/sensitive-confirm';
import MailService from '#services/notification/notificationEmailService';
import { getConfirmOTPEmail } from '#templates/email/confirmOTP';
import LoggingService from '#services/file-system/logService';
import { sendSuccess } from '#utils/responseUtils';
import Config from '#config';

/** OTP TTL: 5 minutes */
const OTP_TTL_SECONDS = 300;
const OTP_TTL_MINUTES = OTP_TTL_SECONDS / 60;

/** Generate a cryptographically secure 6-digit numeric OTP */
function generateOtp(): string {
	return String(randomInt(100000, 1000000));
}

export default (_express: Application) => {
	const mailService = MailService.getInstance();
	const logger = new LoggingService();

	return <Resource>{
		post: {
			middleware: [verify, createRateLimit(15 * 60 * 1000, 5)] as any,
			handler: async (req: Req, res: Res) => {
				const { id: userId, email, username } = req.user!;
				const otp = generateOtp();
				await storeConfirmOtp(userId, otp, OTP_TTL_SECONDS);

				// Send via email (fire-and-forget — OTP is already persisted in Redis)
				mailService
					.sendmail({
						from: Config.email.from,
						to: email,
						subject: 'Mã xác nhận hành động - Action Confirmation Code',
						html: getConfirmOTPEmail({
							username: username || '',
							email,
							otp,
							expiresInMinutes: OTP_TTL_MINUTES,
						}),
					})
					.catch((error) => {
						console.error('Failed to send email confirmation OTP:', error);
						logger
							.logErrorAsync('SendConfirmOtp', error instanceof Error ? error : new Error(String(error)), null)
							.catch(() => {});
					});

				// eslint-disable-next-line no-restricted-syntax
				const isDev = process.env.NODE_ENV === 'development';

				return sendSuccess(res, {
					expiresInSeconds: OTP_TTL_SECONDS,
					...(isDev ? { otp } : {}),
				});
			},
		},
	};
};
