import secrets
import json
import urllib.parse
import base64
import time

from typing import Optional

import httpx
import qrcode
    
from nacl.public import PrivateKey, PublicKey, Box
from nacl.utils import random

from pytoniq_core import Cell, Builder

AMOUNT = 0.001

def generate_payload() -> str:
    return secrets.token_hex(32)

import base64
from pytoniq_core import Builder

def create_text_comment_payload(text: str) -> str:
    cell = (Builder()
            .store_uint(0, 32)
            .store_bytes(text.encode('utf-8'))
            .end_cell())
    
    boc_bytes = cell.to_boc()
    
    base64_str = base64.b64encode(boc_bytes).decode('utf-8')
    
    return base64_str

payload = generate_payload()

private_key = PrivateKey.generate()
public_key = private_key.public_key
session_id = public_key.encode().hex()

request_data = {
    "manifestUrl": "https://evrysomewhere.taild6c291.ts.net/tonconnect-manifest.json",
    "items": [
        {"name": "ton_addr"},
        {"name": "ton_proof", "payload": payload}
    ],
    "bridgeUrl": "https://bridge.tonapi.io/bridge"
}

request_string = json.dumps(request_data, separators=(",", ":"))
encoded_request = urllib.parse.quote(request_string)

link = f"tc://?v=2&id={session_id}&r={encoded_request}&ret=none"

qr = qrcode.make(link)
qr.save("qr.png") # type: ignore

authorized = False
with httpx.stream("GET", f"https://bridge.tonapi.io/bridge/events?client_id={session_id}", timeout=None) as res:
    for line in res.iter_lines():
        if line.startswith("data:"):
            json_data = line[5:].strip()
            
            if json_data:
                event = json.loads(json_data)

                wallet_pub_bytes = bytes.fromhex(event["from"])
                wallet_public_key = PublicKey(wallet_pub_bytes)

                encrypted_bytes = base64.b64decode(event["message"])
                nonce = encrypted_bytes[:24]
                ciphertext = encrypted_bytes[24:]

                box = Box(private_key, wallet_public_key)
                decrypted_bytes = box.decrypt(ciphertext, nonce)
                decrypted_json_string = decrypted_bytes.decode("utf-8")

                if not authorized:
                    print("[+] Кошелёк авторизован")
                    authorized = True

                    valid_until = int(time.time()) + 300
                    transaction_details = {
                        "valid_until": valid_until,
                        "messages": [
                            {
                                "address": "UQDOef853Umo2SvmAY11AGut0DOjj-sy759jUbr2RU4Ypc15",
                                "amount": str(int(AMOUNT * 10 ** 9))
                            }
                        ]
                    }

                    inner_json_string = json.dumps(transaction_details, separators=(",", ":"))

                    clear_body = {
                        "id": "1",
                        "method": "sendTransaction",
                        "params": [inner_json_string]
                    }

                    clear_bytes = json.dumps(clear_body, separators=(",", ":")).encode("utf-8")

                    send_nonce = random(24)
                    ciphertext = box.encrypt(clear_bytes, send_nonce).ciphertext
                    encrypted_packet = send_nonce + ciphertext

                    base64_message = base64.b64encode(encrypted_packet).decode("utf-8")

                    url = f"https://bridge.tonapi.io/bridge/message?client_id={session_id}&to={event["from"]}&ttl=300"

                    req = httpx.post(url, content=base64_message, headers={"Content-Type": "text/plain"})
                else:
                    print("[!] Кошелёк ответил на транзакцию")
                    ans = json.loads(decrypted_bytes.decode("utf-8"))
                    
                    
                    if "result" in ans:
                        boc_base64 = ans["result"]
                        boc_bytes = base64.b64decode(boc_base64)
                        
                        cell = Cell.one_from_boc(boc_bytes)

                        tx_hash = cell.hash.hex()
                        print(f"[+] Хеш транзакции: {tx_hash}")
                        print(f"    Проверить в эксплорере: https://tonviewer.com/transaction/{tx_hash}")
                        
                        print(f"[+] Cумма перевода: {AMOUNT} GRAM")
                    else:
                        print("[-] Транзакция отклонена пользователем")
                    
                    break
