defmodule Blockchain.Transaction.ReceiptTest do
  use ExUnit.Case, async: true
  doctest Blockchain.Transaction.Receipt
  alias Blockchain.Transaction.Receipt

  test "serilalize and deserialize" do
    receipt = %Receipt{
      state: <<1, 2, 3>>,
      cumulative_gas: 5,
      bloom_filter: <<2, 3, 4>>,
      logs: []
    }

    assert receipt ==
             receipt
             |> Receipt.serialize()
             |> ExRLP.encode()
             |> ExRLP.decode()
             |> Receipt.deserialize()
  end

  test "decodes receipt" do
    result =
      "f90162a02f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee83040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000"
      |> Base.decode16!(case: :mixed)
      |> ExRLP.decode()
      |> Receipt.deserialize()

    expected_receipt =
      Receipt.new(
        <<47, 105, 125, 103, 30, 154, 228, 238, 36, 164, 60, 75, 13, 126, 21, 241, 203, 75, 166,
          222, 21, 97, 18, 13, 67, 185, 164, 232, 196, 168, 166, 238>>,
        265_390,
        [
          %EVM.LogEntry{
            address:
              <<220, 244, 33, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26, 116, 8, 85, 167,
                151, 111>>,
            data:
              <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0>>,
            topics: []
          }
        ]
      )

    assert result == expected_receipt
  end

  test "encodes receipt" do
    expected_result =
      "f90162a02f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee83040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000"
      |> Base.decode16!(case: :mixed)

    result =
      <<47, 105, 125, 103, 30, 154, 228, 238, 36, 164, 60, 75, 13, 126, 21, 241, 203, 75, 166,
        222, 21, 97, 18, 13, 67, 185, 164, 232, 196, 168, 166, 238>>
      |> Receipt.new(
        265_390,
        [
          %EVM.LogEntry{
            address:
              <<220, 244, 33, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26, 116, 8, 85, 167,
                151, 111>>,
            data:
              <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0>>,
            topics: []
          }
        ]
      )
      |> Receipt.serialize()
      |> ExRLP.encode()

    assert expected_result == result
  end

  test "encodes receipt with multiple similar logs" do
    encoded =
      <<47, 105, 125, 103, 30, 154, 228, 238, 36, 164, 60, 75, 13, 126, 21, 241, 203, 75, 166,
        222, 21, 97, 18, 13, 67, 185, 164, 232, 196, 168, 166, 238>>
      |> Receipt.new(
        265_390,
        [
          %EVM.LogEntry{
            address:
              <<220, 244, 33, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26, 116, 8, 85, 167,
                151, 111>>,
            data:
              <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0>>,
            topics: []
          },
          %EVM.LogEntry{
            address:
              <<220, 244, 33, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26, 116, 8, 85, 167,
                151, 111>>,
            data:
              <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0>>,
            topics: []
          }
        ]
      )
      |> Receipt.serialize()
      |> ExRLP.encode()

    expectected_result =
      <<249, 1, 154, 160, 47, 105, 125, 103, 30, 154, 228, 238, 36, 164, 60, 75, 13, 126, 21, 241,
        203, 75, 166, 222, 21, 97, 18, 13, 67, 185, 164, 232, 196, 168, 166, 238, 131, 4, 12, 174,
        185, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 112, 247, 148, 220, 244,
        33, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26, 116, 8, 85, 167, 151, 111, 192, 160,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 247, 148, 220, 244, 33, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26, 116, 8, 85,
        167, 151, 111, 192, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>

    assert encoded == expectected_result
  end

  test "decodes receipt with multiple different logs" do
    encoded =
      <<47, 105, 125, 103, 30, 154, 228, 238, 36, 164, 60, 75, 13, 126, 21, 241, 203, 75, 166,
        222, 21, 97, 18, 13, 67, 185, 164, 232, 196, 168, 166, 238>>
      |> Receipt.new(
        265_390,
        [
          %EVM.LogEntry{
            address:
              <<220, 244, 33, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26, 116, 8, 85, 167,
                151, 111>>,
            data:
              <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0>>,
            topics: []
          },
          %EVM.LogEntry{
            address:
              <<13, 207, 65, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26, 116, 8, 85, 167,
                151, 111>>,
            data:
              <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0>>,
            topics: [
              <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 4, 12, 174>>
            ]
          }
        ]
      )
      |> Receipt.serialize()
      |> ExRLP.encode()

    expected_result =
      <<249, 1, 188, 160, 47, 105, 125, 103, 30, 154, 228, 238, 36, 164, 60, 75, 13, 126, 21, 241,
        203, 75, 166, 222, 21, 97, 18, 13, 67, 185, 164, 232, 196, 168, 166, 238, 131, 4, 12, 174,
        185, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 146, 247, 148, 220,
        244, 33, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26, 116, 8, 85, 167, 151, 111, 192,
        160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 248, 88, 148, 13, 207, 65, 208, 147, 66, 139, 9, 108, 165, 1, 167, 205, 26,
        116, 8, 85, 167, 151, 111, 225, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 12, 174, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>

    assert encoded == expected_result
  end

  test "calculates complex bloom filter during initialisation" do
    cumulative_gas = 48_790

    logs = [
      %EVM.LogEntry{
        address:
          <<15, 87, 46, 82, 149, 197, 127, 21, 136, 111, 155, 38, 62, 47, 109, 45, 108, 123, 94,
            198>>,
        data:
          <<255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0>>,
        topics: [
          <<9, 94, 123, 174, 166, 166, 199, 196, 194, 223, 235, 151, 126, 250, 195, 38, 175, 85,
            45, 135>>
        ]
      }
    ]

    state =
      <<147, 30, 199, 90, 63, 237, 39, 81, 172, 159, 26, 220, 75, 83, 5, 88, 68, 252, 10, 108,
        193, 83, 58, 133, 219, 127, 200, 198, 125, 64, 202, 3>>

    bloom = Receipt.new(state, cumulative_gas, logs).bloom_filter

    int_bloom = :binary.decode_unsigned(bloom)

    # credo:disable-for-lines:5
    assert int_bloom ==
             109_494_275_596_070_721_076_281_852_834_480_474_855_644_006_928_319_473_312_153_123_552_872_301_234_471_351_037_660_549_766_207_339_279_026_600_326_441_522_862_763_130_088_888_459_714_071_839_461_914_696_997_202_997_197_289_764_671_326_340_464_733_352_703_925_542_002_660_802_710_971_502_929_260_127_052_332_405_863_295_365_767_798_958_080_332_467_127_801_591_393_633_315_660_147_155_688_456_502_861_076_903_360_675_358_637_935_579_256_066_482_175_232_627_703_761_770_228_720_092_086_766_373_940_197_861_148_669_727_264_500_332_179_928_389_232_990_655_757_728_252_276_161_576_429_112_155_922_102_690_552_288_367_940_356_878_563_158_745_537_344_349_870_267_175_174_935_408_625_056_740_470_543_071_725_451_604_543_458_541_202_053_980_212_231_916_496_144_737_413_809_449_328_599_139_896_543_674_368
  end
end
