import { Application } from 'express';
import { Resource } from 'express-automatic-routes';
import { Req, Res } from '#interfaces/IApi';
import { createRateLimit } from '#middlewares/auth';
import { validateQueryZod } from '#middlewares/validators';
import {
	VerifyEmailQuerySchema,
	VerifyEmailResponseDataSchema,
	type VerifyEmailResponseData,
} from '#contracts/auth/schema';
import { sendSuccess } from '#utils/responseUtils';
import { GenericError } from '#interfaces/error/generic';
import EmailVerificationService from '#services/auth/emailVerificationService';
import { AuditLogService } from '#services/audit/auditLogService';
import { randomUUID } from 'crypto';

/**
 * GET /api/v1/auth/verify-email?token=...
 *
 * Public endpoint hit directly from the verification email link. Marks the
 * verification token as used and flips the user to `active` + sets
 * `email_verified_at`. Returns JSON describing the outcome so a SPA can show
 * a "verified!" screen and prompt the user to log in.
 */
export default (_express: Application) => {
	return <Resource>{
		get: {
			middleware: [createRateLimit(5 * 60 * 1000, 30), validateQueryZod(VerifyEmailQuerySchema)] as any,
			handler: async (req: Req, res: Res) => {
				try {
					const { token } = req.query as unknown as { token: string };
					const outcome = await EmailVerificationService.getInstance().verifyToken(String(token));

					if (outcome.kind === 'not_found') {
						throw new GenericError('VERIFICATION_TOKEN_INVALID');
					}
					if (outcome.kind === 'used') {
						throw new GenericError('VERIFICATION_TOKEN_INVALID', undefined, {
							vi: 'Liên kết xác thực đã được sử dụng trước đó. Bạn có thể đăng nhập ngay bây giờ.',
							en: 'This verification link was already used. You may log in now.',
						});
					}
					if (outcome.kind === 'expired') {
						throw new GenericError('VERIFICATION_TOKEN_EXPIRED');
					}

					// outcome.kind === 'ok' — fire-and-forget audit log
					AuditLogService.enqueueSystemAudit({
						requestId: randomUUID(),
						traceId: randomUUID(),
						actorId: outcome.user.id,
						actorName:
							`${outcome.user.first_name || ''} ${outcome.user.last_name || ''}`.trim() || outcome.user.email,
						actorEmail: outcome.user.email,
						actorRole: 'USER',
						action: 'EMAIL_VERIFIED',
						module: 'AUTH',
						entityId: outcome.user.id,
						entityType: 'User',
						description: `Email verified for ${outcome.user.email}`,
						severity: 'LOW',
					} as any).catch(() => {});

					const data: VerifyEmailResponseData = {
						verified: true,
						email: outcome.user.email,
						status: outcome.user.status ?? 'active',
						email_verified_at: outcome.user.email_verified_at
							? outcome.user.email_verified_at.toISOString()
							: new Date().toISOString(),
						message:
							'Email đã được xác thực thành công. Bạn có thể đăng nhập ngay bây giờ. / Email verified successfully. You may log in now.',
					};
					// Validate data matches the response schema (compile-time + runtime sanity)
					VerifyEmailResponseDataSchema.parse(data);
					return sendSuccess(res, data);
				} catch (error) {
					return res.error(error);
				}
			},
		},
	};
};