import { Request, Response, NextFunction } from 'express';
import { ParsedQs } from 'qs';
import { ParamsDictionary } from 'express-serve-static-core';

const isObject = (value: unknown): value is Record<string, unknown> =>
  typeof value === 'object' && value !== null && !Array.isArray(value);

const sanitizeValue = (value: unknown): unknown => {
  if (Array.isArray(value)) {
    return value.map(sanitizeValue);
  }

  if (isObject(value)) {
    const sanitized: Record<string, unknown> = {};
    for (const [key, val] of Object.entries(value)) {
      if (key.startsWith('$') || key.includes('.')) {
        continue;
      }
      sanitized[key] = sanitizeValue(val);
    }
    return sanitized;
  }

  if (typeof value === 'string') {
    return value.trim();
  }

  return value;
};

export const sanitizationMiddleware = (
  req: Request,
  _res: Response,
  next: NextFunction,
): void => {
  if (req.body) {
    req.body = sanitizeValue(req.body) as Record<string, unknown>;
  }
  if (req.query) {
    req.query = sanitizeValue(req.query) as ParsedQs;
  }
  if (req.params) {
    req.params = sanitizeValue(req.params) as ParamsDictionary;
  }
  next();
};
