#!/usr/bin/env python3
# Copyright (c) 2024 The Bitcoin Unlimited developers
import asyncio
from test_framework.util import assert_equal, wait_for
from test_framework.electrumutil import (
    ElectrumTestFramework,
)
from test_framework.electrumconnection import ElectrumConnection


class ElectrumTokenHistoryTests(ElectrumTestFramework):
    async def run_test(self):
        # This test users nexad wallet to create and send tokens.
        # Mine and mature some coins.
        n = self.nodes[0]
        n.generate(120)

        cli = ElectrumConnection()
        await cli.connect()
        try:
            await self.sync_height(cli)
            await self.test_token_only(n, cli)
            await self.test_token_filter(n, cli)
        finally:
            cli.disconnect()

    async def test_token_only(self, n, cli):
        """
        Check that only transaction that transfer tokens are
        in the history.
        """
        mint_to_addr = n.getnewaddress()
        token_id, _ = await self.create_token(to_addr=mint_to_addr, mint_amount=100)
        addr = n.getnewaddress()
        addr_scripthash = await cli.call("blockchain.address.get_scripthash", addr)
        txid_send = await self.send_token(token_id, addr, 42)

        # This tx should not show up in token history
        n.sendtoaddress(addr, 21)

        await self.sync_mempool(cli)

        assert_equal(2, len(await cli.call("blockchain.address.get_history", addr)))
        token_history = await cli.call("token.address.get_history", addr)
        assert_equal(1, len(token_history["transactions"]))

        # These calls should provide same result
        assert_equal(token_history, await cli.call("token.address.get_mempool", addr))
        assert_equal(
            token_history,
            await cli.call("token.scripthash.get_history", addr_scripthash),
        )
        assert_equal(
            token_history,
            await cli.call("token.scripthash.get_mempool", addr_scripthash),
        )

        assert_equal(token_history["transactions"][0]["tx_hash"], txid_send)

        # Mine transactions
        n.generate(1)
        await self.sync_all(cli)
        assert_equal(
            0,
            len((await cli.call("token.address.get_mempool", addr))["transactions"]),
        )

        assert_equal(
            1,
            len((await cli.call("token.address.get_history", addr))["transactions"]),
        )

    async def test_token_filter(self, n, cli):
        """
        Check that we can filter on tokenID's
        """
        mint_to_addr = n.getnewaddress()
        token1_id, _ = await self.create_token(to_addr=mint_to_addr, mint_amount=100)
        token2_id, _ = await self.create_token(to_addr=mint_to_addr, mint_amount=100)

        addr = n.getnewaddress()
        await cli.call("blockchain.address.get_scripthash", addr)

        await self.send_token(token1_id, addr, 42)
        await self.send_token(token2_id, addr, 24)

        await self.sync_mempool(cli)

        # 2 transactions with 2 different tokens
        async def check_token_history_2():
            h = await cli.call("token.address.get_history", addr)
            return len(h["transactions"]) == 2

        await wait_for(10, check_token_history_2)

        # Filtering on one of the tokens should give 1 transaction
        async def check_token_history_filtered():
            h = await cli.call("token.address.get_history", addr, None, token1_id)
            return len(h["transactions"]) == 1

        await wait_for(10, check_token_history_filtered)


if __name__ == "__main__":
    asyncio.run(ElectrumTokenHistoryTests().main())
