defmodule Towerops.HoneybadgerFilterTest do
  use ExUnit.Case, async: true

  alias Towerops.HoneybadgerFilter

  describe "filter_params/1" do
    test "filters SNMP community strings" do
      params = %{
        "name" => "Device 1",
        "snmp_community" => "public",
        "ip_address" => "192.168.1.1"
      }

      filtered = HoneybadgerFilter.filter_params(params)

      assert filtered["name"] == "Device 1"
      assert filtered["snmp_community"] == "[FILTERED]"
      assert filtered["ip_address"] == "192.168.1.1"
    end

    test "filters community strings with just 'community' key" do
      params = %{"community" => "secret123", "device_id" => "abc"}

      filtered = HoneybadgerFilter.filter_params(params)

      assert filtered["community"] == "[FILTERED]"
      assert filtered["device_id"] == "abc"
    end

    test "filters passwords" do
      params = %{"email" => "user@example.com", "password" => "secret"}

      filtered = HoneybadgerFilter.filter_params(params)

      assert filtered["email"] == "user@example.com"
      assert filtered["password"] == "[FILTERED]"
    end

    test "filters SNMPv3 credentials" do
      params = %{
        "snmp_version" => "3",
        "auth_password" => "authpass",
        "priv_password" => "privpass",
        "username" => "admin"
      }

      filtered = HoneybadgerFilter.filter_params(params)

      assert filtered["snmp_version"] == "3"
      assert filtered["auth_password"] == "[FILTERED]"
      assert filtered["priv_password"] == "[FILTERED]"
      assert filtered["username"] == "admin"
    end

    test "filters API keys and tokens" do
      params = %{
        "api_key" => "key123",
        "token" => "token456",
        "secret" => "secret789"
      }

      filtered = HoneybadgerFilter.filter_params(params)

      assert filtered["api_key"] == "[FILTERED]"
      assert filtered["token"] == "[FILTERED]"
      assert filtered["secret"] == "[FILTERED]"
    end

    test "filters nested params" do
      params = %{
        "device" => %{
          "name" => "Router",
          "snmp_community" => "private",
          "ip_address" => "10.0.0.1"
        }
      }

      filtered = HoneybadgerFilter.filter_params(params)

      assert filtered["device"]["name"] == "Router"
      assert filtered["device"]["snmp_community"] == "[FILTERED]"
      assert filtered["device"]["ip_address"] == "10.0.0.1"
    end

    test "filters atom keys" do
      params = %{
        name: "Device",
        snmp_community: "public",
        ip_address: "192.168.1.1"
      }

      filtered = HoneybadgerFilter.filter_params(params)

      assert filtered[:name] == "Device"
      assert filtered[:snmp_community] == "[FILTERED]"
      assert filtered[:ip_address] == "192.168.1.1"
    end

    test "handles case-insensitive filtering" do
      params = %{
        "SNMP_COMMUNITY" => "public",
        "SnmpCommunity" => "private",
        "API_KEY" => "secret"
      }

      filtered = HoneybadgerFilter.filter_params(params)

      assert filtered["SNMP_COMMUNITY"] == "[FILTERED]"
      assert filtered["SnmpCommunity"] == "[FILTERED]"
      assert filtered["API_KEY"] == "[FILTERED]"
    end

    test "does not filter non-sensitive data" do
      params = %{
        "name" => "Device",
        "ip_address" => "192.168.1.1",
        "description" => "Main router"
      }

      filtered = HoneybadgerFilter.filter_params(params)

      assert filtered == params
    end
  end

  describe "filter_context/1" do
    test "filters sensitive data from context params" do
      context = %{
        params: %{
          "device" => %{"snmp_community" => "public", "name" => "Router"}
        }
      }

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered.params["device"]["name"] == "Router"
      assert filtered.params["device"]["snmp_community"] == "[FILTERED]"
    end

    test "filters sensitive data from cgi_data" do
      context = %{
        cgi_data: %{"auth_token" => "Bearer token123", "user_agent" => "Mozilla/5.0"}
      }

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered.cgi_data["auth_token"] == "[FILTERED]"
      assert filtered.cgi_data["user_agent"] == "Mozilla/5.0"
    end

    test "filters ignored registered names" do
      context = %{registered_name: "memsup"}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters Redix connection errors (tcp_closed)" do
      context = %{reason: {:tcp_closed, :some_data}}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters Redix connection errors (econnrefused)" do
      context = %{reason: {:econnrefused, :some_data}}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters Redix errors by message" do
      context = %{message: "Redix connection failed"}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters DBConnection errors by exception" do
      context = %{reason: %DBConnection.ConnectionError{message: "connection lost"}}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters DBConnection errors by message" do
      context = %{message: "DBConnection timeout"}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters normal shutdown" do
      context = %{reason: :normal}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters shutdown" do
      context = %{reason: :shutdown}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters shutdown with reason" do
      context = %{reason: {:shutdown, :application_stopped}}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters port_died with :normal reason" do
      context = %{reason: {:port_died, :normal}}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end

    test "filters port_died with :shutdown reason" do
      context = %{reason: {:port_died, :shutdown}}

      filtered = HoneybadgerFilter.filter_context(context)

      assert filtered == nil
    end
  end
end
