import { Response, NextFunction } from 'express';
import { sanitizeFilename } from './validation';

// Validation rules (same as existing validation but for JSON)
const VALIDATION_RULES = {
  prompt: {
    minLength: 3,
    maxLength: 2000,
    required: true,
  },
  filename: {
    minLength: 1,
    maxLength: 100,
    required: true,
    pattern: /^[a-zA-Z0-9_-]+$/, // Only alphanumeric, underscore, hyphen
  },
};

// Valid aspect ratios supported by Gemini SDK
const VALID_ASPECT_RATIOS = [
  '1:1', // Square (1024x1024)
  '2:3', // Portrait (832x1248)
  '3:2', // Landscape (1248x832)
  '3:4', // Portrait (864x1184)
  '4:3', // Landscape (1184x864)
  '4:5', // Portrait (896x1152)
  '5:4', // Landscape (1152x896)
  '9:16', // Vertical (768x1344)
  '16:9', // Widescreen (1344x768)
  '21:9', // Ultrawide (1536x672)
] as const;

/**
 * Validate the text-to-image JSON request
 */
export const validateTextToImageRequest = (
  req: any,
  res: Response,
  next: NextFunction,
): void | Response => {
  const timestamp = new Date().toISOString();
  const { prompt, filename, aspectRatio, autoEnhance, enhancementOptions } = req.body;
  const errors: string[] = [];

  console.log(`[${timestamp}] [${req.requestId}] Validating text-to-image JSON request`);

  // Validate that request body exists
  if (!req.body || typeof req.body !== 'object') {
    return res.status(400).json({
      success: false,
      error: 'Request body must be valid JSON',
      message: 'Invalid request format',
    });
  }

  // Set defaults before validation
  // Default autoEnhance to true if not explicitly set
  if (req.body.autoEnhance === undefined) {
    req.body.autoEnhance = true;
  }

  // Default template to "photorealistic" in enhancementOptions
  if (req.body.enhancementOptions && !req.body.enhancementOptions.template) {
    req.body.enhancementOptions.template = 'photorealistic';
  } else if (!req.body.enhancementOptions && req.body.autoEnhance !== false) {
    // If autoEnhance is true (default) and no enhancementOptions, create it with default template
    req.body.enhancementOptions = { template: 'photorealistic' };
  }

  // Validate prompt
  if (!prompt) {
    errors.push('Prompt is required');
  } else if (typeof prompt !== 'string') {
    errors.push('Prompt must be a string');
  } else if (prompt.trim().length < VALIDATION_RULES.prompt.minLength) {
    errors.push(`Prompt must be at least ${VALIDATION_RULES.prompt.minLength} characters`);
  } else if (prompt.length > VALIDATION_RULES.prompt.maxLength) {
    errors.push(`Prompt must be less than ${VALIDATION_RULES.prompt.maxLength} characters`);
  }

  // Validate filename
  if (!filename) {
    errors.push('Filename is required');
  } else if (typeof filename !== 'string') {
    errors.push('Filename must be a string');
  } else if (filename.trim().length < VALIDATION_RULES.filename.minLength) {
    errors.push('Filename cannot be empty');
  } else if (filename.length > VALIDATION_RULES.filename.maxLength) {
    errors.push(`Filename must be less than ${VALIDATION_RULES.filename.maxLength} characters`);
  } else if (!VALIDATION_RULES.filename.pattern.test(filename)) {
    errors.push('Filename can only contain letters, numbers, underscores, and hyphens');
  }

  // Validate aspectRatio (optional, defaults to "1:1")
  if (aspectRatio !== undefined) {
    if (typeof aspectRatio !== 'string') {
      errors.push('aspectRatio must be a string');
    } else if (!VALID_ASPECT_RATIOS.includes(aspectRatio as any)) {
      errors.push(`Invalid aspectRatio. Must be one of: ${VALID_ASPECT_RATIOS.join(', ')}`);
    }
  }

  // Validate autoEnhance (optional boolean)
  if (autoEnhance !== undefined && typeof autoEnhance !== 'boolean') {
    errors.push('autoEnhance must be a boolean');
  }

  // Validate enhancementOptions (optional object)
  if (enhancementOptions !== undefined) {
    if (typeof enhancementOptions !== 'object' || Array.isArray(enhancementOptions)) {
      errors.push('enhancementOptions must be an object');
    } else {
      const { template } = enhancementOptions;

      // Validate template parameter
      if (
        template !== undefined &&
        ![
          'photorealistic',
          'illustration',
          'minimalist',
          'sticker',
          'product',
          'comic',
          'general',
        ].includes(template)
      ) {
        errors.push(
          'Invalid template in enhancementOptions. Must be one of: photorealistic, illustration, minimalist, sticker, product, comic, general',
        );
      }
    }
  }

  // Validate meta (optional object)
  if (req.body.meta !== undefined) {
    if (typeof req.body.meta !== 'object' || Array.isArray(req.body.meta)) {
      errors.push('meta must be an object');
    } else if (req.body.meta.tags !== undefined) {
      if (!Array.isArray(req.body.meta.tags)) {
        errors.push('meta.tags must be an array');
      } else {
        // Validate each tag is a string
        for (const tag of req.body.meta.tags) {
          if (typeof tag !== 'string') {
            errors.push('Each tag in meta.tags must be a string');
            break;
          }
        }
      }
    }
  }

  // Check for XSS attempts in prompt
  const xssPatterns = [/<script/i, /javascript:/i, /on\w+\s*=/i, /<iframe/i, /<object/i, /<embed/i];

  if (prompt && xssPatterns.some((pattern) => pattern.test(prompt))) {
    errors.push('Invalid characters detected in prompt');
  }

  // Log validation results
  if (errors.length > 0) {
    console.log(`[${timestamp}] [${req.requestId}] Validation failed: ${errors.join(', ')}`);
    return res.status(400).json({
      success: false,
      error: 'Validation failed',
      message: errors.join(', '),
    });
  }

  // Sanitize filename
  if (filename) {
    req.body.filename = sanitizeFilename(filename.trim());
    if (req.body.filename !== filename.trim()) {
      console.log(
        `[${timestamp}] [${req.requestId}] Filename sanitized: "${filename}" -> "${req.body.filename}"`,
      );
    }
  }

  // Trim and clean prompt
  if (prompt) {
    req.body.prompt = prompt.trim();
  }

  console.log(`[${timestamp}] [${req.requestId}] JSON validation passed`);
  next();
};

