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

  alias Towerops.LogFilter

  describe "filter_bandit_errors/2" do
    test "stops Bandit invalid HTTP version string errors" do
      log_event = %{
        level: :error,
        msg: {:string, "** (Bandit.HTTPError) Invalid HTTP version"}
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :stop
    end

    test "stops Bandit HTTP errors with additional context" do
      log_event = %{
        level: :error,
        msg: {:string, "Some context Bandit.HTTPError: Invalid HTTP version details"}
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :stop
    end

    test "ignores Bandit errors without 'Invalid HTTP version'" do
      log_event = %{
        level: :error,
        msg: {:string, "** (Bandit.HTTPError) Some other error"}
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "stops error reports containing Bandit.HTTPError" do
      log_event = %{
        level: :error,
        msg: {
          :report,
          %{
            label: {:error_logger, :error_report},
            report: [message: "** (Bandit.HTTPError) Connection error"]
          }
        }
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :stop
    end

    test "ignores error reports without Bandit.HTTPError" do
      log_event = %{
        level: :error,
        msg: {
          :report,
          %{
            label: {:error_logger, :error_report},
            report: [message: "Some other error"]
          }
        }
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "ignores error reports with non-binary message" do
      log_event = %{
        level: :error,
        msg: {
          :report,
          %{
            label: {:error_logger, :error_report},
            report: [message: {:atom, :some_error}]
          }
        }
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "ignores error reports with no message key" do
      log_event = %{
        level: :error,
        msg: {
          :report,
          %{
            label: {:error_logger, :error_report},
            report: [other_key: "value"]
          }
        }
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "ignores non-error level logs" do
      log_event = %{
        level: :info,
        msg: {:string, "** (Bandit.HTTPError) Invalid HTTP version"}
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "ignores non-string messages" do
      log_event = %{
        level: :error,
        msg: {:atom, :some_error}
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "ignores logs with unexpected structure" do
      log_event = %{
        level: :error
        # Missing :msg key
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "ignores empty map" do
      log_event = %{}

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "ignores warning level with Bandit error" do
      log_event = %{
        level: :warning,
        msg: {:string, "** (Bandit.HTTPError) Invalid HTTP version"}
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "stops error with Bandit.HTTPError and Invalid HTTP version (case sensitive)" do
      log_event = %{
        level: :error,
        msg: {:string, "Bandit.HTTPError: Invalid HTTP version"}
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :stop
    end

    test "ignores if only 'Bandit.HTTPError' present without 'Invalid HTTP version'" do
      log_event = %{
        level: :error,
        msg: {:string, "Bandit.HTTPError occurred"}
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end

    test "ignores if only 'Invalid HTTP version' present without 'Bandit.HTTPError'" do
      log_event = %{
        level: :error,
        msg: {:string, "Invalid HTTP version detected"}
      }

      assert LogFilter.filter_bandit_errors(log_event, []) == :ignore
    end
  end
end
