import Joi from 'joi';
import { QRCodeAccessType, QRCodeStatus, QRCodeType } from '../types/qrcode.types';

export class QRCodeValidation {
  // Validation for creating a new QR code
  public static createQRCode = Joi.object({
    title: Joi.string().required().messages({
      'string.empty': 'Title is required',
    }),

    type: Joi.string()
      .valid(...Object.values(QRCodeType))
      .optional()
      .default('MEMORY_TAG')
      .messages({
        'any.only':
          'Type must be one of: MEMORY_TAG, MEDICAL_QR, CAR, LUGGAGE, PET, IDENTIFICATIONS, DOCUMENT, LINK, WIFI',
      }),

    // Standardized fields for all QR code types
    item_name: Joi.string().allow('', null).max(255).optional().messages({
      'string.max': 'Item name must not exceed 255 characters',
    }),

    item_description: Joi.string().allow('').optional(),

    // Option A1: explicit allow empty string
    images: Joi.alternatives()
      .try(
        Joi.array()
          .items(
            Joi.object({
              originalName: Joi.string().required().messages({
                'any.required': 'Original name is required for each image',
              }),
              filePath: Joi.string().required().messages({
                'any.required': 'File path is required for each image',
              }),
              mimeType: Joi.string()
                .valid(
                  'image/jpeg',
                  'image/jpg',
                  'image/png',
                  'image/gif',
                  'image/webp'
                )
                .required()
                .messages({
                  'any.only': 'Only JPEG, PNG, GIF, and WebP images are allowed',
                  'any.required': 'MIME type is required for each image',
                }),
              size: Joi.number()
                .max(10 * 1024 * 1024)
                .required()
                .messages({
                  'number.max': 'Image size must not exceed 10MB',
                  'any.required': 'Size is required for each image',
                }),
            })
          )
          .max(10)
          .messages({ 'array.max': 'Maximum 10 images allowed' }),
        Joi.valid(null),
        Joi.string().valid('') // <<< allow empty string as "no images"
      )
      .optional()
      .messages({ 'alternatives.match': 'Invalid image data format' }),

    // Location support for all QR code types
    location: Joi.object({
      latitude: Joi.number().min(-90).max(90).required().messages({
        'number.min': 'Latitude must be between -90 and 90',
        'number.max': 'Latitude must be between -90 and 90',
        'any.required': 'Latitude is required',
      }),
      longitude: Joi.number().min(-180).max(180).required().messages({
        'number.min': 'Longitude must be between -180 and 180',
        'number.max': 'Longitude must be between -180 and 180',
        'any.required': 'Longitude is required',
      }),
    })
      .optional()
      .when('location_enabled', {
        is: true,
        then: Joi.required(),
        otherwise: Joi.optional(),
      })
      .messages({
        'any.required': 'Location coordinates are required when location is enabled',
      }),

    location_enabled: Joi.boolean().optional().default(false).messages({
      'boolean.base': 'Location enabled must be a boolean value',
    }),

    // Type-specific details stored as JSON
    type_details: Joi.object().optional().messages({
      'object.base': 'Type details must be an object',
    }),

    car_details: Joi.object().optional().messages({
      'object.base': 'Type details must be an object',
    }),

    name: Joi.string().min(1).max(255).optional().messages({
      'string.min': 'Name must be at least 1 character long',
      'string.max': 'Name must not exceed 255 characters',
    }),

    description: Joi.string().max(1000).optional().messages({
      'string.max': 'Description must not exceed 1000 characters',
    }),

    lastKnownLocation: Joi.string().max(500).optional().messages({
      'string.max': 'Last known location must not exceed 500 characters',
    }),

    notes: Joi.string().max(1000).optional().messages({
      'string.max': 'Notes must not exceed 1000 characters',
    }),

    expired_at: Joi.date().min('now').optional().allow(null).messages({
      'date.min': 'Expiration date must be in the future',
    }),

    status: Joi.string()
      .valid(...Object.values(QRCodeStatus))
      .optional()
      .messages({
        'any.only': 'Status must be one of: ACTIVE, INACTIVE',
      }),

    access_type: Joi.string()
      .valid(...Object.values(QRCodeAccessType))
      .optional()
      .default('PUBLIC')
      .messages({
        'any.only': 'Access type must be one of: PUBLIC, PRIVATE',
      }),

    pin: Joi.string()
      .min(4)
      .max(50)
      .optional()
      .allow(null, '')
      .when('type', {
        is: 'MEDICAL_QR',
        then: Joi.required(),
        otherwise: Joi.when('access_type', {
          is: 'PRIVATE',
          then: Joi.required(),
          otherwise: Joi.optional(),
        }),
      })
      .messages({
        'string.min': 'PIN must be at least 4 characters long',
        'string.max': 'PIN must not exceed 50 characters',
        'any.required': 'PIN is required for medical QR codes and when access type is PRIVATE',
      }),

    color: Joi.optional(),

    background_color: Joi.optional(),

    size: Joi.optional(),

    privacy_controls: Joi.object({
      access_level: Joi.string()
        .valid('PUBLIC', 'RESTRICTED')
        .optional()
        .default('PUBLIC')
        .messages({
          'any.only': 'Access level must be either PUBLIC or RESTRICTED',
        }),

      access_password: Joi.string()
        .min(4)
        .max(50)
        .optional()
        .allow(null, '')
        .when('access_level', {
          is: 'RESTRICTED',
          then: Joi.when('...type', {
            is: 'MEDICAL_QR',
            then: Joi.optional(),
            otherwise: Joi.required(),
          }),
          otherwise: Joi.optional(),
        })
        .messages({
          'string.min': 'Access password must be at least 4 characters long',
          'string.max': 'Access password must not exceed 50 characters',
          'any.required':
            'Access password is required when access level is RESTRICTED (except for medical QR codes)',
        }),

      is_disabled: Joi.boolean().optional().default(false).messages({
        'boolean.base': 'Is disabled must be a boolean value',
      }),

      allow_anonymous_messaging: Joi.boolean().optional().default(false).messages({
        'boolean.base': 'Allow anonymous messaging must be a boolean value',
      }),

      emergency_notify: Joi.object({
        enabled: Joi.boolean().optional().default(false).messages({
          'boolean.base': 'Emergency notify enabled must be a boolean value',
        }),

        contact_email: Joi.string().email().optional(),

        contact_phone: Joi.string()
          .min(10)
          .max(15)
          .optional()
          .allow(null, '')
          .when('enabled', {
            is: true,
            then: Joi.required(),
            otherwise: Joi.optional(),
          })
          .messages({
            'string.min': 'Contact phone must be at least 10 characters long',
            'string.max': 'Contact phone must not exceed 15 characters',
            'any.required':
              'Contact phone is required when emergency notifications are enabled',
          }),
      })
        .optional()
        .default({ enabled: false })
        .messages({
          'object.base': 'Emergency notify must be an object',
        }),
    })
      .optional()
      .messages({
        'object.base': 'Privacy controls must be an object',
      }),

    memory_tag: Joi.object({
      location_enabled: Joi.boolean().optional().default(false).messages({
        'boolean.base': 'Location enabled must be a boolean value',
      }),

      location: Joi.object({
        latitude: Joi.number().min(-90).max(90).required().messages({
          'number.min': 'Latitude must be between -90 and 90',
          'number.max': 'Latitude must be between -90 and 90',
          'any.required': 'Latitude is required',
        }),

        longitude: Joi.number().min(-180).max(180).required().messages({
          'number.min': 'Longitude must be between -180 and 180',
          'number.max': 'Longitude must be between -180 and 180',
          'any.required': 'Longitude is required',
        }),
      })
        .optional()
        .when('location_enabled', {
          is: true,
          then: Joi.required(),
          otherwise: Joi.optional(),
        })
        .messages({
          'any.required': 'Location coordinates are required when location is enabled',
        }),

      images: Joi.array()
        .items(
          Joi.object({
            originalName: Joi.string().required().messages({
              'any.required': 'Original name is required for each image',
            }),
            filePath: Joi.string().required().messages({
              'any.required': 'File path is required for each image',
            }),
            mimeType: Joi.string()
              .valid('image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp')
              .required()
              .messages({
                'any.only': 'Only JPEG, PNG, GIF, and WebP images are allowed',
                'any.required': 'MIME type is required for each image',
              }),
            size: Joi.number()
              .max(10 * 1024 * 1024) // 10MB max
              .required()
              .messages({
                'number.max': 'Image size must not exceed 10MB',
                'any.required': 'Size is required for each image',
              }),
          })
        )
        .max(10)
        .optional()
        .messages({
          'array.max': 'Maximum 10 images allowed',
        }),
    })
      .optional()
      .when('type', {
        is: 'MEMORY_TAG',
        then: Joi.optional(),
        otherwise: Joi.forbidden(),
      })
      .messages({
        'any.unknown': 'Memory tag data is only allowed for MEMORY_TAG type QR codes',
      }),
  });

