# frozen_string_literal: true

class WafPoliciesController < ApplicationController
  # Follow proper before_action order:
  # 1. Authentication/Authorization
  # All actions require authentication

  # 2. Resource loading
  before_action :set_waf_policy, only: [:show, :edit, :update, :destroy, :activate, :deactivate]

  # GET /waf_policies
  def index
    @pagy, @waf_policies = pagy(policy_scope(WafPolicy).includes(:user, :generated_rules).order(created_at: :desc))
    @policy_types = WafPolicy::POLICY_TYPES
    @actions = WafPolicy::ACTIONS
  end

  # GET /waf_policies/new
  def new
    authorize WafPolicy
    @waf_policy = WafPolicy.new
    @policy_types = WafPolicy::POLICY_TYPES
    @actions = WafPolicy::ACTIONS

    # Set default values from URL parameters
    @waf_policy.policy_type = params[:policy_type] if params[:policy_type].present?
    @waf_policy.policy_action = params[:policy_action] if params[:policy_action].present?
    @waf_policy.targets = params[:targets] if params[:targets].present?
  end

  # POST /waf_policies
  def create
    authorize WafPolicy
    @waf_policy = WafPolicy.new(waf_policy_params)
    @waf_policy.user = Current.user
    @policy_types = WafPolicy::POLICY_TYPES
    @actions = WafPolicy::ACTIONS

    if @waf_policy.save
      redirect_to @waf_policy, notice: 'WAF policy was successfully created.'
    else
      render :new, status: :unprocessable_entity
    end
  end

  # GET /waf_policies/:id
  def show
    @generated_rules = @waf_policy.generated_rules.includes(:network_range).order(created_at: :desc).limit(20)
    @effectiveness_stats = @waf_policy.effectiveness_stats
  end

  # GET /waf_policies/:id/edit
  def edit
    @policy_types = WafPolicy::POLICY_TYPES
    @actions = WafPolicy::ACTIONS
  end

  # PATCH/PUT /waf_policies/:id
  def update
    @policy_types = WafPolicy::POLICY_TYPES
    @actions = WafPolicy::ACTIONS

    if @waf_policy.update(waf_policy_params)
      redirect_to @waf_policy, notice: 'WAF policy was successfully updated.'
    else
      render :edit, status: :unprocessable_entity
    end
  end

  # DELETE /waf_policies/:id
  def destroy
    policy_name = @waf_policy.name

    # Soft delete by disabling and expiring the policy
    @waf_policy.update!(enabled: false, expires_at: Time.current)

    redirect_to waf_policies_url, notice: "WAF policy '#{policy_name}' was disabled."
  end

  # POST /waf_policies/:id/activate
  def activate
    @waf_policy.activate!

    redirect_to @waf_policy, notice: 'WAF policy was activated.'
  end

  # POST /waf_policies/:id/deactivate
  def deactivate
    @waf_policy.deactivate!

    redirect_to @waf_policy, notice: 'WAF policy was deactivated.'
  end

  # GET /waf_policies/new_country
  def new_country
    authorize WafPolicy
    @waf_policy = WafPolicy.new(policy_type: 'country', policy_action: 'deny')
    @policy_types = WafPolicy::POLICY_TYPES
    @actions = WafPolicy::ACTIONS
  end

  # POST /waf_policies/create_country
  def create_country
    authorize WafPolicy

    countries = params[:countries]&.reject(&:blank?) || []
    policy_action = params[:policy_action] || 'deny'

    if countries.empty?
      redirect_to new_country_waf_policies_path, alert: 'Please select at least one country.'
      return
    end

    # Build the options hash with additional_data if present
    options = {
      policy_action: policy_action,
      user: Current.user,
      description: params[:description]
    }

    # Add additional_data if provided (for redirect/challenge actions)
    if params[:additional_data].present?
      options[:additional_data] = params[:additional_data].to_unsafe_hash
    end

    @waf_policy = WafPolicy.create_country_policy(countries, **options)

    if @waf_policy.persisted?
      redirect_to @waf_policy, notice: "Country blocking policy was successfully created for #{countries.join(', ')}."
    else
      @policy_types = WafPolicy::POLICY_TYPES
      @actions = WafPolicy::ACTIONS
      render :new_country, status: :unprocessable_entity
    end
  end

  private

  def set_waf_policy
    # First try to find by ID (standard Rails behavior)
    if params[:id] =~ /^\d+$/
      @waf_policy = WafPolicy.find_by(id: params[:id])
    end

    # If not found by ID, try to find by parameterized name
    unless @waf_policy
      # Try direct parameterized comparison by parameterizing existing policy names
      @waf_policy = WafPolicy.all.find { |policy| policy.to_param == params[:id] }
    end

    if @waf_policy
      authorize @waf_policy
    else
      redirect_to waf_policies_path, alert: 'WAF policy not found.'
    end
  end

  def waf_policy_params
    params.require(:waf_policy).permit(
      :name,
      :description,
      :policy_type,
      :policy_action,
      :enabled,
      :expires_at,
      targets: [],
      additional_data: {}
    )
  end
end