import { Application } from 'express';
import { Resource } from 'express-automatic-routes';
import { Req, Res } from '#interfaces/IApi';
import { createRateLimit } from '#middlewares/auth';
import { validateZod } from '#middlewares/validators';
import {
	ResendVerificationBodySchema,
	type ResendVerificationResponseData,
} from '#contracts/auth/schema';
import { sendSuccess } from '#utils/responseUtils';
import { GenericError } from '#interfaces/error/generic';
import EmailVerificationService from '#services/auth/emailVerificationService';
import { User } from '#models/User';
import Logger from '#utils/logger';

/**
 * POST /api/v1/auth/resend-verification
 *
 * Re-sends the verification email for an unverified account. To avoid
 * leaking which emails are registered we always respond with the same shape
 * (sent=true) when the email doesn't exist or is already verified — the
 * caller can simply tell the user "if your email exists, we sent a link".
 *
 * Returns the verification expiry and the mail transport mode so debug
 * environments know whether the link was actually sent over SMTP or just
 * appended to dev-mail.log.
 */
export default (_express: Application) => {
	return <Resource>{
		post: {
			// Tight rate limit to avoid spam. 3 requests / 5 minutes / IP.
			middleware: [createRateLimit(5 * 60 * 1000, 3), validateZod(ResendVerificationBodySchema)] as any,
			handler: async (req: Req, res: Res) => {
				try {
					const { email } = req.body;
					const normalizedEmail = String(email).trim().toLowerCase();
					const user = await User.findOne({ where: { email: normalizedEmail } });

					// Generic 200 to avoid email enumeration
					if (!user) {
						const data: ResendVerificationResponseData = {
							sent: true,
							expires_at: null,
							email_mode: 'fallback',
							message:
								'Nếu email tồn tại trong hệ thống, một liên kết xác thực mới sẽ được gửi. / If the email exists, a new verification link will be sent.',
						};
						return sendSuccess(res, data);
					}

					try {
						const result = await EmailVerificationService.getInstance().resendVerificationEmail(user);
						const data: ResendVerificationResponseData = {
							sent: true,
							expires_at: result.expiresAt.toISOString(),
							email_mode: result.mode,
							message:
								'Email xác thực đã được gửi lại. Vui lòng kiểm tra hộp thư. / Verification email re-sent. Please check your inbox.',
						};
						return sendSuccess(res, data);
					} catch (innerErr) {
						if (innerErr instanceof GenericError && innerErr.code === 'USER_ALREADY_VERIFIED') {
							const data: ResendVerificationResponseData = {
								sent: true,
								expires_at: null,
								email_mode: 'fallback',
								message:
									'Email đã được xác thực trước đó. Bạn có thể đăng nhập ngay bây giờ. / This email has already been verified. You may log in now.',
							};
							return sendSuccess(res, data);
						}
						throw innerErr;
					}
				} catch (error) {
					Logger.warn(`[resend-verification] failed: ${(error as Error).message ?? error}`);
					return res.error(error);
				}
			},
		},
	};
};