  // Validation for updating a QR code
  public static updateQRCode = Joi.object({
    title: Joi.string().min(1).max(255).optional().messages({
      'string.empty': 'Title cannot be empty',
      'string.min': 'Title must be at least 1 character long',
      'string.max': 'Title must not exceed 255 characters',
    }),

    type: Joi.string()
      .valid(...Object.values(QRCodeType))
      .optional()
      .messages({
        'any.only':
          'Type must be one of: MEMORY_TAG, MEDICAL_QR, CAR, LUGGAGE, PET, IDENTIFICATIONS, DOCUMENT, LINK, WIFI',
      }),

    // Standardized fields for all QR code types
    item_name: Joi.string().allow('', null).max(255).optional().messages({
      'string.max': 'Item name must not exceed 255 characters',
    }),

    item_description: Joi.string().allow('').optional(),

    images: Joi.array()
      .items(
        Joi.object({
          originalName: Joi.string().required().messages({
            'any.required': 'Original name is required for each image',
          }),
          filePath: Joi.string().required().messages({
            'any.required': 'File path is required for each image',
          }),
          mimeType: Joi.string()
            .valid('image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp')
            .required()
            .messages({
              'any.only': 'Only JPEG, PNG, GIF, and WebP images are allowed',
              'any.required': 'MIME type is required for each image',
            }),
          size: Joi.number()
            .max(10 * 1024 * 1024) // 10MB max
            .required()
            .messages({
              'number.max': 'Image size must not exceed 10MB',
              'any.required': 'Size is required for each image',
            }),
        })
      )
      .max(10)
      .optional()
      .messages({
        'array.max': 'Maximum 10 images allowed',
      }),

    // Location support for all QR code types
    location: Joi.object({
      latitude: Joi.number().min(-90).max(90).required().messages({
        'number.min': 'Latitude must be between -90 and 90',
        'number.max': 'Latitude must be between -90 and 90',
        'any.required': 'Latitude is required',
      }),
      longitude: Joi.number().min(-180).max(180).required().messages({
        'number.min': 'Longitude must be between -180 and 180',
        'number.max': 'Longitude must be between -180 and 180',
        'any.required': 'Longitude is required',
      }),
    })
      .optional()
      .when('location_enabled', {
        is: true,
        then: Joi.required(),
        otherwise: Joi.optional(),
      })
      .messages({
        'any.required': 'Location coordinates are required when location is enabled',
      }),

    location_enabled: Joi.boolean().optional().messages({
      'boolean.base': 'Location enabled must be a boolean value',
    }),

    // Type-specific details stored as JSON
    type_details: Joi.object().optional().messages({
      'object.base': 'Type details must be an object',
    }),

    name: Joi.string().min(1).max(255).optional().messages({
      'string.min': 'Name must be at least 1 character long',
      'string.max': 'Name must not exceed 255 characters',
    }),

    description: Joi.string().max(1000).optional().messages({
      'string.max': 'Description must not exceed 1000 characters',
    }),

    lastKnownLocation: Joi.string().max(500).optional().messages({
      'string.max': 'Last known location must not exceed 500 characters',
    }),

    notes: Joi.string().max(1000).optional().messages({
      'string.max': 'Notes must not exceed 1000 characters',
    }),

    expired_at: Joi.date().min('now').optional().allow(null).messages({
      'date.min': 'Expiration date must be in the future',
    }),

    status: Joi.string()
      .valid(...Object.values(QRCodeStatus))
      .optional()
      .messages({
        'any.only': 'Status must be one of: ACTIVE, INACTIVE',
      }),

    access_type: Joi.string()
      .valid(...Object.values(QRCodeAccessType))
      .optional()
      .messages({
        'any.only': 'Access type must be one of: PUBLIC, PRIVATE',
      }),

    pin: Joi.string()
      .min(4)
      .max(50)
      .optional()
      .allow(null, '')
      .when('type', {
        is: 'MEDICAL_QR',
        then: Joi.required(),
        otherwise: Joi.when('access_type', {
          is: 'PRIVATE',
          then: Joi.required(),
          otherwise: Joi.optional(),
        }),
      })
      .messages({
        'string.min': 'PIN must be at least 4 characters long',
        'string.max': 'PIN must not exceed 50 characters',
        'any.required': 'PIN is required for medical QR codes and when access type is PRIVATE',
      }),

    color: Joi.string()
      .pattern(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)
      .optional()
      .messages({
        'string.pattern.base':
          'Color must be a valid hex color (e.g., #000000 or #000)',
      }),

    background_color: Joi.string()
      .pattern(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)
      .optional()
      .messages({
        'string.pattern.base':
          'Background color must be a valid hex color (e.g., #FFFFFF or #FFF)',
      }),

    size: Joi.number().integer().min(100).max(1000).optional().messages({
      'number.min': 'Size must be at least 100 pixels',
      'number.max': 'Size must not exceed 1000 pixels',
    }),

    privacy_controls: Joi.object({
      access_level: Joi.string().valid('PUBLIC', 'RESTRICTED').optional().messages({
        'any.only': 'Access level must be either PUBLIC or RESTRICTED',
      }),

      access_password: Joi.string()
        .min(4)
        .max(50)
        .optional()
        .allow(null, '')
        .when('access_level', {
          is: 'RESTRICTED',
          then: Joi.when('...type', {
            is: 'MEDICAL_QR',
            then: Joi.optional(),
            otherwise: Joi.required(),
          }),
          otherwise: Joi.optional(),
        })
        .messages({
          'string.min': 'Access password must be at least 4 characters long',
          'string.max': 'Access password must not exceed 50 characters',
          'any.required':
            'Access password is required when access level is RESTRICTED (except for medical QR codes)',
        }),

      is_disabled: Joi.boolean().optional().messages({
        'boolean.base': 'Is disabled must be a boolean value',
      }),

      allow_anonymous_messaging: Joi.boolean().optional().messages({
        'boolean.base': 'Allow anonymous messaging must be a boolean value',
      }),

      emergency_notify: Joi.object({
        enabled: Joi.boolean().optional().messages({
          'boolean.base': 'Emergency notify enabled must be a boolean value',
        }),

        contact_email: Joi.string().email().optional().allow(null, '').messages({
          'string.email': 'Contact email must be a valid email address',
        }),

        contact_phone: Joi.string()
          .min(10)
          .max(15)
          .optional()
          .allow(null, '')
          .messages({
            'string.min': 'Contact phone must be at least 10 characters long',
            'string.max': 'Contact phone must not exceed 15 characters',
          }),
      })
        .optional()
        .messages({
          'object.base': 'Emergency notify must be an object',
        }),
    })
      .optional()
      .messages({
        'object.base': 'Privacy controls must be an object',
      }),

    memory_tag: Joi.object({
      location_enabled: Joi.boolean().optional().messages({
        'boolean.base': 'Location enabled must be a boolean value',
      }),

      location: Joi.object({
        latitude: Joi.number().min(-90).max(90).required().messages({
          'number.min': 'Latitude must be between -90 and 90',
          'number.max': 'Latitude must be between -90 and 90',
          'any.required': 'Latitude is required',
        }),

        longitude: Joi.number().min(-180).max(180).required().messages({
          'number.min': 'Longitude must be between -180 and 180',
          'number.max': 'Longitude must be between -180 and 180',
          'any.required': 'Longitude is required',
        }),
      })
        .optional()
        .when('location_enabled', {
          is: true,
          then: Joi.required(),
          otherwise: Joi.optional(),
        })
        .messages({
          'any.required': 'Location coordinates are required when location is enabled',
        }),

      images: Joi.array()
        .items(
          Joi.object({
            originalName: Joi.string().required().messages({
              'any.required': 'Original name is required for each image',
            }),
            filePath: Joi.string().required().messages({
              'any.required': 'File path is required for each image',
            }),
            mimeType: Joi.string()
              .valid('image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp')
              .required()
              .messages({
                'any.only': 'Only JPEG, PNG, GIF, and WebP images are allowed',
                'any.required': 'MIME type is required for each image',
              }),
            size: Joi.number()
              .max(10 * 1024 * 1024) // 10MB max
              .required()
              .messages({
                'number.max': 'Image size must not exceed 10MB',
                'any.required': 'Size is required for each image',
              }),
          })
        )
        .max(10)
        .optional()
        .messages({
          'array.max': 'Maximum 10 images allowed',
        }),
    }).optional(),
  });

