package io.emeraldpay.dshackle.upstream.polkadot

import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import org.assertj.core.api.Assertions
import org.junit.jupiter.api.Test

val example = """
{
    "block": {
      "header": {
        "parentHash": "0xb52a9b51fb698a891cf378b990b0b6a5743e52fa5175b44a8a6d4e0b2cfd0a53",
        "number": "0x1121bbc",
        "stateRoot": "0x66835be7bb9d6e698a6785f3c03215d468fa1feddce7b3c8c97e8313df7207ca",
        "extrinsicsRoot": "0x0103947815e820645daee747c608219f5745b0de688955a46816a7f016fc661f",
        "digest": {
          "logs": [
            "0x0642414245b50103f9000000722de01000000000d871116ec87ad9b8b45d73ccb9d1b7ba5fd11507dade591dcfa2559948b8314cbc20a9e0cfeedfafbb01dd9778bf3a57e426c83a668e79917952110fef280b01d452047028f36edb8a2e4983cc1207b06e638db5736a49203dcb678b882f1e0f",
            "0x05424142450101a056f81200f7ce9a09ffd3342648c54f8ecdf8045436ad27388947a41f681d33c2da0990c313b04d106b76d515e38f36540fb860927caf6f9f7c7e3d7233a88a"
          ]
        }
      },
      "extrinsics": [
        "0x280403000be01f29868b01",
        "[encoded data, 76482 characters]",
        "0x4102840088e9f05bf9ce1ae5cf584ba3d43982bccf957db3e97d781220e5ddbdb5de6a1501e2775e3339265fab8c47f900e1a3d627e77d5ab36b8f3ff7de4ae6c7c9a37769201dc94a19d7fa74afea15e802ea7285b0919d95b45c00c295d50f71adb6788c45011400050300066a8fcd5add9fdc97485581b00862bddc2f5c7fef7d0a64bb9052d8534ecd4507001ea6a752",
        "0x450284001c273165b790274c4232543b81ac6510525abe9ee8cb47b36544f371fb0cae49019c5677183aa6e23da0f9310ca90f7f6f0798a55d329cbccf36be7c64025f1407eafa798c5274203f66b604ced0c0bb4dc68e0e71db4d3f1d0599f29d4563b28945030c000503009cda5b3931d308d24e236f6e3ab5c50a99fd4922bd80f3a3b9bad5b0c8d93a350b009c62337201",
        "0xb9018400c0d998fb9f36dc65132dd06a845548d564e1db500fec59a8926a8fc75a8ba4460138f470ba7cdee1cd52271bf24456deb6ac041c33a081ec719704a578c1dd2d5feb99322b9de9276f683b70e7f592b4ff84c635e50fdd57f29e8ef6317f8621887503ac0007010300286bee"
      ]
    },
    "justifications": null
  }
""".trimIndent()

val healthOk = """{
    "peers": 16,
    "isSyncing": false,
    "shouldHavePeers": true
}
""".trimIndent()

val healthOk2 = """{
    "peers": 0,
    "isSyncing": false,
    "shouldHavePeers": false
}
""".trimIndent()

val healthBadPeers = """{
    "peers": 0,
    "isSyncing": false,
    "shouldHavePeers": true
}
""".trimIndent()

val healthBadSyncing = """{
    "peers": 16,
    "isSyncing": true,
    "shouldHavePeers": true
}
""".trimIndent()

class PolkadotChainSpecificTest {
    @Test
    fun parseResponse() {
        val result = PolkadotChainSpecific.parseBlock(example.toByteArray(), "1")

        Assertions.assertThat(result.height).isEqualTo(17963964)
        Assertions.assertThat(result.hash).isEqualTo(BlockId.from("0xb52a9b51fb698a891cf378b990b0b6a5743e52fa5175b44a8a6d4e0b2cfd0a53"))
        Assertions.assertThat(result.upstreamId).isEqualTo("1")
        Assertions.assertThat(result.parentHash).isEqualTo(BlockId.from("0xb52a9b51fb698a891cf378b990b0b6a5743e52fa5175b44a8a6d4e0b2cfd0a53"))
    }

    @Test
    fun validateHealth() {
        Assertions.assertThat(PolkadotChainSpecific.validate(healthOk.toByteArray(), 10, "test")).isEqualTo(
            UpstreamAvailability.OK,
        )
    }

    @Test
    fun validateHealthWithoutPeersOk() {
        Assertions.assertThat(PolkadotChainSpecific.validate(healthOk2.toByteArray(), 10, "test")).isEqualTo(
            UpstreamAvailability.OK,
        )
    }

    @Test
    fun validateHealthWithoutPeers() {
        Assertions.assertThat(PolkadotChainSpecific.validate(healthBadPeers.toByteArray(), 10, "test")).isEqualTo(
            UpstreamAvailability.IMMATURE,
        )
    }

    @Test
    fun validateHealthSyncing() {
        Assertions.assertThat(PolkadotChainSpecific.validate(healthBadSyncing.toByteArray(), 10, "test")).isEqualTo(
            UpstreamAvailability.SYNCING,
        )
    }
}
