/**
 * Captcha verification middleware
 */

import type { CaptchaConfig } from "../config/captcha.js";
import { verifyCaptcha, getRemoteAddress } from "../utils/captcha.js";
import { createErrorResponse, HTTP_STATUS } from "../utils/response.js";
import { prisma } from "../config/database.js";

/**
 * Creates a captcha verification middleware for a specific verification point
 */
export function captchaMiddleware(config: CaptchaConfig, tokenField = "captchaToken") {
	return async (req: any, res: any, next: any) => {
		// If captcha is disabled, skip verification
		if (!config.enabled || config.provider === "none") {
			return next();
		}

		// Extract token from request
		// Check query params first (for GET requests like OAuth), then body, then headers
		const token = req.query[tokenField]
			|| req.body?.[tokenField]
			|| req.headers["x-captcha-token"]
			|| "";

		if (!token) {
			return res.status(HTTP_STATUS.BAD_REQUEST)
				.json(createErrorResponse("Captcha token required", HTTP_STATUS.BAD_REQUEST));
		}

		// Get remote IP for verification
		const remoteIp = getRemoteAddress(req);

		// Verify the captcha
		const verified = await verifyCaptcha(token, config, remoteIp);

		if (!verified) {
			return res.status(HTTP_STATUS.BAD_REQUEST)
				.json(createErrorResponse("Captcha verification failed", HTTP_STATUS.BAD_REQUEST));
		}

		// Verification successful, proceed
		return next();
	};
}

/**
 * Creates a conditional captcha middleware for paint endpoint
 * Only requires captcha every N paints based on config.paintInterval
 */
export function conditionalPaintCaptchaMiddleware(config: CaptchaConfig, tokenField = "captchaToken") {
	return async (req: any, res: any, next: any) => {
		// If captcha is disabled, skip verification
		if (!config.enabled || config.provider === "none") {
			return next();
		}

		// If no user is authenticated, skip (auth middleware will handle this)
		if (!req.user?.id) {
			return next();
		}

		// Get user's current paint count
		const user = await prisma.user.findUnique({
			where: { id: req.user.id },
			select: { paintsSinceCaptcha: true }
		});

		if (!user) {
			return next();
		}

		// Determine if captcha is required
		let captchaRequired = false;

		if (config.paintInterval === undefined || config.paintInterval === 0) {
			// Always require captcha if interval is 0 or not set
			captchaRequired = true;
		} else if (config.paintInterval > 0) {
			// Require captcha every N paints
			captchaRequired = user.paintsSinceCaptcha >= config.paintInterval;
		}

		// If captcha is not required yet, let them through and increment counter
		if (!captchaRequired) {
			// Store in request that we don't need to reset counter
			req.skipCaptchaCounterReset = true;
			return next();
		}

		// Captcha is required - verify token
		const token = req.query[tokenField]
			|| req.body?.[tokenField]
			|| req.headers["x-captcha-token"]
			|| "";

		if (!token) {
			return res.status(HTTP_STATUS.BAD_REQUEST)
				.json(createErrorResponse("Captcha token required", HTTP_STATUS.BAD_REQUEST));
		}

		// Get remote IP for verification
		const remoteIp = getRemoteAddress(req);

		// Verify the captcha
		const verified = await verifyCaptcha(token, config, remoteIp);

		if (!verified) {
			return res.status(HTTP_STATUS.BAD_REQUEST)
				.json(createErrorResponse("Captcha verification failed", HTTP_STATUS.BAD_REQUEST));
		}

		// Verification successful - mark that counter should be reset
		req.shouldResetCaptchaCounter = true;
		return next();
	};
}