  // Validation for QR code query parameters
  public static getQRCodes = Joi.object({
    page: Joi.number().integer().min(1).optional().default(1).messages({
      'number.min': 'Page must be at least 1',
    }),

    limit: Joi.number().integer().min(1).max(100).optional().default(10).messages({
      'number.min': 'Limit must be at least 1',
      'number.max': 'Limit must not exceed 100',
    }),
    search: Joi.string().min(1).optional().messages({
      'string.empty': 'Search cannot be empty',
      'string.min': 'Search must be at least 1 character long',
    }),
  });

  // Validation for updating Memory Tag location
  public static updateMemoryTagLocation = Joi.object({
    latitude: Joi.number().min(-90).max(90).required().messages({
      'number.min': 'Latitude must be between -90 and 90',
      'number.max': 'Latitude must be between -90 and 90',
      'any.required': 'Latitude is required',
    }),

    longitude: Joi.number().min(-180).max(180).required().messages({
      'number.min': 'Longitude must be between -180 and 180',
      'number.max': 'Longitude must be between -180 and 180',
      'any.required': 'Longitude is required',
    }),

    location_enabled: Joi.boolean().optional().default(true).messages({
      'boolean.base': 'Location enabled must be a boolean value',
    }),
  });

  // Validation for MongoDB ObjectId
  public static objectId = Joi.string()
    .pattern(/^[0-9a-fA-F]{24}$/)
    .required()
    .messages({
      'string.pattern.base': 'Invalid ID format',
      'any.required': 'ID is required',
    });

