import { Bloom, Hash } from 'ox'
import { describe, expect, test } from 'vp/test'

describe('contains', () => {
  test('default', () => {
    expect(
      Bloom.contains(
        '0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
        '0xef2d6d194084c2de36e0dabfce45d046b37d1106',
      ),
    ).toBeTruthy()
    expect(
      Bloom.contains(
        '0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
        '0x02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc',
      ),
    ).toBeTruthy()
    expect(
      Bloom.contains(
        '0x00000000000000000000008000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000044000200000000000000000002000000000000000000000040000000000000000000000000000020000000000000000000800000000000800000000000800000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808002000000000400000000000000000000000060000000000000000000000000000000000000000000000100000000000002000000',
        '0xef2d6d194084c2de36e0dabfce45d046b37d1106',
      ),
    ).toBeFalsy()
    expect(
      Bloom.contains(
        '0x00000000000000000000008000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000044000200000000000000000002000000000000000000000040000000000000000000000000000020000000000000000000800000000000800000000000800000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808002000000000400000000000000000000000060000000000000000000000000000000000000000000000100000000000002000000',
        '0x02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc',
      ),
    ).toBeFalsy()
    expect(
      Bloom.contains(
        '0x00000000000000000000008000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000044000200000000000000000002000000000000000000000040000000000000000000000000000020000000000000000000800000000000800000000000800000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808002000000000400000000000000000000000060000000000000000000000000000000000000000000000100000000000002000000',
        '0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb',
      ),
    ).toBeTruthy()
  })

  test('error: rejects bloom of incorrect length', () => {
    expect(() =>
      Bloom.contains(
        '0xdeadbeef',
        '0xef2d6d194084c2de36e0dabfce45d046b37d1106',
      ),
    ).toThrowErrorMatchingInlineSnapshot(
      '[Bloom.InvalidBloomError: Value `0xdeadbeef` is not a valid bloom filter (must be a 256-byte hex string).]',
    )
  })

  test('error: rejects non-hex bloom', () => {
    expect(() =>
      Bloom.contains(
        'not-a-hex' as never,
        '0xef2d6d194084c2de36e0dabfce45d046b37d1106',
      ),
    ).toThrowErrorMatchingInlineSnapshot(
      '[Bloom.InvalidBloomError: Value `not-a-hex` is not a valid bloom filter (must be a 256-byte hex string).]',
    )
  })
})

describe('validate', () => {
  test('checks if bloom is valid', () => {
    expect(
      Bloom.validate('a5cc3c03994db5b0d9a5eEdD10Cabab0813678ac'),
    ).toBeFalsy()
    expect(
      Bloom.validate('0xa5cc3c03994db5b0d9a5eEdD10Cabab0813678ac'),
    ).toBeFalsy()
    expect(
      Bloom.validate(
        '0x000000000000000000008000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000044000200000000000000000002000000000000000000000040000000000000000000000000000020000000000000000000800000000000800000000000800000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808002000000000400000000000000000000000060000000000000000000000000000000000000000000000100000000000002000000',
      ),
    ).toBeFalsy()
    expect(
      Bloom.validate(
        '0x00000000000000000000008000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000044000200000000000000000002000000000000000000000040000000000000000000000000000020000000000000000000800000000000800000000000800000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808002000000000400000000000000000000000060000000000000000000000000000000000000000000000100000000000002000000',
      ),
    ).toBeTruthy()
  })
})

const matchingBloom =
  '0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' as const
const matchingAddress = '0xef2d6d194084c2de36e0dabfce45d046b37d1106' as const

describe('prepare + containsPrepared', () => {
  test('matches contains() for matching address', () => {
    const prepared = Bloom.prepare(matchingBloom)
    expect(Bloom.containsPrepared(prepared, matchingAddress)).toBe(
      Bloom.contains(matchingBloom, matchingAddress),
    )
  })

  test('throws for invalid bloom', () => {
    expect(() =>
      Bloom.prepare('0xdeadbeef'),
    ).toThrowErrorMatchingInlineSnapshot(
      '[Bloom.InvalidBloomError: Value `0xdeadbeef` is not a valid bloom filter (must be a 256-byte hex string).]',
    )
  })
})

describe('containsHash', () => {
  test('skips keccak when caller pre-hashes the input', () => {
    const prepared = Bloom.prepare(matchingBloom)
    const hash = Hash.keccak256(matchingAddress, { as: 'Bytes' })
    expect(Bloom.containsHash(prepared, hash)).toBe(true)
  })
})

test('exports', () => {
  expect(Object.keys(Bloom)).toMatchInlineSnapshot(`
    [
      "contains",
      "prepare",
      "containsPrepared",
      "containsHash",
      "validate",
      "InvalidBloomError",
    ]
  `)
})
