/**
 * Schema Validation Detection Utilities
 *
 * Functions for detecting schema validation patterns (zod, yup, joi, etc.)
 * and manual validation patterns.
 */

/**
 * Check if schema validation is applied near a JSON.parse call
 * Looks for zod, yup, joi, or similar validation patterns
 */
export function hasSchemaValidationNearby(content: string, lineNumber: number): boolean {
  const lines = content.split('\n')
  const start = Math.max(0, lineNumber - 5)
  const end = Math.min(lines.length, lineNumber + 10)
  const context = lines.slice(start, end).join('\n')

  const schemaValidationPatterns = [
    // Zod patterns
    /z\.(object|string|number|array|boolean)\s*\(/i,
    /\.parse\s*\(/i,
    /\.safeParse\s*\(/i,
    /schema\.parse/i,
    /Schema\.parse/i,
    // Yup patterns
    /yup\.(object|string|number|array|boolean)\s*\(/i,
    /\.validate\s*\(/i,
    /\.validateSync\s*\(/i,
    // Joi patterns
    /Joi\.(object|string|number|array|boolean)\s*\(/i,
    /\.validateAsync\s*\(/i,
    // Valibot patterns
    /v\.(object|string|number|array|boolean)\s*\(/i,
    // AJV patterns
    /ajv\.compile/i,
    /validate\s*\(\s*schema/i,
    // TypeBox patterns
    /Type\.(Object|String|Number|Array|Boolean)\s*\(/i,
    // Generic validation patterns
    /validateSchema/i,
    /schemaValidator/i,
    /parseAndValidate/i,
  ]

  return schemaValidationPatterns.some(p => p.test(context))
}

/**
 * Check if this file appears to have form/input validation elsewhere
 * (manual checks on body fields, type guards, etc.)
 */
export function hasManualValidation(content: string): boolean {
  const manualValidationPatterns = [
    // Type checking / type guards
    /typeof\s+\w+\s*[!=]==?\s*['"](?:string|number|boolean|object)['"]|Array\.isArray\s*\(/i,
    // Field existence checks followed by throws/returns
    /if\s*\(\s*!(?:body|data|input)\.\w+\s*\)\s*\{?\s*(throw|return)/i,
    // Property access with type assertion comments or inline validation
    /\b(body|data|input)\s*as\s+\w+/i, // Type assertion
    // Manual validation with error handling
    /if\s*\(\s*![\w.]+\s*\|\|\s*typeof\s+[\w.]+/i,
    // Using type predicates
    /is\w+\s*\([\w.]+\)/i, // isFoo(bar) pattern
  ]

  return manualValidationPatterns.some(p => p.test(content))
}

/**
 * Check if SQL query uses whitelist validation pattern
 * e.g., columns validated against allowedColumns array before use
 */
export function hasSQLWhitelistValidation(content: string, lineNumber: number): boolean {
  const lines = content.split('\n')
  const contextStart = Math.max(0, lineNumber - 20)
  const contextEnd = Math.min(lines.length, lineNumber + 5)
  const context = lines.slice(contextStart, contextEnd).join('\n')

  // Whitelist/allowlist validation patterns
  const whitelistPatterns = [
    // Array-based whitelists
    /allowed\w*\s*=\s*\[/i, // allowedColumns = [...]
    /whitelist\w*\s*=\s*\[/i, // whitelistFields = [...]
    /valid\w*\s*=\s*\[/i, // validColumns = [...]
    /\.filter\s*\([^)]*\.includes\s*\(/i, // .filter(c => allowed.includes(c))
    /\.includes\s*\([^)]*\)/i, // allowedColumns.includes(col)
    /\.every\s*\([^)]*\.includes/i, // columns.every(c => allowed.includes(c))
    /if\s*\(\s*!.*\.includes/i, // if (!allowed.includes(...))

    // Object-based whitelists (Record<string, string>)
    /\w+\s+in\s+\w*(?:sortable|allowed|valid|whitelist)\w*/i, // sorter in sortableFields
    /\w+\s+in\s+\w+Fields/i, // key in someFields
    /:\s*Record<string,\s*string>/i, // Type annotation: Record<string, string>
    /const\s+\w+Fields\s*:\s*\{[^}]*\}\s*=/i, // const xyzFields: {...} = (inline type)
    /const\s+\w+Fields\s*=\s*\{[^}]*\}/i, // const xyzFields = { ... }
    /if\s*\([^)]*\s+in\s+\w+Fields\s*\)/i, // if (x in yFields)
    /&&\s*\w+\s+in\s+\w+/i, // && sorter in sortableFields

    // Enum-based validation (ASC/DESC, etc.)
    /===?\s*['"](?:ASC|DESC)['"]/i, // === 'ASC' or === 'DESC'
    /===?\s*\w+\.(?:Asc|Desc|ASC|DESC)/i, // === SortType.Asc
    /toLowerCase\s*\(\s*\)\s*===?\s*\w+\.(?:asc|desc)/i, // .toLowerCase() === SortType.asc
  ]

  return whitelistPatterns.some(p => p.test(context))
}