  // Validation for uploading Memory Tag images
  public static uploadMemoryTagImages = Joi.object({
    images: Joi.array()
      .items(
        Joi.object({
          originalName: Joi.string().required(),
          filePath: Joi.string().required(),
          mimeType: Joi.string()
            .valid('image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp')
            .required()
            .messages({
              'any.only': 'Only JPEG, PNG, GIF, and WebP images are allowed',
            }),
          size: Joi.number()
            .max(10 * 1024 * 1024) // 10MB max
            .required()
            .messages({
              'number.max': 'Image size must not exceed 10MB',
            }),
        })
      )
      .min(1)
      .max(10)
      .required()
      .messages({
        'array.min': 'At least 1 image is required',
        'array.max': 'Maximum 10 images allowed',
        'any.required': 'Images are required',
      }),
  });

  // Validation for removing Memory Tag image
  public static removeMemoryTagImage = Joi.object({
    qrcodeId: QRCodeValidation.objectId,
    imageId: QRCodeValidation.objectId,
  });

  // Validation for accessing private QR codes
  public static accessPrivateQRCode = Joi.object({
    pin: Joi.string().allow('').optional(),
  });

  // Validation for accessing restricted QR codes
  public static accessRestrictedQRCode = Joi.object({
    access_password: Joi.string().min(4).max(50).required().messages({
      'string.min': 'Access password must be at least 4 characters long',
      'string.max': 'Access password must not exceed 50 characters',
      'any.required': 'Access password is required for restricted QR codes',
    }),
  });

