const { body, query } = require('express-validator');
const { isMobilePhone } = require('validator');

// Common validation messages
const messages = {
  required: field => `${field} is required`,
  string: field => `${field} must be a string`,
  email: 'Please provide a valid email address',
  phone: 'Please provide a valid phone number',
  minLength: (field, min) => `${field} must be at least ${min} characters long`,
  maxLength: (field, max) => `${field} cannot exceed ${max} characters`,
  boolean: field => `${field} must be a boolean`,
  in: (field, values) => `${field} must be one of: ${values.join(', ')}`,
  array: field => `${field} must be an array`,
  object: field => `${field} must be an object`,
  numeric: field => `${field} must be a number`,
  min: (field, min) => `${field} must be at least ${min}`,
  max: (field, max) => `${field} cannot exceed ${max}`,
  mongoId: field => `${field} must be a valid MongoDB ID`,
};

// Validation for creating a delivery boy
exports.createDeliveryBoySchema = [
  body('name')
    .trim()
    .notEmpty().withMessage(messages.required('Name'))
    .isString().withMessage(messages.string('Name'))
    .isLength({ min: 2 }).withMessage(messages.minLength('Name', 2))
    .isLength({ max: 100 }).withMessage(messages.maxLength('Name', 100)),

  body('email')
    .trim()
    .notEmpty().withMessage(messages.required('Email'))
    .isEmail().withMessage(messages.email)
    .normalizeEmail(),

  body('phone')
    .trim()
    .notEmpty().withMessage(messages.required('Phone number'))
    .custom(value => isMobilePhone(value, 'any', { strictMode: false }))
    .withMessage(messages.phone),

  body('password')
    .notEmpty().withMessage(messages.required('Password'))
    .isString().withMessage(messages.string('Password'))
    .isLength({ min: 6 }).withMessage(messages.minLength('Password', 6)),

  body('store')
    .optional({ checkFalsy: true })
    .isMongoId().withMessage(messages.mongoId('Store ID')),

  body('isAvailable')
    .optional()
    .isBoolean().withMessage(messages.boolean('Availability')),

  body('status')
    .optional()
    .isIn(['active', 'inactive', 'on_leave'])
    .withMessage(messages.in('Status', ['active', 'inactive', 'on_leave'])),

  body('rating')
    .optional()
    .isNumeric().withMessage(messages.numeric('Rating'))
    .isFloat({ min: 0, max: 5 }).withMessage('Rating must be between 0 and 5'),

  body('location')
    .optional()
    .isObject().withMessage(messages.object('Location'))
    .custom((value) => {
      if (!value.coordinates || !Array.isArray(value.coordinates) || value.coordinates.length !== 2) {
        throw new Error('Location must have coordinates array with [longitude, latitude]');
      }
      const [longitude, latitude] = value.coordinates;
      if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) {
        throw new Error('Invalid coordinates. Longitude must be between -180 and 180, latitude between -90 and 90');
      }
      return true;
    }),

  body('documents')
    .optional()
    .isArray().withMessage(messages.array('Documents'))
    .custom((documents) => {
      if (!Array.isArray(documents)) return true;
      
      for (const doc of documents) {
        if (!doc.type || !['aadhar', 'license', 'rc', 'insurance', 'other'].includes(doc.type)) {
          throw new Error('Document type must be one of: aadhar, license, rc, insurance, other');
        }
        if (!doc.url) {
          throw new Error('Document URL is required for each document');
        }
      }
      return true;
    })
];

// Validation for updating a delivery boy
exports.updateDeliveryBoySchema = [
  body('name')
    .optional()
    .trim()
    .isString().withMessage(messages.string('Name'))
    .isLength({ min: 2 }).withMessage(messages.minLength('Name', 2))
    .isLength({ max: 100 }).withMessage(messages.maxLength('Name', 100)),

  body('email')
    .optional()
    .trim()
    .isEmail().withMessage(messages.email)
    .normalizeEmail(),

  body('phone')
    .optional()
    .trim()
    .custom(value => isMobilePhone(value, 'any', { strictMode: false }))
    .withMessage(messages.phone),

  body('password')
    .optional()
    .isString().withMessage(messages.string('Password'))
    .isLength({ min: 6 }).withMessage(messages.minLength('Password', 6)),

  body('store')
    .optional()
    .isMongoId().withMessage(messages.mongoId('Store ID')),

  body('isAvailable')
    .optional()
    .isBoolean().withMessage(messages.boolean('Availability')),

  body('status')
    .optional()
    .isIn(['active', 'inactive', 'on_leave'])
    .withMessage(messages.in('Status', ['active', 'inactive', 'on_leave'])),

  body('rating')
    .optional()
    .isNumeric().withMessage(messages.numeric('Rating'))
    .isFloat({ min: 0, max: 5 }).withMessage('Rating must be between 0 and 5'),

  body('location')
    .optional()
    .isObject().withMessage(messages.object('Location'))
    .custom((value) => {
      if (!value.coordinates || !Array.isArray(value.coordinates) || value.coordinates.length !== 2) {
        throw new Error('Location must have coordinates array with [longitude, latitude]');
      }
      const [longitude, latitude] = value.coordinates;
      if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) {
        throw new Error('Invalid coordinates. Longitude must be between -180 and 180, latitude between -90 and 90');
      }
      return true;
    }),

  body('documents')
    .optional()
    .isArray().withMessage(messages.array('Documents'))
    .custom((documents) => {
      if (!Array.isArray(documents)) return true;
      
      for (const doc of documents) {
        if (!doc.type || !['aadhar', 'license', 'rc', 'insurance', 'other'].includes(doc.type)) {
          throw new Error('Document type must be one of: aadhar, license, rc, insurance, other');
        }
        if (!doc.url) {
          throw new Error('Document URL is required for each document');
        }
      }
      return true;
    })
];

// Validation for updating delivery boy status
exports.updateStatusSchema = [
  body('status')
    .notEmpty().withMessage(messages.required('Status'))
    .isIn(['active', 'inactive', 'on_leave'])
    .withMessage(messages.in('Status', ['active', 'inactive', 'on_leave']))
];

// Validation for updating delivery boy availability
exports.updateAvailabilitySchema = [
  body('isAvailable')
    .notEmpty().withMessage(messages.required('Availability'))
    .isBoolean().withMessage(messages.boolean('Availability'))
];

// Validation for finding nearby delivery boys
exports.findNearbySchema = [
  query('longitude')
    .isFloat({ min: -180, max: 180 })
    .withMessage('Longitude must be between -180 and 180')
    .toFloat(),
    
  query('latitude')
    .isFloat({ min: -90, max: 90 })
    .withMessage('Latitude must be between -90 and 90')
    .toFloat(),
    
  query('maxDistance')
    .optional()
    .isInt({ min: 1, max: 100000 })
    .withMessage('Max distance must be between 1 and 100,000 meters')
    .toInt()
];
