# frozen_string_literal: true

class GenerateWafRulesJob < ApplicationJob
  queue_as :waf_rules

  def perform(event_id:)
    event = Event.find(event_id)

    # Only analyze blocked events for rule generation
    return unless event.blocked?

    # Generate different types of rules based on patterns
    generate_ip_rules(event)
    generate_path_rules(event)
    generate_user_agent_rules(event)
    generate_parameter_rules(event)

    # Broadcast rule updates globally
    ActionCable.server.broadcast("rules", { type: "refresh" })

  rescue => e
    Rails.logger.error "Error generating WAF rules: #{e.message}"
    Rails.logger.error e.backtrace.join("\n")
  end

  private

  def generate_ip_rules(event)
    return unless event.ip_address.present?

    # Check if this IP has multiple violations
    violation_count = Event
      .by_ip(event.ip_address)
      .blocked
      .where(timestamp: 24.hours.ago..Time.current)
      .count

    # Log high-violation IPs - no automatic blocking without projects
    if violation_count >= 10
      Rails.logger.info "IP with high violation count: #{event.ip_address} (#{violation_count} violations in 24 hours)"
    end
  end

  def generate_path_rules(event)
    return unless event.request_path.present?

    # Look for repeated attack patterns on specific paths
    path_violations = project.events
      .where(request_path: event.request_path)
      .blocked
      .where(timestamp: 1.hour.ago..Time.current)
      .count

    # Suggest path rules if 20+ violations on same path
    if path_violations >= 20
      suggest_path_rule(project, event.request_path, path_violations)
    end
  end

  def generate_user_agent_rules(event)
    return unless event.user_agent.present?

    # Look for malicious user agents
    ua_violations = project.events
      .by_user_agent(event.user_agent)
      .blocked
      .where(timestamp: 1.hour.ago..Time.current)
      .count

    # Suggest user agent rules if 15+ violations from same UA
    if ua_violations >= 15
      suggest_user_agent_rule(project, event.user_agent, ua_violations)
    end
  end

  def generate_parameter_rules(event)
    params = event.query_params
    return unless params.present?

    # Look for suspicious parameter patterns
    params.each do |key, value|
      next unless value.is_a?(String)

      # Check for common attack patterns in parameter values
      if contains_attack_pattern?(value)
        param_violations = project.events
          .where("payload LIKE ?", "%#{key}%#{value}%")
          .blocked
          .where(timestamp: 6.hours.ago..Time.current)
          .count

        if param_violations >= 5
          suggest_parameter_rule(project, key, value, param_violations)
        end
      end
    end
  end

  def suggest_path_rule(project, path, violation_count)
    # Create an issue for manual review
    Issue.create!(
      project: project,
      title: "Suggested Path Rule",
      description: "Path '#{path}' has #{violation_count} violations in 1 hour",
      severity: "low",
      metadata: {
        type: "path_rule",
        path: path,
        violation_count: violation_count,
        suggested_action: "block"
      }
    )
  end

  def suggest_user_agent_rule(project, user_agent, violation_count)
    # Create an issue for manual review
    Issue.create!(
      project: project,
      title: "Suggested User Agent Rule",
      description: "User Agent '#{user_agent}' has #{violation_count} violations in 1 hour",
      severity: "low",
      metadata: {
        type: "user_agent_rule",
        user_agent: user_agent,
        violation_count: violation_count,
        suggested_action: "block"
      }
    )
  end

  def suggest_parameter_rule(project, param_name, param_value, violation_count)
    # Create an issue for manual review
    Issue.create!(
      project: project,
      title: "Suggested Parameter Rule",
      description: "Parameter '#{param_name}' with suspicious values has #{violation_count} violations",
      severity: "medium",
      metadata: {
        type: "parameter_rule",
        param_name: param_name,
        param_value: param_value,
        violation_count: violation_count,
        suggested_action: "block"
      }
    )
  end

  def contains_attack_pattern?(value)
    # Common attack patterns
    attack_patterns = [
      /<script/i,                    # XSS
      /union.*select/i,             # SQL injection
      /\.\./,                       # Directory traversal
      /\/etc\/passwd/i,             # File inclusion
      /cmd\.exe/i,                  # Command injection
      /eval\(/i,                    # Code injection
      /javascript:/i,               # JavaScript protocol
      /onload=/i,                   # Event handler injection
    ]

    attack_patterns.any? { |pattern| value.match?(pattern) }
  end
end