  // Validation for QR code analytics query
  public static getQRCodeAnalytics = Joi.object({
    qrcode_id: QRCodeValidation.objectId.optional(),
    date_from: Joi.date().iso().optional().messages({
      'date.format': 'Date from must be a valid ISO date',
    }),
    date_to: Joi.date().iso().min(Joi.ref('date_from')).optional().messages({
      'date.format': 'Date to must be a valid ISO date',
      'date.min': 'Date to must be after date from',
    }),
    group_by: Joi.string()
      .valid('day', 'week', 'month', 'year')
      .optional()
      .default('day')
      .messages({
        'any.only': 'Group by must be one of: day, week, month, year',
      }),
  });

  // Validation for bulk operations
  public static bulkUpdateQRCodes = Joi.object({
    qrcode_ids: Joi.array()
      .items(QRCodeValidation.objectId)
      .min(1)
      .max(50)
      .required()
      .messages({
        'array.min': 'At least 1 QR code ID is required',
        'array.max': 'Maximum 50 QR codes can be updated at once',
        'any.required': 'QR code IDs are required',
      }),
    updates: Joi.object({
      status: Joi.string()
        .valid(...Object.values(QRCodeStatus))
        .optional()
        .messages({
          'any.only': 'Status must be one of: ACTIVE, INACTIVE',
        }),
      access_type: Joi.string()
        .valid(...Object.values(QRCodeAccessType))
        .optional()
        .messages({
          'any.only': 'Access type must be one of: PUBLIC, PRIVATE',
        }),
    })
      .min(1)
      .required()
      .messages({
        'object.min': 'At least one update field is required',
        'any.required': 'Updates are required',
      }),
  });

