import { logger } from '@goodgo/logger';
import { Request, Response, NextFunction } from 'express';
import { z, ZodError } from 'zod';

/**
 * EN: Middleware to validate request data using Zod schemas
 * VI: Middleware để validate dữ liệu request sử dụng Zod schemas
 *
 * @param schema - Zod schema to validate against / Schema Zod để validate
 * @param property - Request property to validate ('body', 'query', 'params') / Property request để validate
 */
export const validateDto = (schema: z.ZodTypeAny, property: 'body' | 'query' | 'params' = 'body') => {
  return (req: Request, res: Response, next: NextFunction) => {
    try {
      // EN: Sanitize input by trimming strings
      // VI: Sanitize input bằngcách trim strings
      const sanitizedData = sanitizeInput(req[property]);

      // EN: Validate the sanitized data
      // VI: Validate dữ liệu đã được sanitize
      const validatedData = schema.parse(sanitizedData);

      // EN: Replace the original data with validated data
      // VI: Thay thế dữ liệu gốc bằng dữ liệu đã validate
      (req as any)[property] = validatedData;

      logger.debug('Request validation successful / Validation request thành công', {
        property,
      });

      return next();
    } catch (error) {
      if (error instanceof ZodError) {
        logger.warn('Request validation failed / Validation request thất bại', {
          property,
          errors: error.issues, // Zod 4: error.errors → error.issues
          body: req.body,
        });

        // EN: Return structured validation error
        // VI: Trả về lỗi validation có cấu trúc
        return res.status(400).json({
          success: false,
          error: {
            code: 'VALIDATION_ERROR',
            message: 'Invalid request data / Dữ liệu request không hợp lệ',
            details: error.issues.map(err => ({
              field: err.path.join('.'),
              message: err.message,
              code: err.code,
            })),
          },
          timestamp: new Date().toISOString(),
        });
      }

      // EN: Handle unexpected errors
      // VI: Xử lý lỗi không mong muốn
      logger.error('Unexpected validation error / Lỗi validation không mong muốn', { error });
      return res.status(500).json({
        success: false,
        error: {
          code: 'INTERNAL_ERROR',
          message: 'Internal server error / Lỗi máy chủ nội bộ',
        },
        timestamp: new Date().toISOString(),
      });
    }
  };
};

/**
 * EN: Recursively sanitize input by trimming strings and cleaning data
 * VI: Sanitize input một cách đệ quy bằng cách trim strings và làm sạch dữ liệu
 */
function sanitizeInput(data: any): any {
  if (typeof data === 'string') {
    // EN: Trim whitespace and normalize
    // VI: Trim whitespace và normalize
    return data.trim();
  }

  if (Array.isArray(data)) {
    // EN: Sanitize array elements
    // VI: Sanitize các phần tử trong array
    return data.map(sanitizeInput);
  }

  if (data !== null && typeof data === 'object') {
    // EN: Sanitize object properties
    // VI: Sanitize các properties của object
    const sanitized: any = {};
    for (const [key, value] of Object.entries(data)) {
      sanitized[key] = sanitizeInput(value);
    }
    return sanitized;
  }

  // EN: Return primitive values as-is
  // VI: Trả về primitive values như nguyên bản
  return data;
}

// EN: Note: For multiple validations, chain validateDto middlewares in routes
// VI: Lưu ý: Cho multiple validations, chain validateDto middlewares trong routes