
# This is the complementary tutorial for tutorial 08. Sending nutzaps.
# Make sure tutorial 08 is running while testing this. Also make sure you lnbits config is set,
# or manually change the code to access a wallet to mint tokens.
# Check especially the code in line 76 and make sure to replace the npub with the one from
# the dvm in tutorial 8 in line 120.

from pathlib import Path

import dotenv
from nostr_sdk import PublicKey, Client, NostrSigner, EventBuilder, Kind, Tag, Keys, Timestamp, HandleNotification, \
    Filter, Event

import asyncio

from nostr_dvm.utils.definitions import EventDefinitions
from nostr_dvm.utils.dvmconfig import DVMConfig
from nostr_dvm.utils.nostr_utils import send_event, check_and_set_private_key
from nostr_dvm.utils.nut_wallet_utils import NutZapWallet
from nostr_dvm.utils.print_utils import bcolors


# You already know this from our previous test client in tutorial 03: We simply send a kind 5050 request
# to return some text, just as before. Note: Our dvm in tutorial 08 requires a payment of 3 sats.
async def nostr_client_generic_test(ptag):
    keys = Keys.parse(check_and_set_private_key("test_client"))
    relay_list = ["wss://nostr.oxtr.dev", "wss://relay.primal.net"]
    relaysTag = Tag.parse(["relays"] + relay_list)
    alttag = Tag.parse(["alt", "This is a NIP90 DVM AI task"])
    paramTag = Tag.parse(["param", "some_option", "#RUNDVM - With a Nutzap."])
    pTag = Tag.parse(["p", PublicKey.parse(ptag).to_hex()])
    tags = [relaysTag, alttag, pTag, paramTag]
    event = EventBuilder(Kind(5050), "This is a test",
                         tags).sign_with_keys(keys)

    client = Client(keys)
    for relay in relay_list:
        await client.add_relay(relay)
    await client.connect()
    result = await send_event(event, client=client, dvm_config=DVMConfig())
    print(result)


async def nostr_client(target_dvm_npub):

    keys = Keys.parse(check_and_set_private_key("test_client"))
    pk = keys.public_key()
    print(f"Nostr Client public key: {pk.to_bech32()}, Hex: {pk.to_hex()} ")
    client = Client(keys)

    dvmconfig = DVMConfig()
    for relay in dvmconfig.RELAY_LIST:
        await client.add_relay(relay)
    await client.connect()

    kinds = [EventDefinitions.KIND_NIP90_GENERIC]
    for kind in range(6000, 7001):
        if kind not in kinds:
            kinds.append(Kind(kind))

    dvm_filter = (Filter().kinds(kinds).since(Timestamp.now()).pubkey(pk))
    await client.subscribe([dvm_filter], None)

    # This will send a request to the DVM
    await nostr_client_generic_test(target_dvm_npub)

    # We listen to
    class NotificationHandler(HandleNotification):
        last_event_time = 0
        async def handle(self, relay_url, subscription_id, event: Event):
            if event.kind().as_u16() == 7000:
                print(bcolors.YELLOW + "[Nostr Client]: " + event.content() + bcolors.ENDC)
                amount_sats = 0
                status = ""
                for tag in event.tags().to_vec():
                    if tag.as_vec()[0] == "amount":
                        amount_sats = int(int(tag.as_vec()[1]) / 1000) # millisats
                    if tag.as_vec()[0] == "status":
                       status = tag.as_vec()[1]

                if status == "payment-required":
                    print("do a nutzap of " + str(amount_sats) +" sats here")

                    send_zap_amount = amount_sats
                    send_zap_message = "From my nutsack"
                    send_receiver = event.author().to_hex()
                    send_zapped_event = event.id().to_hex() # None  # None, or zap an event like this: Nip19Event.from_nostr_uri("nostr:nevent1qqsxq59mhz8s6aj9jzltcmqmmv3eutsfcpkeny2x755vdu5dtq44ldqpz3mhxw309ucnydewxqhrqt338g6rsd3e9upzp75cf0tahv5z7plpdeaws7ex52nmnwgtwfr2g3m37r844evqrr6jqvzqqqqqqyqtxyr6").event_id().to_hex()
                    zapped_event_id_hex = send_zapped_event
                    nutzap_wallet = NutZapWallet()
                    nut_wallet = await nutzap_wallet.get_nut_wallet(client, keys)

                    if nut_wallet is None:
                        relays = DVMConfig().NUTZAP_RELAYS
                        mints = DVMConfig().NUZAP_MINTS
                        await nutzap_wallet.create_new_nut_wallet(mints, relays, client, keys, "Test", "My Nutsack")
                        nut_wallet = await nutzap_wallet.get_nut_wallet(client, keys)
                        if nut_wallet is not None:
                            await nutzap_wallet.announce_nutzap_info_event(nut_wallet, client, keys)
                        else:
                            print("Couldn't fetch wallet, please restart and see if it is there")

                    await nutzap_wallet.send_nut_zap(send_zap_amount, send_zap_message, nut_wallet, zapped_event_id_hex, send_receiver, client,
                                       keys)

            elif 6000 < event.kind().as_u16() < 6999:
                print(bcolors.GREEN + "[Nostr Client]: " +  event.content() + bcolors.ENDC)


        async def handle_msg(self, relay_url, msg):
            return

    asyncio.create_task(client.handle_notifications(NotificationHandler()))
    # await client.handle_notifications(NotificationHandler())
    while True:
        await asyncio.sleep(2)


if __name__ == '__main__':

    env_path = Path('.env')
    if env_path.is_file():
        print(f'loading environment from {env_path.resolve()}')
        dotenv.load_dotenv(env_path, verbose=True, override=True)
    else:
        raise FileNotFoundError(f'.env file not found at {env_path} ')

    # Replace this key with the one from your DVM from part 8.
    target_dvm_npub = "npub150laafgrw4dlj5pc7jk2qzhxkghtqn9pplsyg8u6jkpd9afaszzsu06p39"
    asyncio.run(nostr_client(target_dvm_npub))