/**
 * Log text-to-image request details for debugging
 */
export const logTextToImageRequest = (req: any, _res: Response, next: NextFunction): void => {
  const timestamp = new Date().toISOString();
  const { prompt, filename, autoEnhance, enhancementOptions } = req.body;

  console.log(`[${timestamp}] [${req.requestId}] === TEXT-TO-IMAGE REQUEST ===`);
  console.log(`[${timestamp}] [${req.requestId}] Method: ${req.method}`);
  console.log(`[${timestamp}] [${req.requestId}] Path: ${req.path}`);
  console.log(`[${timestamp}] [${req.requestId}] Content-Type: ${req.get('Content-Type')}`);
  console.log(
    `[${timestamp}] [${req.requestId}] Prompt: "${prompt?.substring(0, 100)}${prompt?.length > 100 ? '...' : ''}"`,
  );
  console.log(`[${timestamp}] [${req.requestId}] Filename: "${filename}"`);
  console.log(`[${timestamp}] [${req.requestId}] Auto-enhance: ${autoEnhance || false}`);
  if (enhancementOptions) {
    console.log(`[${timestamp}] [${req.requestId}] Enhancement options:`, enhancementOptions);
  }
  console.log(`[${timestamp}] [${req.requestId}] Reference files: 0 (text-only endpoint)`);
  console.log(`[${timestamp}] [${req.requestId}] =====================================`);
  next();
};
