const resp = require('../response.js');

const ORDER_DIRECTIONS = new Set(['ASC', 'DESC']);
const SAFE_COLUMN_PATTERN = /^[A-Za-z0-9_.\s-]+$/;

function toOptionalInt(value) {
    if (value === undefined || value === null || value === '') return undefined;
    const parsed = Number.parseInt(value, 10);
    return Number.isFinite(parsed) ? parsed : Number.NaN;
}

module.exports = (options = {}) => {
    const {
        requireEntId = false,
        maxLimit = 100,
        maxSearchLength = 200,
        maxColumnLength = 64
    } = options;

    return (req, res, next) => {
        const payload = req.body && typeof req.body === 'object' ? req.body : {};

        const rawCol = payload.col;
        if (rawCol !== undefined && rawCol !== null && rawCol !== '') {
            if (typeof rawCol !== 'string') {
                return res.status(400).json(resp('Validation Error', 'col must be a string', null, req, false));
            }
            const normalizedCol = rawCol.trim();
            if (!normalizedCol || normalizedCol.length > maxColumnLength || !SAFE_COLUMN_PATTERN.test(normalizedCol)) {
                return res.status(400).json(resp('Validation Error', 'Invalid col value', null, req, false));
            }
            req.body.col = normalizedCol;
        }

        const rawDir = payload.dir;
        if (rawDir !== undefined && rawDir !== null && rawDir !== '') {
            if (typeof rawDir !== 'string') {
                return res.status(400).json(resp('Validation Error', 'dir must be a string', null, req, false));
            }
            const normalizedDir = rawDir.trim().toUpperCase();
            if (!ORDER_DIRECTIONS.has(normalizedDir)) {
                return res.status(400).json(resp('Validation Error', 'dir must be ASC or DESC', null, req, false));
            }
            req.body.dir = normalizedDir;
        }

        const offset = toOptionalInt(payload.offset);
        if (offset !== undefined) {
            if (!Number.isInteger(offset) || offset < 0) {
                return res.status(400).json(resp('Validation Error', 'offset must be a non-negative integer', null, req, false));
            }
            req.body.offset = offset;
        }

        const limit = toOptionalInt(payload.limit);
        if (limit !== undefined) {
            if (!Number.isInteger(limit) || limit < 1 || limit > maxLimit) {
                return res.status(400).json(resp('Validation Error', `limit must be between 1 and ${maxLimit}`, null, req, false));
            }
            req.body.limit = limit;
        }

        if (payload.search !== undefined && payload.search !== null) {
            if (typeof payload.search !== 'string') {
                return res.status(400).json(resp('Validation Error', 'search must be a string', null, req, false));
            }
            const normalizedSearch = payload.search.trim();
            if (normalizedSearch.length > maxSearchLength) {
                return res.status(400).json(resp('Validation Error', `search exceeds max length ${maxSearchLength}`, null, req, false));
            }
            req.body.search = normalizedSearch;
        }

        if (requireEntId) {
            const entId = toOptionalInt(payload.ent_id);
            if (!Number.isInteger(entId) || entId < 1) {
                return res.status(400).json(resp('Validation Error', 'ent_id is required and must be a positive integer', null, req, false));
            }
            req.body.ent_id = entId;
        }

        return next();
    };
};