/**
 * Request Validation Middleware
 * Validates request body, query params, and route params
 */

import { ValidationError } from './errorHandler.mjs'

/**
 * Validation rules
 */
export const rules = {
  required: (field) => ({
    validate: (value) => value !== undefined && value !== null && value !== '',
    message: `${field} ist erforderlich`,
  }),

  email: () => ({
    validate: (value) => !value || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
    message: 'Ungültige E-Mail-Adresse',
  }),

  minLength: (field, min) => ({
    validate: (value) => !value || value.length >= min,
    message: `${field} muss mindestens ${min} Zeichen lang sein`,
  }),

  maxLength: (field, max) => ({
    validate: (value) => !value || value.length <= max,
    message: `${field} darf maximal ${max} Zeichen lang sein`,
  }),

  isIn: (field, values) => ({
    validate: (value) => !value || values.includes(value),
    message: `${field} muss einer der folgenden Werte sein: ${values.join(', ')}`,
  }),

  isNumber: (field) => ({
    validate: (value) => !value || !isNaN(Number(value)),
    message: `${field} muss eine Zahl sein`,
  }),

  isPositive: (field) => ({
    validate: (value) => !value || Number(value) > 0,
    message: `${field} muss positiv sein`,
  }),

  isArray: (field) => ({
    validate: (value) => !value || Array.isArray(value),
    message: `${field} muss ein Array sein`,
  }),

  isObject: (field) => ({
    validate: (value) => !value || (typeof value === 'object' && !Array.isArray(value)),
    message: `${field} muss ein Objekt sein`,
  }),
}

/**
 * Validate request against schema
 * @param {Object} schema - Validation schema { body: {}, query: {}, params: {} }
 */
export function validate(schema) {
  return (req, res, next) => {
    const errors = {}

    // Validate each part of the request
    for (const [location, fields] of Object.entries(schema)) {
      const data = req[location] || {}

      for (const [field, fieldRules] of Object.entries(fields)) {
        const value = data[field]
        const fieldErrors = []

        for (const rule of fieldRules) {
          if (!rule.validate(value)) {
            fieldErrors.push(rule.message)
          }
        }

        if (fieldErrors.length > 0) {
          errors[field] = fieldErrors
        }
      }
    }

    if (Object.keys(errors).length > 0) {
      return next(new ValidationError('Validierungsfehler', errors))
    }

    next()
  }
}

/**
 * Common validation schemas
 */
export const schemas = {
  // User registration
  register: {
    body: {
      email: [rules.required('E-Mail'), rules.email()],
      password: [rules.required('Passwort'), rules.minLength('Passwort', 8)],
    },
  },

  // Email connection
  connectEmail: {
    body: {
      userId: [rules.required('User ID')],
      provider: [rules.required('Provider'), rules.isIn('Provider', ['gmail', 'outlook'])],
      email: [rules.required('E-Mail'), rules.email()],
    },
  },

  // Checkout
  checkout: {
    body: {
      userId: [rules.required('User ID')],
      plan: [rules.required('Plan'), rules.isIn('Plan', ['basic', 'pro', 'business'])],
    },
  },

  // Email sorting
  sortEmails: {
    body: {
      userId: [rules.required('User ID')],
      accountId: [rules.required('Account ID')],
      maxEmails: [rules.isNumber('maxEmails'), rules.isPositive('maxEmails')],
    },
  },
}