  // Validation for QR code search
  public static searchQRCodes = Joi.object({
    query: Joi.string().min(1).max(100).required().messages({
      'string.min': 'Search query must be at least 1 character long',
      'string.max': 'Search query must not exceed 100 characters',
      'any.required': 'Search query is required',
    }),
    page: Joi.number().integer().min(1).optional().default(1).messages({
      'number.min': 'Page must be at least 1',
    }),
    limit: Joi.number().integer().min(1).max(50).optional().default(10).messages({
      'number.min': 'Limit must be at least 1',
      'number.max': 'Limit must not exceed 50',
    }),
    type: Joi.string()
      .valid(...Object.values(QRCodeType))
      .optional()
      .messages({
        'any.only':
          'Type must be one of: MEMORY_TAG, MEDICAL_QR, CAR, LUGGAGE, PET, IDENTIFICATIONS, DOCUMENT, LINK, WIFI',
      }),
    status: Joi.string()
      .valid(...Object.values(QRCodeStatus))
      .optional()
      .messages({
        'any.only': 'Status must be one of: ACTIVE, INACTIVE',
      }),
  });

  // Validation for QR code export
  public static exportQRCodes = Joi.object({
    format: Joi.string()
      .valid('json', 'csv', 'pdf')
      .optional()
      .default('json')
      .messages({
        'any.only': 'Export format must be one of: json, csv, pdf',
      }),
    qrcode_ids: Joi.array()
      .items(QRCodeValidation.objectId)
      .max(100)
      .optional()
      .messages({
        'array.max': 'Maximum 100 QR codes can be exported at once',
      }),
    filters: Joi.object({
      type: Joi.string()
        .valid(...Object.values(QRCodeType))
        .optional(),
      status: Joi.string()
        .valid(...Object.values(QRCodeStatus))
        .optional(),
      access_type: Joi.string()
        .valid(...Object.values(QRCodeAccessType))
        .optional(),
      date_from: Joi.date().iso().optional(),
      date_to: Joi.date().iso().min(Joi.ref('date_from')).optional(),
    }).optional(),
  });

  // Validation for QR code sharing
  public static shareQRCode = Joi.object({
    share_method: Joi.string()
      .valid('email', 'sms', 'link', 'social')
      .required()
      .messages({
        'any.only': 'Share method must be one of: email, sms, link, social',
        'any.required': 'Share method is required',
      }),
    recipients: Joi.array()
      .items(Joi.string().email())
      .when('share_method', {
        is: 'email',
        then: Joi.array().items(Joi.string().email()).required().min(1).max(10),
        otherwise: Joi.optional(),
      })
      .messages({
        'array.min': 'At least 1 recipient email is required',
        'array.max': 'Maximum 10 recipients allowed',
        'string.email': 'All recipients must be valid email addresses',
      }),
    phone_numbers: Joi.array()
      .items(Joi.string().min(10).max(15))
      .when('share_method', {
        is: 'sms',
        then: Joi.array().items(Joi.string().min(10).max(15)).required().min(1).max(5),
        otherwise: Joi.optional(),
      })
      .messages({
        'array.min': 'At least 1 phone number is required',
        'array.max': 'Maximum 5 phone numbers allowed',
        'string.min': 'Phone number must be at least 10 characters',
        'string.max': 'Phone number must not exceed 15 characters',
      }),
    message: Joi.string().max(500).optional().messages({
      'string.max': 'Message must not exceed 500 characters',
    }),
    include_qr_image: Joi.boolean().optional().default(true).messages({
      'boolean.base': 'Include QR image must be a boolean value',
    }),
  });

  // Validation for QR code duplication
  public static duplicateQRCode = Joi.object({
    title: Joi.string().min(1).max(255).optional().messages({
      'string.min': 'Title must be at least 1 character long',
      'string.max': 'Title must not exceed 255 characters',
    }),
    copy_memory_tag: Joi.boolean().optional().default(false).messages({
      'boolean.base': 'Copy memory tag must be a boolean value',
    }),
    copy_privacy_controls: Joi.boolean().optional().default(true).messages({
      'boolean.base': 'Copy privacy controls must be a boolean value',
    }),
  });
}
