import os
import socket
import threading
import time
import re
import hashlib
import random
import json
from datetime import datetime
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from PIL import Image, ImageTk
import cv2


WALLET_VERSION = "2.3.0"

# Safe prime for 256-bit Diffie-Hellman Key Exchange (DHKE)
DH_PRIME = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
DH_GENERATOR = 2

def generate_dh_keys():
    """Generates standard DH private and public keys"""
    priv = random.randint(2, DH_PRIME - 2)
    pub = pow(DH_GENERATOR, priv, DH_PRIME)
    return priv, pub

def derive_shared_secret(our_priv, their_pub):
    """Computes Diffie-Hellman key exchange shared secret"""
    return pow(their_pub, our_priv, DH_PRIME)

def encrypt_payload(shared_secret, message_str):
    """Encrypts a message using a SHA-256 feedback stream cipher with a random IV"""
    key = hashlib.sha256(str(shared_secret).encode("utf-8")).digest()
    iv = bytes([random.randint(0, 255) for _ in range(16)])
    plaintext = message_str.encode("utf-8")
    ciphertext = bytearray()
    block_key = key
    for i in range(0, len(plaintext), 32):
        block_key = hashlib.sha256(block_key + iv).digest()
        chunk = plaintext[i:i+32]
        for j in range(len(chunk)):
            ciphertext.append(chunk[j] ^ block_key[j])
    return f"e2ee:{iv.hex()}:{ciphertext.hex()}"

def decrypt_payload(shared_secret, encrypted_str):
    """Decrypts a SHA-256 feedback stream cipher payload using derived key and IV"""
    if not encrypted_str.startswith("e2ee:"):
        return encrypted_str  # Not encrypted payload
    try:
        parts = encrypted_str.split(":")
        iv = bytes.fromhex(parts[1])
        ciphertext = bytes.fromhex(parts[2])
        key = hashlib.sha256(str(shared_secret).encode("utf-8")).digest()
        plaintext = bytearray()
        block_key = key
        for i in range(0, len(ciphertext), 32):
            block_key = hashlib.sha256(block_key + iv).digest()
            chunk = ciphertext[i:i+32]
            for j in range(len(chunk)):
                plaintext.append(chunk[j] ^ block_key[j])
        return plaintext.decode("utf-8")
    except Exception as e:
        return f"[E2EE Decryption Failed: {e}]"


class RpcClient:
    def __init__(self, host: str, port: int, token: str = ""):
        self.host = host
        self.port = port
        self.token = token.strip()

    def call(self, command: str, timeout: float = 12.0) -> str:
        wire = command.strip()
        if self.token:
            wire = f"{self.token} {wire}"
        try:
            with socket.create_connection((self.host, self.port), timeout=timeout) as s:
                s.sendall((wire + "\n").encode("utf-8"))
                data = s.recv(1048576)  # 1MB buffer for extreme getblocks grids and large data
                return data.decode("utf-8", errors="ignore").strip()
        except Exception as e:
            return f"error: {e}"


class AdditionWalletGUI:
    def __init__(self, root: tk.Tk):
        self.root = root
        self.root.title(f"ADDITION Wallet v{WALLET_VERSION}")
        self.root.geometry("1180x720")
        self.root.configure(bg="#0b0f19")

        # Set Global Combobox Popdown Option DB styles to resolve gray-on-white contrast issues
        self.root.option_add("*TCombobox*Listbox.background", "#161f30")
        self.root.option_add("*TCombobox*Listbox.foreground", "#ffffff")
        self.root.option_add("*TCombobox*Listbox.selectBackground", "#ef4444")
        self.root.option_add("*TCombobox*Listbox.selectForeground", "#ffffff")
        self.root.option_add("*TCombobox*Listbox.font", ("Segoe UI", 9))
        self.root.option_add("*TCombobox*Listbox.relief", "flat")
        self.root.option_add("*TCombobox*Listbox.borderWidth", "0")

        # Premium Dark Obsidian Color Palette with Warm Highlights
        self.bg_dark = "#0b0f19"
        self.card_dark = "#161f30"
        self.accent_red = "#ef4444"
        self.accent_amber = "#f59e0b"
        self.text_white = "#ffffff"
        self.text_gray = "#94a3b8"

        # Preloaded nodes list
        self.nodes = [
            {"name": "Local Node (Local RPC)", "host": "127.0.0.1", "port": 8546, "token": "cf9876543210fedcba0123456789abcd"},
            {"name": "Local Node (LAN RPC)", "host": "127.0.0.1", "port": 18545, "token": ""},
            {"name": "Production GCP Node", "host": "146.148.58.198", "port": 18545, "token": "cf9876543210fedcba0123456789abcd"},
            {"name": "Bootstrap Node A", "host": "104.197.8.21", "port": 18545, "token": ""}
        ]
        
        self.active_node_idx = 0
        node_cfg = self.nodes[self.active_node_idx]
        self.rpc = RpcClient(node_cfg["host"], node_cfg["port"], node_cfg["token"])

        self.current_address = ""
        self.current_pub = ""
        self.current_priv = ""
        
        # Local session Diffie-Hellman keys for message encryption
        self.dh_priv, self.dh_pub = generate_dh_keys()
        
        self.mining_loop_active = False
        self.master_password = None
        self.video_cap = None

        # Hide window during startup unlock / initialization prompts for maximum security
        self.root.withdraw()

        # Load persisted wallets keystore
        self.load_persisted_wallets()

        # Reveal the beautiful dashboard once successfully unlocked
        self.root.deiconify()

        self.style = ttk.Style()
        self.style.theme_use("clam")
        
        # Stylize standard elements for beautiful Obsidian theme
        self.style.configure(".", background=self.bg_dark, foreground=self.text_white)
        self.style.configure("TNotebook", background=self.bg_dark, borderwidth=0)
        self.style.configure("TNotebook.Tab", background=self.card_dark, foreground=self.text_gray, borderwidth=1, padding=[10, 5], font=("Segoe UI", 9, "bold"))
        self.style.map("TNotebook.Tab", background=[("selected", self.accent_red)], foreground=[("selected", "#ffffff")])
        self.style.configure("Treeview", background="#0c111d", foreground="white", fieldbackground="#0c111d", borderwidth=0, font=("Consolas", 9))
        self.style.configure("Treeview.Heading", background="#1e293b", foreground="white", relief="flat", font=("Segoe UI", 9, "bold"))

        # Combobox main field styling
        self.style.configure("TCombobox", fieldbackground="#080c14", background="#1e293b", foreground="#ffffff", bordercolor="#1e293b", arrowcolor="#ffffff")
        self.style.map("TCombobox", fieldbackground=[("readonly", "#080c14")], foreground=[("readonly", "#ffffff")])

        self._build_ui()
        self._start_poll_thread()

    def encrypt_keystore_data(self, wallets_list, password: str) -> dict:
        """Encrypts the wallets list into an Ethereum Keystore V3-like JSON format using AES-256-GCM"""
        salt = os.urandom(16)
        n = 16384
        r = 8
        p = 1
        dklen = 32
        
        # Derive symmetric encryption key
        key = hashlib.scrypt(password.encode("utf-8"), salt=salt, n=n, r=r, p=p, dklen=dklen)
        
        # Serialize data
        plaintext = json.dumps({"wallets": wallets_list}, indent=4).encode("utf-8")
        
        # Encrypt with AES-GCM
        aesgcm = AESGCM(key)
        nonce = os.urandom(12)
        ciphertext_with_tag = aesgcm.encrypt(nonce, plaintext, None)
        
        ciphertext = ciphertext_with_tag[:-16]
        tag = ciphertext_with_tag[-16:]
        
        return {
            "crypto": {
                "cipher": "aes-256-gcm",
                "ciphertext": ciphertext.hex(),
                "cipherparams": {
                    "iv": nonce.hex(),
                    "tag": tag.hex()
                },
                "kdf": "scrypt",
                "kdfparams": {
                    "n": n,
                    "r": r,
                    "p": p,
                    "dklen": dklen,
                    "salt": salt.hex()
                }
            },
            "version": 3
        }

    def decrypt_keystore_data(self, keystore_json: dict, password: str) -> list:
        """Decrypts an Ethereum Keystore V3-like JSON format using AES-256-GCM"""
        crypto = keystore_json["crypto"]
        if crypto["cipher"] != "aes-256-gcm":
            raise ValueError(f"Unsupported cipher: {crypto['cipher']}")
        if crypto["kdf"] != "scrypt":
            raise ValueError(f"Unsupported KDF: {crypto['kdf']}")
            
        ciphertext = bytes.fromhex(crypto["ciphertext"])
        iv = bytes.fromhex(crypto["cipherparams"]["iv"])
        tag = bytes.fromhex(crypto["cipherparams"]["tag"])
        
        kdfparams = crypto["kdfparams"]
        salt = bytes.fromhex(kdfparams["salt"])
        
        # Derive symmetric decryption key
        key = hashlib.scrypt(
            password.encode("utf-8"),
            salt=salt,
            n=kdfparams["n"],
            r=kdfparams["r"],
            p=kdfparams["p"],
            dklen=kdfparams["dklen"]
        )
        
        # Re-combine ciphertext and GCM tag
        ciphertext_with_tag = ciphertext + tag
        
        aesgcm = AESGCM(key)
        plaintext = aesgcm.decrypt(iv, ciphertext_with_tag, None)
        
        data = json.loads(plaintext.decode("utf-8"))
        return data.get("wallets", [])

    def load_persisted_wallets(self):
        """Loads labeled wallets from wallets.json file, supporting AES-256-GCM decryption and legacy migration"""
        self.wallets_file = "wallets.json"
        self.saved_wallets = []
        
        # Scenario 1: Keystore file does not exist. Initialize fresh.
        if not os.path.exists(self.wallets_file):
            import tkinter.simpledialog
            while True:
                pwd = tk.simpledialog.askstring(
                    "Initialize Keystore",
                    "No keystore found.\n\nPlease create a Master Password to secure your new quantum-resistant keystore:",
                    show="*"
                )
                if pwd is None:
                    messagebox.showerror("Security Enforcement", "A Master Password is required to initialize the secure wallet. Closing.")
                    self.root.destroy()
                    import sys
                    sys.exit(0)
                pwd = pwd.strip()
                if not pwd:
                    messagebox.showwarning("Validation Error", "Password cannot be empty. Please enter a valid password.")
                    continue
                pwd_confirm = tk.simpledialog.askstring(
                    "Confirm Password",
                    "Please confirm your new Master Password:",
                    show="*"
                )
                if pwd_confirm is None:
                    continue
                if pwd != pwd_confirm.strip():
                    messagebox.showerror("Error", "Passwords do not match. Please try again.")
                    continue
                
                # Setup master password and default miner wallet
                self.master_password = pwd
                self.saved_wallets = [
                    {
                        "label": "Main Miner Wallet (Default)",
                        "address": "e48d89a9efd7b844fae2398d16bd3ab8968cd5bb",
                        "pub": "b0841124bb0f81c4144d5f757775fffef3013692cc07ca9d5c1a6b1d1bc67cfec92e2122",
                        "priv": "e2e775df58dc180df35b4488fdcf22cb6a5c102a7e786b09dfae328e1d520bb2"
                    }
                ]
                self.save_wallets_to_disk()
                messagebox.showinfo("Success", "Keystore initialized and encrypted successfully with AES-256-GCM!")
                break
            return

        # Scenario 2: Keystore file exists. Load and parse it.
        try:
            with open(self.wallets_file, "r", encoding="utf-8") as f:
                data = json.load(f)
        except Exception as e:
            messagebox.showerror("Keystore Error", f"Failed to parse wallets.json: {e}\nPlease resolve the issue or remove the file to start fresh.")
            self.root.destroy()
            import sys
            sys.exit(0)

        # Check if the keystore file is encrypted
        if "crypto" in data:
            import tkinter.simpledialog
            attempts = 0
            while True:
                pwd = tk.simpledialog.askstring(
                    "Unlock Keystore",
                    "Enter Master Password to decrypt your AES-256-GCM secured keystore:",
                    show="*"
                )
                if pwd is None:
                    messagebox.showerror("Security Enforcement", "Keystore must be unlocked to run the wallet. Closing.")
                    self.root.destroy()
                    import sys
                    sys.exit(0)
                
                pwd = pwd.strip()
                try:
                    self.saved_wallets = self.decrypt_keystore_data(data, pwd)
                    self.master_password = pwd
                    break
                except Exception:
                    attempts += 1
                    if attempts >= 3:
                        messagebox.showerror("Security Lockout", "Incorrect password 3 times. Closing application for security.")
                        self.root.destroy()
                        import sys
                        sys.exit(0)
                    messagebox.showerror("Decryption Failed", f"Incorrect master password! ({3 - attempts} attempts remaining)")
                    continue
        else:
            # Scenario 3: Plain unencrypted legacy keystore format. Migrate immediately!
            import tkinter.simpledialog
            legacy_wallets = data.get("wallets", [])
            if not legacy_wallets:
                legacy_wallets = [
                    {
                        "label": "Main Miner Wallet (Default)",
                        "address": "e48d89a9efd7b844fae2398d16bd3ab8968cd5bb",
                        "pub": "b0841124bb0f81c4144d5f757775fffef3013692cc07ca9d5c1a6b1d1bc67cfec92e2122",
                        "priv": "e2e775df58dc180df35b4488fdcf22cb6a5c102a7e786b09dfae328e1d520bb2"
                    }
                ]
            
            messagebox.showinfo("Migration Required", "Legacy unencrypted keystore detected!\n\nFor security compliance, please create a new Master Password to encrypt your private keys with AES-256-GCM.")
            
            while True:
                pwd = tk.simpledialog.askstring(
                    "Create Master Password",
                    "Establish a new Master Password to secure your migrated keystore:",
                    show="*"
                )
                if pwd is None:
                    messagebox.showerror("Security Enforcement", "A Master Password is required to migrate the legacy keystore. Closing.")
                    self.root.destroy()
                    import sys
                    sys.exit(0)
                
                pwd = pwd.strip()
                if not pwd:
                    messagebox.showwarning("Validation Error", "Password cannot be empty.")
                    continue
                
                pwd_confirm = tk.simpledialog.askstring(
                    "Confirm Password",
                    "Please confirm your Master Password:",
                    show="*"
                )
                if pwd_confirm is None:
                    continue
                if pwd != pwd_confirm.strip():
                    messagebox.showerror("Error", "Passwords do not match. Please try again.")
                    continue
                
                # Encrypt and save migrated keystore
                self.master_password = pwd
                self.saved_wallets = legacy_wallets
                self.save_wallets_to_disk()
                messagebox.showinfo("Migration Complete", "Legacy keystore migrated to production-grade AES-256-GCM format successfully!")
                break

    def save_wallets_to_disk(self):
        """Saves current keystore memory to wallets.json encrypted with AES-256-GCM"""
        if not hasattr(self, "master_password") or not self.master_password:
            print("[Keystore Error] No master password to encrypt wallets on disk!")
            return
        try:
            encrypted_data = self.encrypt_keystore_data(self.saved_wallets, self.master_password)
            with open(self.wallets_file, "w", encoding="utf-8") as f:
                json.dump(encrypted_data, f, indent=4)
        except Exception as e:
            print(f"[Keystore Error] Could not encrypt/save wallets: {e}")

    def sync_selectors(self):
        """Refreshes Combobox displays for wallets keystore selection"""
        if hasattr(self, "wallet_selector"):
            labels = [f"{w['label']} ({w['address'][:8]}...)" for w in self.saved_wallets]
            self.wallet_selector["values"] = labels
            
            # Select first or matching
            for idx, w in enumerate(self.saved_wallets):
                if w["address"] == self.current_address:
                    self.wallet_selector.current(idx)
                    return
            if self.saved_wallets:
                self.wallet_selector.current(0)
                self.on_wallet_account_changed(None)

    def _build_ui(self):
        # 1. Header Frame (Operations Console completely removed)
        header = tk.Frame(self.root, bg="#111217", height=60)
        header.pack(fill="x")

        # Load dynamic logo banner professionally if it exists in Assets
        script_dir = os.path.dirname(os.path.abspath(__file__))
        logo_path = os.path.join(script_dir, "Assets", "Addition Head logo.png")
        logo_loaded = False
        
        if os.path.exists(logo_path):
            try:
                img = Image.open(logo_path)
                # Aspect ratio is 963x190. Resized to 223x44 to fit compact header
                img_resized = img.resize((223, 44), Image.Resampling.LANCZOS)
                self.header_logo_img = ImageTk.PhotoImage(img_resized)
                
                logo_lbl = tk.Label(header, image=self.header_logo_img, bg="#111217")
                logo_lbl.pack(side="left", padx=15, pady=8)
                logo_loaded = True
            except Exception as e:
                print(f"[UI Warning] Could not load logo image: {e}")

        if not logo_loaded:
            title_lbl = tk.Label(
                header,
                text="ADDITION L1 Wallet",
                bg="#111217",
                fg=self.accent_red,
                font=("Segoe UI", 18, "bold"),
                padx=15,
                pady=10
            )
            title_lbl.pack(side="left")

        # Active Node Selector
        self.node_lbl = tk.Label(
            header,
            text="Active Node Selector:",
            bg="#111217",
            fg=self.text_gray,
            font=("Segoe UI", 9)
        )
        self.node_lbl.pack(side="left", padx=(15, 6))

        self.node_selector = ttk.Combobox(
            header,
            values=[n["name"] for n in self.nodes],
            width=26,
            state="readonly"
        )
        self.node_selector.current(self.active_node_idx)
        self.node_selector.bind("<<ComboboxSelected>>", self.on_node_changed)
        self.node_selector.pack(side="left", pady=10)

        # Language Selector
        self.lang_lbl = tk.Label(
            header,
            text="Language:",
            bg="#111217",
            fg=self.text_gray,
            font=("Segoe UI", 9)
        )
        self.lang_lbl.pack(side="left", padx=(15, 6))

        self.lang_selector = ttk.Combobox(
            header,
            values=["EN", "FR"],
            width=5,
            state="readonly"
        )
        self.active_lang = "en"
        self.lang_selector.current(0)
        self.lang_selector.bind("<<ComboboxSelected>>", self.on_language_changed)
        self.lang_selector.pack(side="left", pady=10)

        self.status_label = tk.Label(
            header,
            text="● CONNECTING...",
            bg="#111217",
            fg=self.accent_amber,
            font=("Consolas", 10, "bold"),
            padx=20
        )
        self.status_label.pack(side="right")

        # 2. Main Tabs Notebook
        self.tabs = ttk.Notebook(self.root)
        self.tabs.pack(fill="both", expand=True, padx=16, pady=(6, 2))

        self.tab_dashboard = tk.Frame(self.tabs, bg=self.bg_dark)
        self.tab_send = tk.Frame(self.tabs, bg=self.bg_dark)
        self.tab_mine = tk.Frame(self.tabs, bg=self.bg_dark)
        self.tab_token = tk.Frame(self.tabs, bg=self.bg_dark)
        self.tab_contract = tk.Frame(self.tabs, bg=self.bg_dark)
        self.tab_privacy = tk.Frame(self.tabs, bg=self.bg_dark)
        self.tab_messaging = tk.Frame(self.tabs, bg=self.bg_dark)
        self.tab_cli = tk.Frame(self.tabs, bg=self.bg_dark)
        self.tab_explorer = tk.Frame(self.tabs, bg=self.bg_dark)
        self.tab_docs = tk.Frame(self.tabs, bg=self.bg_dark)

        self.tabs.add(self.tab_dashboard, text="Dashboard")
        self.tabs.add(self.tab_send, text="Send & Stake")
        self.tabs.add(self.tab_mine, text="CPU Miner")
        self.tabs.add(self.tab_token, text="Token Factory")
        self.tabs.add(self.tab_contract, text="Smart Contract VM")
        self.tabs.add(self.tab_privacy, text="ZK-Shield Privacy")
        self.tabs.add(self.tab_messaging, text="E2EE Messaging")
        self.tabs.add(self.tab_cli, text="Advanced CLI")
        self.tabs.add(self.tab_explorer, text="Block Explorer")
        self.tabs.add(self.tab_docs, text="Developer Guides")

        self._build_dashboard_tab()
        self._build_send_tab()
        self._build_mine_tab()
        self._build_token_tab()
        self._build_contract_tab()
        self._build_privacy_tab()
        self._build_messaging_tab()
        self._build_cli_tab()
        self._build_explorer_tab()
        self._build_docs_tab()

        # 3. Branding Footer
        footer = tk.Frame(self.root, bg="#111217", height=24)
        footer.pack(fill="x", side="bottom")
        
        self.footer_lbl = tk.Label(
            footer,
            text="By Addison Electronique Enterprise inc",
            bg="#111217",
            fg="#ffffff",
            font=("Segoe UI", 8, "bold"),
            pady=2
        )
        self.footer_lbl.pack(anchor="center")

        # Sync keystore wallets dropdown
        self.sync_selectors()

    def on_language_changed(self, event=None):
        self.active_lang = self.lang_selector.get().lower()
        self.translate_gui()

    def translate_gui(self):
        trans = {
            "en": {
                "node_lbl": "Active Node Selector:",
                "lang_lbl": "Language:",
                "tabs": ["Dashboard", "Send & Stake", "CPU Miner", "Token Factory", "Smart Contract VM", "ZK-Shield Privacy", "E2EE Messaging", "Advanced CLI", "Block Explorer", "Developer Guides"],
                "footer": "By Addison Electronique Enterprise inc",
                "status_conn": "● CONNECTING...",
                "status_online": "● ONLINE (MAINNET)",
                "status_offline": "● NODE OFFLINE",
                "keystore_title": "Keystore & Wallet Account Manager",
                "select_wallet_lbl": "SELECT ACTIVE WALLET ACCOUNT",
                "wallet_label_lbl": "ACCOUNT LABEL / NAME",
                "btn_save_keystore": "Save to Keystore",
                "btn_delete_account": "Delete Account",
                "keys_title": "Active Key Vector Details (ML-DSA-87 / Dilithium5)",
                "addr_lbl": "ACTIVE ADDRESS",
                "pub_lbl": "PUBLIC KEY VECTOR",
                "priv_lbl": "PRIVATE KEY VECTOR",
                "btn_gen_keys": "Generate New Keys",
                "btn_load_fields": "Load Fields",
                "btn_refresh_bal": "Refresh Balance",
                "balance_lbl": "Confirmed Ledger Balance"
            },
            "fr": {
                "node_lbl": "Sélecteur de Nœud Actif :",
                "lang_lbl": "Langue :",
                "tabs": ["Tableau de bord", "Envoyer & Staker", "Mineur CPU", "Créateur de Token", "VM Contrats Intelligents", "Confidentialité ZK", "Messagerie E2EE", "CLI Avancé", "Explorateur de Blocs", "Guides Développeurs"],
                "footer": "Par Addison Electronique Enterprise inc",
                "status_conn": "● CONNEXION...",
                "status_online": "● EN LIGNE (MAINNET)",
                "status_offline": "● NŒUD HORS-LIGNE",
                "keystore_title": "Gestionnaire de Compte Keystore",
                "select_wallet_lbl": "CHOISIR COMPTE DE PORTEFEUILLE ACTIF",
                "wallet_label_lbl": "ÉTIQUETTE DE COMPTE / NOM",
                "btn_save_keystore": "Enregistrer Keystore",
                "btn_delete_account": "Supprimer Compte",
                "keys_title": "Vecteurs de Clés Actives (ML-DSA-87 / Dilithium5)",
                "addr_lbl": "ADRESSE ACTIVE",
                "pub_lbl": "VECTEUR CLÉ PUBLIQUE",
                "priv_lbl": "VECTEUR CLÉ PRIVÉE",
                "btn_gen_keys": "Générer Nouvelles Clés",
                "btn_load_fields": "Charger Champs",
                "btn_refresh_bal": "Actualiser Solde",
                "balance_lbl": "Solde Confirmé du Grand Livre"
            }
        }
        
        lang = self.active_lang
        self.node_lbl.config(text=trans[lang]["node_lbl"])
        self.lang_lbl.config(text=trans[lang]["lang_lbl"])
        self.footer_lbl.config(text=trans[lang]["footer"])
        
        # Translate tabs
        tab_titles = trans[lang]["tabs"]
        for idx, title in enumerate(tab_titles):
            self.tabs.tab(idx, text=title)

        # Update dynamic status label translations
        curr_status = self.status_label.cget("text")
        if "CONNECTING" in curr_status or "CONNEXION" in curr_status:
            self.status_label.config(text=trans[lang]["status_conn"])
        elif "ONLINE" in curr_status or "EN LIGNE" in curr_status:
            self.status_label.config(text=trans[lang]["status_online"])
        elif "OFFLINE" in curr_status or "HORS-LIGNE" in curr_status:
            self.status_label.config(text=trans[lang]["status_offline"])

        # Translate dashboard widgets
        if hasattr(self, "keystore_title"):
            self.keystore_title.config(text=trans[lang]["keystore_title"])
            self.select_wallet_lbl.config(text=trans[lang]["select_wallet_lbl"])
            self.wallet_label_lbl.config(text=trans[lang]["wallet_label_lbl"])
            self.btn_save_keystore.config(text=trans[lang]["btn_save_keystore"])
            self.btn_delete_account.config(text=trans[lang]["btn_delete_account"])
            self.keys_title.config(text=trans[lang]["keys_title"])
            self.addr_lbl.config(text=trans[lang]["addr_lbl"])
            self.pub_lbl.config(text=trans[lang]["pub_lbl"])
            self.priv_lbl.config(text=trans[lang]["priv_lbl"])
            self.btn_gen_keys.config(text=trans[lang]["btn_gen_keys"])
            self.btn_load_fields.config(text=trans[lang]["btn_load_fields"])
            self.btn_refresh_bal.config(text=trans[lang]["btn_refresh_bal"])
            self.balance_lbl.config(text=trans[lang]["balance_lbl"])

    def _entry(self, parent, width=100, show_placeholder=False, placeholder_text=""):
        e = tk.Entry(
            parent,
            bg="#080c14",
            fg="#ffffff",
            insertbackground="#ffffff",
            bd=1,
            relief="solid",
            width=width,
            highlightthickness=1,
            highlightbackground="#1e293b",
            highlightcolor=self.accent_red
        )
        if show_placeholder and placeholder_text:
            e.insert(0, placeholder_text)
        return e

    def _button(self, parent, text, command, color=None):
        btn_color = color if color else self.accent_red
        active_color = "#b91c1c" if btn_color == self.accent_red else "#1e293b"
        return tk.Button(
            parent,
            text=text,
            command=command,
            bg=btn_color,
            fg="white",
            activebackground=active_color,
            activeforeground="white",
            bd=0,
            cursor="hand2",
            padx=18,
            pady=8,
            font=("Segoe UI", 9, "bold")
        )

    def play_video_loop(self):
        """Asynchronously decodes and renders addition chain video.mp4 in a loop with high-fidelity linear alpha-blending background removal"""
        if not hasattr(self, "video_cap") or self.video_cap is None:
            return
            
        try:
            import numpy as np
            ret, frame = self.video_cap.read()
            if not ret:
                # Loop back to beginning
                self.video_cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
                ret, frame = self.video_cap.read()
                
            if ret:
                # Convert BGR (OpenCV) to RGB (Pillow)
                frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                
                # High-fidelity linear alpha-blending for perfect white background keying
                # Minimum of R, G, B channels represents distance from white background [253, 253, 253]
                # Scale k to reach 1.0 at 253
                bg_color = np.array([22, 31, 48], dtype=np.float32)
                k = np.min(frame_rgb, axis=2, keepdims=True) / 253.0
                k = np.clip(k, 0.0, 1.0)
                
                # Blend: C_blend = C_src + k * (C_bg - 253.0)
                blended = frame_rgb.astype(np.float32) + k * (bg_color - 253.0)
                frame_rgb = np.clip(blended, 0, 255).astype(np.uint8)
                
                img = Image.fromarray(frame_rgb)
                
                # Resized slightly smaller to fit perfectly inside the compressed 1180x720 window
                # Native video aspect ratio is approx 1.49. Rescaled to 320x215.
                img_resized = img.resize((320, 215), Image.Resampling.LANCZOS)
                self.video_frame_img = ImageTk.PhotoImage(img_resized)
                
                if hasattr(self, "video_lbl") and self.video_lbl.winfo_exists():
                    self.video_lbl.config(image=self.video_frame_img)
        except Exception as e:
            print(f"[Video Loop Error] {e}")
            
        # Schedule next frame in ~33ms (approx 30 FPS)
        if hasattr(self, "root") and self.root.winfo_exists():
            self.root.after(33, self.play_video_loop)

    def _build_dashboard_tab(self):
        left_pane = tk.Frame(self.tab_dashboard, bg=self.bg_dark)
        left_pane.pack(side="left", fill="both", expand=True, padx=(0, 8), pady=6)

        right_pane = tk.Frame(self.tab_dashboard, bg=self.bg_dark)
        right_pane.pack(side="right", fill="both", expand=True, padx=(8, 0), pady=6)

        # Labeled Account Keystore Manager Panel
        keystore_card = tk.Frame(left_pane, bg=self.card_dark, padx=14, pady=12, bd=1, relief="solid")
        keystore_card.pack(fill="x", pady=4)

        self.keystore_title = tk.Label(keystore_card, text="Keystore & Wallet Account Manager", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 11, "bold"))
        self.keystore_title.pack(anchor="w", pady=(0, 6))

        self.select_wallet_lbl = tk.Label(keystore_card, text="SELECT ACTIVE WALLET ACCOUNT", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold"))
        self.select_wallet_lbl.pack(anchor="w")
        self.wallet_selector = ttk.Combobox(keystore_card, state="readonly")
        self.wallet_selector.pack(fill="x", ipady=3, pady=(2, 6))
        self.wallet_selector.bind("<<ComboboxSelected>>", self.on_wallet_account_changed)

        self.wallet_label_lbl = tk.Label(keystore_card, text="ACCOUNT LABEL / NAME", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold"))
        self.wallet_label_lbl.pack(anchor="w")
        self.wallet_label_entry = self._entry(keystore_card, placeholder_text="e.g. Mining Pool Address")
        self.wallet_label_entry.pack(fill="x", ipady=4, pady=(2, 8))

        mgr_btns = tk.Frame(keystore_card, bg=self.card_dark)
        mgr_btns.pack(fill="x")

        self.btn_save_keystore = self._button(mgr_btns, "Save to Keystore", self.save_current_to_keystore)
        self.btn_save_keystore.pack(side="left")
        self.btn_delete_account = self._button(mgr_btns, "Delete Account", self.delete_account_from_keystore, color="#333a4a")
        self.btn_delete_account.pack(side="right")

        # Left: Keys display panel
        keys_card = tk.Frame(left_pane, bg=self.card_dark, padx=14, pady=12, bd=1, relief="solid")
        keys_card.pack(fill="x", pady=8)

        self.keys_title = tk.Label(keys_card, text="Active Key Vector Details (ML-DSA-87 / Dilithium5)", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 11, "bold"))
        self.keys_title.pack(anchor="w", pady=(0, 6))

        self.addr_lbl = tk.Label(keys_card, text="ACTIVE ADDRESS", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold"))
        self.addr_lbl.pack(anchor="w")
        self.addr_entry = self._entry(keys_card)
        self.addr_entry.pack(fill="x", ipady=4, pady=(2, 6))

        self.pub_lbl = tk.Label(keys_card, text="PUBLIC KEY VECTOR", bg=keys_card.cget("bg"), fg=self.text_gray, font=("Segoe UI", 8, "bold"))
        self.pub_lbl.pack(anchor="w")
        self.pub_entry = self._entry(keys_card)
        self.pub_entry.pack(fill="x", ipady=4, pady=(2, 6))

        self.priv_lbl = tk.Label(keys_card, text="PRIVATE KEY VECTOR", bg=keys_card.cget("bg"), fg=self.text_gray, font=("Segoe UI", 8, "bold"))
        self.priv_lbl.pack(anchor="w")
        self.priv_entry = self._entry(keys_card)
        self.priv_entry.pack(fill="x", ipady=4, pady=(2, 6))

        btns_frame = tk.Frame(keys_card, bg=self.card_dark)
        btns_frame.pack(fill="x", pady=(6, 0))

        self.btn_gen_keys = self._button(btns_frame, "Generate New Keys", self.create_wallet)
        self.btn_gen_keys.pack(side="left")
        self.btn_load_fields = self._button(btns_frame, "Load Fields", self.load_wallet_fields, color="#333a4a")
        self.btn_load_fields.pack(side="left", padx=10)
        self.btn_refresh_bal = self._button(btns_frame, "Refresh Balance", self.refresh_balance, color="#333a4a")
        self.btn_refresh_bal.pack(side="left")

        # Right: Balance and stats
        bal_card = tk.Frame(right_pane, bg=self.card_dark, padx=14, pady=12, bd=1, relief="solid")
        bal_card.pack(fill="x", pady=4)

        # Split layout to include ADD Coin logo professionally on the right
        text_f = tk.Frame(bal_card, bg=self.card_dark)
        text_f.pack(side="left", fill="both", expand=True)

        self.balance_lbl = tk.Label(text_f, text="Confirmed Ledger Balance", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 9, "bold"))
        self.balance_lbl.pack(anchor="w")
        self.balance_label = tk.Label(text_f, text="0.00 ADD", bg=self.card_dark, fg=self.accent_red, font=("Consolas", 28, "bold"))
        self.balance_label.pack(anchor="w", pady=(4, 0))

        script_dir = os.path.dirname(os.path.abspath(__file__))
        coin_path = os.path.join(script_dir, "Assets", "coin Add.jpg")
        if os.path.exists(coin_path):
            try:
                # Load coin image
                coin_img = Image.open(coin_path).convert("RGBA")
                
                # Professional high-fidelity circular masking
                # Crop to exact non-white bounding box to center the coin perfectly
                cropped = coin_img.crop((81, 62, 953, 971))
                
                # Resize to a perfect square first to resolve any aspect ratio stretching
                square_img = cropped.resize((800, 800), Image.Resampling.LANCZOS)
                
                # Create a perfect circular mask with antialiasing bounds
                from PIL import ImageDraw
                mask = Image.new("L", (800, 800), 0)
                draw = ImageDraw.Draw(mask)
                draw.ellipse((4, 4, 796, 796), fill=255)
                square_img.putalpha(mask)
                
                # Resize to target 80x80 display dimensions
                coin_img_resized = square_img.resize((80, 80), Image.Resampling.LANCZOS)
                
                # Pre-blend the transparent coin image onto card background (#161f30) in memory
                # This guarantees a perfect borderless alpha edge blend on any Tkinter widget
                bg_color = (22, 31, 48)
                final_coin_img = Image.new("RGB", (80, 80), bg_color)
                final_coin_img.paste(coin_img_resized, (0, 0), coin_img_resized)
                
                self.coin_photo_img = ImageTk.PhotoImage(final_coin_img)
                coin_lbl = tk.Label(bal_card, image=self.coin_photo_img, bg=self.card_dark, bd=0, highlightthickness=0)
                coin_lbl.pack(side="right", padx=(10, 5))
            except Exception as e:
                print(f"[UI Warning] Could not load coin image: {e}")

        stats_card = tk.Frame(right_pane, bg=self.card_dark, padx=14, pady=12, bd=1, relief="solid")
        stats_card.pack(fill="x", pady=6)

        tk.Label(stats_card, text="L1 Mainnet Live Information", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 11, "bold")).pack(anchor="w", pady=(0, 8))
        
        # Dual-Column Stats Grid Frame
        self.stats_grid_frame = tk.Frame(stats_card, bg=self.card_dark)
        self.stats_grid_frame.pack(fill="both", expand=True, pady=4)
        
        # Fields layout (key, displayName, column, row)
        self.stat_fields = [
            ("height", "Height", 0, 0),
            ("mempool", "Mempool", 0, 1),
            ("peers", "Peers", 0, 2),
            ("difficulty_target", "Difficulty", 0, 3),
            ("next_reward", "Reward", 0, 4),
            ("last_tps", "Network TPS", 0, 5),
            ("pq_mode", "PQ Security", 0, 6),
            
            ("total_staked", "Total Staked", 1, 0),
            ("fees_last_block", "Fees Last", 1, 1),
            ("dynamic_min_fee", "Min Fee", 1, 2),
            ("last_mine_ms", "Solve Time", 1, 3),
            ("last_mined_txs", "Last Txs", 1, 4),
            ("privacy_mode", "ZK Privacy", 1, 5),
            ("max_supply", "Max Supply", 1, 6),
        ]
        
        self.stat_labels = {}
        for key, name, col, row in self.stat_fields:
            padx = (0, 15) if col == 0 else (15, 0)
            
            f = tk.Frame(self.stats_grid_frame, bg=self.card_dark)
            f.grid(row=row, column=col, sticky="w", padx=padx, pady=2)
            
            lbl_name = tk.Label(f, text=f"{name}: ", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 9, "bold"))
            lbl_name.pack(side="left")
            
            lbl_val = tk.Label(f, text="N/A", bg=self.card_dark, fg=self.text_white, font=("Consolas", 9, "bold"))
            lbl_val.pack(side="left")
            
            self.stat_labels[key] = lbl_val
            
        # Offline Warning Label
        self.offline_error_label = tk.Label(
            stats_card,
            text="Querying node metrics...",
            bg=self.card_dark,
            fg=self.text_white,
            font=("Segoe UI", 9, "bold"),
            justify="left"
        )
        # By default, we keep it packed and hide the grid until the first poll
        self.stats_grid_frame.pack_forget()
        self.offline_error_label.pack(fill="both", expand=True, pady=10)

        # Beautiful L1 Live Activity Video Loop Card
        video_path = os.path.join(script_dir, "Assets", "addition chain video.mp4")
        if os.path.exists(video_path):
            try:
                self.video_cap = cv2.VideoCapture(video_path)
                
                arch_card = tk.Frame(right_pane, bg=self.card_dark, padx=10, pady=8, bd=1, relief="solid")
                arch_card.pack(fill="x", pady=(6, 4))
                
                tk.Label(arch_card, text="L1 Blockchain Live Activity Layout", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 10, "bold")).pack(anchor="w", pady=(0, 4))
                
                # bd=0, highlightthickness=0 ensures zero clipping/cropping of video frames!
                self.video_lbl = tk.Label(arch_card, bg=self.card_dark, bd=0, highlightthickness=0, relief="flat")
                self.video_lbl.pack(anchor="center")
                
                # Start loop player
                self.play_video_loop()
            except Exception as e:
                print(f"[UI Warning] Could not initialize video loop: {e}")

    def _build_send_tab(self):
        wrap = tk.Frame(self.tab_send, bg=self.bg_dark, padx=10, pady=10)
        wrap.pack(fill="both", expand=True)

        send_card = tk.Frame(wrap, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        send_card.pack(fill="x", pady=5)

        tk.Label(send_card, text="Transfer Funds (Post-Quantum Secure)", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        tk.Label(send_card, text="RECIPIENT ADDRESS", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.send_to = self._entry(send_card)
        self.send_to.pack(fill="x", ipady=6, pady=(4, 10))

        row = tk.Frame(send_card, bg=self.card_dark)
        row.pack(fill="x")

        col1 = tk.Frame(row, bg=self.card_dark)
        col2 = tk.Frame(row, bg=self.card_dark)
        col3 = tk.Frame(row, bg=self.card_dark)
        col1.pack(side="left", fill="x", expand=True)
        col2.pack(side="left", fill="x", expand=True, padx=15)
        col3.pack(side="left", fill="x", expand=True)

        tk.Label(col1, text="AMOUNT (ADD)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.send_amount = self._entry(col1)
        self.send_amount.pack(fill="x", ipady=6, pady=(4, 0))

        tk.Label(col2, text="FEE (ADD)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.send_fee = self._entry(col2)
        self.send_fee.insert(0, "0.001")
        self.send_fee.pack(fill="x", ipady=6, pady=(4, 0))

        tk.Label(col3, text="NONCE", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.send_nonce = self._entry(col3)
        self.send_nonce.insert(0, "1")
        self.send_nonce.pack(fill="x", ipady=6, pady=(4, 0))

        self._button(send_card, "Submit Signed Transaction", self.send_transaction).pack(fill="x", pady=(18, 0))

        stake_card = tk.Frame(wrap, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        stake_card.pack(fill="x", pady=15)

        tk.Label(stake_card, text="Non-Custodial PoS Staking Pool Management", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        tk.Label(stake_card, text="STAKE AMOUNT (ADD)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.stake_amount = self._entry(stake_card)
        self.stake_amount.pack(fill="x", ipady=6, pady=(4, 12))

        s_btns = tk.Frame(stake_card, bg=self.card_dark)
        s_btns.pack(fill="x")

        self._button(s_btns, "Stake Coins", self.stake).pack(side="left", fill="x", expand=True)
        self._button(s_btns, "Unstake Coins", self.unstake, color="#333a4a").pack(side="left", fill="x", expand=True, padx=10)
        self._button(s_btns, "Claim Staking Rewards", self.claim_rewards, color="#333a4a").pack(side="left", fill="x", expand=True)

    def _build_mine_tab(self):
        wrap = tk.Frame(self.tab_mine, bg=self.bg_dark, padx=10, pady=10)
        wrap.pack(fill="both", expand=True)

        mine_card = tk.Frame(wrap, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        mine_card.pack(fill="x", pady=5)

        tk.Label(mine_card, text="1 MiB Scratchpad Proof of Measurable Work (PoMW) Solver", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        tk.Label(mine_card, text="REWARD BLOCK ADDRESS", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.mine_addr = self._entry(mine_card)
        self.mine_addr.pack(fill="x", ipady=6, pady=(4, 12))

        btns_row = tk.Frame(mine_card, bg=self.card_dark)
        btns_row.pack(fill="x")

        self.mine_once_btn = self._button(btns_row, "Mine 1 Block", self.mine_block)
        self.mine_once_btn.pack(side="left", fill="x", expand=True, padx=(0, 10))

        self.loop_btn = self._button(btns_row, "Start Continuous Mining Loop", self.toggle_mining_loop, color=self.accent_amber)
        self.loop_btn.pack(side="right", fill="x", expand=True, padx=(10, 0))

        log_frame = tk.Frame(wrap, bg=self.card_dark, bd=1, relief="solid")
        log_frame.pack(fill="both", expand=True, pady=15)

        tk.Label(log_frame, text="Active Miner Execution Logs", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 10, "bold")).pack(anchor="w", padx=15, pady=8)

        self.miner_console = scrolledtext.ScrolledText(
            log_frame,
            bg="#080c14",
            fg="#ef4444",
            insertbackground="white",
            bd=0,
            font=("Consolas", 9),
            height=14
        )
        self.miner_console.pack(fill="both", expand=True, padx=10, pady=10)
        self.miner_console.configure(state="disabled")

    def _build_token_tab(self):
        wrap = tk.Frame(self.tab_token, bg=self.bg_dark, padx=10, pady=10)
        wrap.pack(fill="both", expand=True)

        token_card = tk.Frame(wrap, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        token_card.pack(fill="x", pady=5)

        tk.Label(token_card, text="On-Chain Custom Token Factory", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        row1 = tk.Frame(token_card, bg=self.card_dark)
        row1.pack(fill="x", pady=5)

        c1 = tk.Frame(row1, bg=self.card_dark)
        c2 = tk.Frame(row1, bg=self.card_dark)
        c3 = tk.Frame(row1, bg=self.card_dark)
        c1.pack(side="left", fill="x", expand=True)
        c2.pack(side="left", fill="x", expand=True, padx=15)
        c3.pack(side="left", fill="x", expand=True)

        tk.Label(c1, text="TOKEN TICKER", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.token_sym = self._entry(c1, placeholder_text="e.g. USDCX")
        self.token_sym.pack(fill="x", ipady=6, pady=4)

        tk.Label(c2, text="ASSET NAME", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.token_name = self._entry(c2, placeholder_text="e.g. USD_Coin")
        self.token_name.pack(fill="x", ipady=6, pady=4)

        tk.Label(c3, text="DECIMALS", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.token_dec = self._entry(c3)
        self.token_dec.insert(0, "18")
        self.token_dec.pack(fill="x", ipady=6, pady=4)

        row2 = tk.Frame(token_card, bg=self.card_dark)
        row2.pack(fill="x", pady=5)

        c4 = tk.Frame(row2, bg=self.card_dark)
        c5 = tk.Frame(row2, bg=self.card_dark)
        c6 = tk.Frame(row2, bg=self.card_dark)
        c4.pack(side="left", fill="x", expand=True)
        c5.pack(side="left", fill="x", expand=True, padx=15)
        c6.pack(side="left", fill="x", expand=True)

        tk.Label(c4, text="MAX SUPPLY", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.token_max = self._entry(c4)
        self.token_max.insert(0, "21000000")
        self.token_max.pack(fill="x", ipady=6, pady=4)

        tk.Label(c5, text="INITIAL MINT", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.token_mint = self._entry(c5)
        self.token_mint.insert(0, "10000000")
        self.token_mint.pack(fill="x", ipady=6, pady=4)

        tk.Label(c6, text="BURNABLE", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.token_burn = ttk.Combobox(c6, values=["Yes (1)", "No (0)"], state="readonly")
        self.token_burn.current(0)
        self.token_burn.pack(fill="x", ipady=4, pady=4)

        self._button(token_card, "Deploy Custom Token Asset", self.deploy_custom_token).pack(fill="x", pady=(18, 5))

        amm_card = tk.Frame(wrap, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        amm_card.pack(fill="x", pady=15)

        tk.Label(amm_card, text="Automated Market Maker (AMM) Liquidity Pool Setup", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        tk.Label(amm_card, text="STAKED LIQUIDITY TOKEN TICKER", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.amm_token_b = self._entry(amm_card, placeholder_text="e.g. USDCX")
        self.amm_token_b.pack(fill="x", ipady=6, pady=(4, 12))

        self._button(amm_card, "Create ADD / Token Pool (30 bps fee)", self.create_amm_pool, color=self.accent_amber).pack(fill="x")

    def _build_contract_tab(self):
        wrap = tk.Frame(self.tab_contract, bg=self.bg_dark, padx=10, pady=10)
        wrap.pack(fill="both", expand=True)

        panes = tk.Frame(wrap, bg=self.bg_dark)
        panes.pack(fill="both", expand=True)

        left_c = tk.Frame(panes, bg=self.bg_dark)
        left_c.pack(side="left", fill="both", expand=True, padx=(0, 10))

        right_c = tk.Frame(panes, bg=self.bg_dark)
        right_c.pack(side="right", fill="both", expand=True, padx=(10, 0))

        deploy_card = tk.Frame(left_c, bg=self.card_dark, padx=15, pady=15, bd=1, relief="solid")
        deploy_card.pack(fill="both", expand=True)

        tk.Label(deploy_card, text="Compile & Deploy L1 Contract", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))
        
        tk.Label(deploy_card, text="VM CONTRACT SCRIPT", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        
        default_script = (
            "// ADDITION L1 Yield Pool Contract\n"
            "INIT_POOL(yield_rate=128, max_capacity=1000000);\n"
            "SET_STATE(\"yield_rate\", 128);\n"
            "SET_STATE(\"total_staked\", 0);"
        )
        self.contract_code = scrolledtext.ScrolledText(deploy_card, bg="#080c14", fg="#ffffff", insertbackground="white", bd=0, font=("Consolas", 9), height=14)
        self.contract_code.insert(tk.END, default_script)
        self.contract_code.pack(fill="both", expand=True, pady=(4, 10))

        self._button(deploy_card, "Deploy Contract Script", self.deploy_contract).pack(fill="x")

        exec_card = tk.Frame(right_c, bg=self.card_dark, padx=15, pady=15, bd=1, relief="solid")
        exec_card.pack(fill="x")

        tk.Label(exec_card, text="Interact with Deployed Contracts", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        tk.Label(exec_card, text="TARGET CONTRACT SHA3-512 HASH", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.exec_cid = self._entry(exec_card)
        self.exec_cid.pack(fill="x", ipady=6, pady=(4, 10))

        cw_row = tk.Frame(exec_card, bg=self.card_dark)
        cw_row.pack(fill="x", pady=5)
        c_a = tk.Frame(cw_row, bg=self.card_dark)
        c_b = tk.Frame(cw_row, bg=self.card_dark)
        c_a.pack(side="left", fill="x", expand=True)
        c_b.pack(side="left", fill="x", expand=True, padx=(15, 0))

        tk.Label(c_a, text="METHOD OPERATION", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.exec_method = ttk.Combobox(c_a, values=["set", "add", "get", "token_balance"], state="readonly")
        self.exec_method.current(2)
        self.exec_method.pack(fill="x", ipady=4, pady=4)

        tk.Label(c_b, text="STATE KEY", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.exec_key = self._entry(c_b)
        self.exec_key.insert(0, "yield_rate")
        self.exec_key.pack(fill="x", ipady=6, pady=4)

        tk.Label(exec_card, text="INPUT VALUE (INTEGERS ONLY)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.exec_val = self._entry(exec_card)
        self.exec_val.insert(0, "0")
        self.exec_val.pack(fill="x", ipady=6, pady=(4, 12))

        self._button(exec_card, "Execute VM State Transition", self.execute_contract_call).pack(fill="x")

        console_frame = tk.Frame(right_c, bg=self.card_dark, bd=1, relief="solid", padx=15, pady=15)
        console_frame.pack(fill="both", expand=True, pady=15)

        tk.Label(console_frame, text="Contract Console Outputs", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 10, "bold")).pack(anchor="w")
        self.contract_log_box = scrolledtext.ScrolledText(console_frame, bg="#080c14", fg=self.accent_amber, insertbackground="white", bd=0, font=("Consolas", 9), height=7)
        self.contract_log_box.pack(fill="both", expand=True, pady=8)
        self.contract_log_box.insert(tk.END, "[VM Compiler] Awaiting operations...")

    def _build_privacy_tab(self):
        """Builds the ZK-Shield Privacy Portal"""
        wrap = tk.Frame(self.tab_privacy, bg=self.bg_dark, padx=10, pady=10)
        wrap.pack(fill="both", expand=True)

        left_p = tk.Frame(wrap, bg=self.bg_dark)
        left_p.pack(side="left", fill="both", expand=True, padx=(0, 10))

        right_p = tk.Frame(wrap, bg=self.bg_dark)
        right_p.pack(side="right", fill="both", expand=True, padx=(10, 0))

        # Left: Shield (Mint ZK) Panel
        shield_card = tk.Frame(left_p, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        shield_card.pack(fill="x", pady=5)

        tk.Label(shield_card, text="Shield Coins (Transparent ➔ Shielded ZK Note)", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        tk.Label(shield_card, text="MINT OWNER L1 ADDRESS", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.zk_mint_owner = self._entry(shield_card)
        self.zk_mint_owner.pack(fill="x", ipady=6, pady=(4, 10))

        r_fields = tk.Frame(shield_card, bg=self.card_dark)
        r_fields.pack(fill="x")
        c_a = tk.Frame(r_fields, bg=self.card_dark)
        c_b = tk.Frame(r_fields, bg=self.card_dark)
        c_a.pack(side="left", fill="x", expand=True)
        c_b.pack(side="left", fill="x", expand=True, padx=(15, 0))

        tk.Label(c_a, text="SHIELD AMOUNT (ADD)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.zk_mint_amt = self._entry(c_a)
        self.zk_mint_amt.pack(fill="x", ipady=6, pady=4)

        tk.Label(c_b, text="NOTE COMMITMENT HASH", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.zk_mint_commit = self._entry(c_b)
        self.zk_mint_commit.pack(fill="x", ipady=6, pady=4)

        tk.Label(shield_card, text="ZK RANGE PROOF BLOB (AUTO-GENERATED IF BLANK)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w", pady=(6, 0))
        self.zk_mint_proof = self._entry(shield_card)
        self.zk_mint_proof.pack(fill="x", ipady=6, pady=(4, 15))

        self._button(shield_card, "Shield ADD Coins (zk_mint)", self.execute_zk_mint).pack(fill="x")

        # Right: Spend ZK Panel
        spend_card = tk.Frame(right_p, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        spend_card.pack(fill="x", pady=5)

        tk.Label(spend_card, text="Spend Shielded Coins (Shielded ➔ Shielded / Transparent)", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        tk.Label(spend_card, text="RECIPIENT ADDRESS / SHIELDED KEY", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.zk_spend_recip = self._entry(spend_card)
        self.zk_spend_recip.pack(fill="x", ipady=6, pady=(4, 10))

        r2_fields = tk.Frame(spend_card, bg=self.card_dark)
        r2_fields.pack(fill="x")
        c2_a = tk.Frame(r2_fields, bg=self.card_dark)
        c2_b = tk.Frame(r2_fields, bg=self.card_dark)
        c2_a.pack(side="left", fill="x", expand=True)
        c2_b.pack(side="left", fill="x", expand=True, padx=(15, 0))

        tk.Label(c2_a, text="SPEND AMOUNT (ADD)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.zk_spend_amt = self._entry(c2_a)
        self.zk_spend_amt.pack(fill="x", ipady=6, pady=4)

        tk.Label(c2_b, text="SPENT NULLIFIER HASH", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.zk_spend_null = self._entry(c2_b)
        self.zk_spend_null.pack(fill="x", ipady=6, pady=4)

        tk.Label(spend_card, text="ZK-STARK TRACE PROOF (AUTO-GENERATED IF BLANK)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w", pady=(6, 0))
        self.zk_spend_proof = self._entry(spend_card)
        self.zk_spend_proof.pack(fill="x", ipady=6, pady=(4, 15))

        self._button(spend_card, "Spend Shielded Coins (zk_spend)", self.execute_zk_spend).pack(fill="x")

        # ZK Stats Panel
        zk_stats = tk.Frame(left_p, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        zk_stats.pack(fill="both", expand=True, pady=15)

        tk.Label(zk_stats, text="ZK-Shield Consensus Cryptography Status", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 11, "bold")).pack(anchor="w", pady=(0, 8))
        self.zk_status_lbl = tk.Label(zk_stats, text="Querying ZK status metrics...", bg=self.card_dark, fg=self.accent_amber, font=("Consolas", 10), justify="left", anchor="nw")
        self.zk_status_lbl.pack(fill="both", expand=True, pady=5)
        
        self._button(zk_stats, "Refresh ZK Status", self.refresh_zk_status, color="#333a4a").pack(fill="x", pady=(10, 0))

    def _build_messaging_tab(self):
        """Builds the E2EE Anonymous Messaging Hub"""
        wrap = tk.Frame(self.tab_messaging, bg=self.bg_dark, padx=10, pady=10)
        wrap.pack(fill="both", expand=True)

        left_m = tk.Frame(wrap, bg=self.bg_dark)
        left_m.pack(side="left", fill="both", expand=True, padx=(0, 10))

        right_m = tk.Frame(wrap, bg=self.bg_dark)
        right_m.pack(side="right", fill="both", expand=True, padx=(10, 0))

        send_m_card = tk.Frame(left_m, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        send_m_card.pack(fill="both", expand=True)

        tk.Label(send_m_card, text="Send Anonymous E2EE Message", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        tk.Label(send_m_card, text="SENDER ADDRESS / KEY", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.msg_sender = self._entry(send_m_card)
        self.msg_sender.pack(fill="x", ipady=6, pady=(4, 10))

        tk.Label(send_m_card, text="RECIPIENT L1 ADDRESS", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.msg_recipient = self._entry(send_m_card)
        self.msg_recipient.pack(fill="x", ipady=6, pady=(4, 10))

        row_fields = tk.Frame(send_m_card, bg=self.card_dark)
        row_fields.pack(fill="x")
        c1 = tk.Frame(row_fields, bg=self.card_dark)
        c2 = tk.Frame(row_fields, bg=self.card_dark)
        c1.pack(side="left", fill="x", expand=True)
        c2.pack(side="left", fill="x", expand=True, padx=(15, 0))

        tk.Label(c1, text="RECIPIENT DH PUBLIC KEY (FOR E2EE)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.msg_recip_dh = self._entry(c1)
        self.msg_recip_dh.pack(fill="x", ipady=6, pady=4)

        tk.Label(c2, text="TIME-TO-LIVE (TTL SECONDS)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.msg_ttl = self._entry(c2)
        self.msg_ttl.insert(0, "300")
        self.msg_ttl.pack(fill="x", ipady=6, pady=4)

        tk.Label(send_m_card, text="MESSAGE CONTENT (PLAINTEXT)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w", pady=(6, 0))
        self.msg_body = scrolledtext.ScrolledText(send_m_card, bg="#080c14", fg="white", insertbackground="white", bd=0, font=("Segoe UI", 10), height=8)
        self.msg_body.pack(fill="both", expand=True, pady=(4, 15))

        self._button(send_m_card, "Encrypt & Dispatch E2EE Message", self.send_e2ee_message).pack(fill="x")

        inbox_card = tk.Frame(right_m, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        inbox_card.pack(fill="both", expand=True)

        tk.Label(inbox_card, text="E2EE Inbox Viewer & Decryption Hub", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        tk.Label(inbox_card, text="RECIPIENT L1 ADDRESS (YOUR ADDR)", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.msg_inbox_addr = self._entry(inbox_card)
        self.msg_inbox_addr.pack(fill="x", ipady=6, pady=(4, 10))

        row2 = tk.Frame(inbox_card, bg=self.card_dark)
        row2.pack(fill="x", pady=(0, 10))
        
        self.inbox_btn = self._button(row2, "Fetch & Decrypt Inbox", self.fetch_inbox_messages)
        self.inbox_btn.pack(side="left", fill="x", expand=True)

        self.dh_btn = self._button(row2, "Show Our DH Public Key", self.show_our_dh_pub, color="#333a4a")
        self.dh_btn.pack(side="right", fill="x", expand=True, padx=(10, 0))

        tk.Label(inbox_card, text="MESSAGE MAILBOX", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        self.inbox_console = scrolledtext.ScrolledText(inbox_card, bg="#080c14", fg=self.accent_amber, insertbackground="white", bd=0, font=("Consolas", 10), height=18)
        self.inbox_console.pack(fill="both", expand=True, pady=(4, 0))
        self.inbox_console.insert(tk.END, "[Mailbox] Inbox unread envelopes will be loaded here...")

    def _build_cli_tab(self):
        """Builds the Advanced Daemon CLI Terminal Tab"""
        wrap = tk.Frame(self.tab_cli, bg=self.bg_dark, padx=10, pady=10)
        wrap.pack(fill="both", expand=True)

        top_f = tk.Frame(wrap, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        top_f.pack(fill="x", pady=5)

        tk.Label(top_f, text="L1 Daemon Command Router Console", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 10))

        # Comprehensive Command presets covering 100% of daemon endpoints
        tk.Label(top_f, text="COMPREHENSIVE COMMAND PRESET REFERENCE SELECTOR", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        
        commands_presets = [
            "getinfo -- Query L1 blockchain general status metrics",
            "monetary_info -- View dynamic supply metrics & block reward policies",
            "privacy_status -- Read global ZK-Shield commitments & nullifiers",
            "ai_status -- View current AI-optimized gas/block schedules",
            "fee_info -- Check dynamic anti-spam fee matrices",
            "peers -- Display list of active validation/discovery seeds",
            "crypto_selftest -- Execute core cryptographic sanity checks on LLVM",
            "sync -- Force active peer synchronization on local chain",
            "node_pubkey -- View local node identity public key vector",
            "pm_purge -- Purge ephemerally expired TTL inbox storage",
            "quit -- Instruct local additiond.exe to safely shut down",
            "token_info ADD -- View token metadata statistics",
            "token_balance ADD e48d89a9efd... -- Query token balance of specific owner",
            "swap_pool_info ADD USDCX -- Read AMM swap pool reserves and fee bps",
            "swap_quote ADD USDCX 1000 -- Fetch AMM quote for swap amount input",
            "pouw_storage_deal_status 0 -- Check active storage contract worker validations",
            "pouw_compute_job_status 0 -- Read compute job decentralized state logs"
        ]
        
        self.cli_combobox = ttk.Combobox(top_f, values=commands_presets, state="readonly")
        self.cli_combobox.bind("<<ComboboxSelected>>", self.on_cli_preset_selected)
        self.cli_combobox.pack(fill="x", ipady=4, pady=(4, 10))

        tk.Label(top_f, text="WRITE CUSTOM COMMAND ENTRY", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 8, "bold")).pack(anchor="w")
        
        self.cli_entry = self._entry(top_f)
        self.cli_entry.insert(0, "getinfo")
        self.cli_entry.pack(fill="x", ipady=6, pady=(4, 15))

        self.cli_btn = self._button(top_f, "Send Raw Console CLI Command", self.execute_cli_command)
        self.cli_btn.pack(fill="x")

        # Monospaced Black Screen ScrolledText
        cli_screen_f = tk.Frame(wrap, bg=self.card_dark, bd=1, relief="solid", padx=15, pady=15)
        cli_screen_f.pack(fill="both", expand=True, pady=15)

        tk.Label(cli_screen_f, text="Monospaced C++ Console Output Screen", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 10, "bold")).pack(anchor="w", pady=(0, 8))

        self.cli_screen = scrolledtext.ScrolledText(cli_screen_f, bg="#020408", fg="#10b981", insertbackground="white", bd=0, font=("Consolas", 10), height=16)
        self.cli_screen.pack(fill="both", expand=True)
        self.cli_screen.insert(tk.END, "========================================================================\n"
                                       "            ADDITION L1 COMPREHENSIVE CLI CONSOLE SCREEN ACTIVE\n"
                                       "========================================================================\n"
                                       "Awaiting developer inputs...")

    def _build_explorer_tab(self):
        wrap = tk.Frame(self.tab_explorer, bg=self.bg_dark, padx=10, pady=10)
        wrap.pack(fill="both", expand=True)

        exp_card = tk.Frame(wrap, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        exp_card.pack(fill="both", expand=True)

        tk.Label(exp_card, text="On-Chain Block History Explorer", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 12, "bold")).pack(anchor="w", pady=(0, 5))
        tk.Label(exp_card, text="Double-click on any block row to inspect complete transactions & Merkle proofs.", bg=self.card_dark, fg=self.text_gray, font=("Segoe UI", 9)).pack(anchor="w", pady=(0, 15))

        columns = ("height", "hash", "time", "txs", "nonce", "difficulty")
        self.explorer_tree = ttk.Treeview(exp_card, columns=columns, show="headings", height=14)
        
        self.explorer_tree.heading("height", text="Block Height")
        self.explorer_tree.heading("hash", text="Dilithium5 Block Hash")
        self.explorer_tree.heading("time", text="Timestamp")
        self.explorer_tree.heading("txs", text="Transactions")
        self.explorer_tree.heading("nonce", text="Nonce")
        self.explorer_tree.heading("difficulty", text="Difficulty")

        self.explorer_tree.column("height", width=90, anchor="center")
        self.explorer_tree.column("hash", width=380, anchor="w")
        self.explorer_tree.column("time", width=160, anchor="center")
        self.explorer_tree.column("txs", width=90, anchor="center")
        self.explorer_tree.column("nonce", width=80, anchor="center")
        self.explorer_tree.column("difficulty", width=140, anchor="center")

        self.explorer_tree.bind("<Double-1>", self.on_block_double_click)
        self.explorer_tree.pack(fill="both", expand=True, pady=10)

        sb = ttk.Scrollbar(self.explorer_tree, orient="vertical", command=self.explorer_tree.yview)
        self.explorer_tree.configure(yscrollcommand=sb.set)
        sb.pack(side="right", fill="y")

        self._button(exp_card, "Refresh Ledger Blocks Grid", self.refresh_blocks_grid).pack(fill="x", pady=(10, 0))

    def _build_docs_tab(self):
        wrap = tk.Frame(self.tab_docs, bg=self.bg_dark, padx=10, pady=10)
        wrap.pack(fill="both", expand=True)

        docs_frame = tk.Frame(wrap, bg=self.card_dark, padx=18, pady=18, bd=1, relief="solid")
        docs_frame.pack(fill="both", expand=True)

        tk.Label(docs_frame, text="L1 Blockchain Developer Manuals", bg=self.card_dark, fg="#ffffff", font=("Segoe UI", 14, "bold")).pack(anchor="w", pady=(0, 15))

        docs_tabs = ttk.Notebook(docs_frame)
        docs_tabs.pack(fill="both", expand=True)

        tab_doc_token = tk.Frame(docs_tabs, bg=self.bg_dark)
        tab_doc_contract = tk.Frame(docs_tabs, bg=self.bg_dark)
        tab_doc_privacy = tk.Frame(docs_tabs, bg=self.bg_dark)
        tab_doc_whitepaper = tk.Frame(docs_tabs, bg=self.bg_dark)

        docs_tabs.add(tab_doc_token, text="Custom Token Guide")
        docs_tabs.add(tab_doc_contract, text="Smart Contract VM Guide")
        docs_tabs.add(tab_doc_privacy, text="ZK-Shield & E2EE Guide")
        docs_tabs.add(tab_doc_whitepaper, text="Livre Blanc (Whitepaper)")

        t_text = scrolledtext.ScrolledText(tab_doc_token, bg="#080c14", fg="#ffffff", bd=0, font=("Consolas", 10), padx=10, pady=10)
        t_text.pack(fill="both", expand=True)
        t_text.insert(tk.END, 
            "========================================================================\n"
            "            L1 CUSTOM TOKEN CREATION METHOD: token_create_ex\n"
            "========================================================================\n\n"
            "ADDITION L1 supports the creation of native custom tokens (User-Defined Assets)\n"
            "directly compiled on the ledger. They enjoy identical speed, gas limits, and\n"
            "post-quantum Dilithium5 security as the main ADD currency.\n\n"
            "RPC API Format:\n"
            "  token_create_ex <symbol> <name> <owner> <max_supply> <initial_mint> <decimals> <burnable_0_1> <dev_wallet> <dev_allocation>\n\n"
            "Parameters:\n"
            "  - symbol: Uppercase identifier (e.g. USDCX, MYCOIN).\n"
            "  - name: Alphanumeric asset name with NO spaces (e.g., USD_Coin_L1).\n"
            "  - owner: The ML-DSA-87 address managing token metadata and administration.\n"
            "  - max_supply: Complete absolute cap representing maximum token supply.\n"
            "  - initial_mint: The exact number of tokens minted to the owner at deploy.\n"
            "  - decimals: Fractional granularity bounds. Default is 18.\n"
            "  - burnable_0_1: Set 1 to allow tokens to be burned; 0 to forbid burning.\n"
            "  - dev_wallet: Reserved Dev wallet alias or '-' to disable allocation.\n"
            "  - dev_allocation: Developer percentage fee. Standard is 0.\n\n"
            "Example Command:\n"
            "  token_create_ex USDCX USD_Coin e48d89a9efd... 1000000 500000 18 1 - 0\n\n"
            "========================================================================\n"
            "            L1 TRANSACTION FEE SYSTEM LOGIC\n"
            "========================================================================\n\n"
            "Like Bitcoin, ADDITION L1 does not enforce a hard-coded absolute minimum fee\n"
            "within its consensus layer. However, validator nodes enforce a dynamic C++\n"
            "mempool relay filter to prevent transaction DDoS and spam attacks.\n\n"
            "Key concepts of the L1 fee architecture:\n"
            "  - Internal Satoshis Unit: Fees are tracked in satoshi-equivalents (1 sat = 1e-8 ADD).\n"
            "  - 'Min Fee: 1': The value '1' shown in the system metrics is 1 satoshi (0.00000001 ADD).\n"
            "    This is the absolute base spam-protection unit. It is virtually free but prevents zero-fee spam.\n"
            "  - Dynamic Market-Driven fees: If network traffic increases, the C++ daemon's AI-optimized\n"
            "    routing fee estimator dynamically raises this suggested relay minimum fee threshold\n"
            "    to prioritize active transactions, mirroring the Bitcoin competitive fee market.\n"
            "  - Low Transaction Cost: Even under full target 100k TPS congestion, suggested fees remain\n"
            "    within highly economical bounds (typically under 0.0001 ADD).\n"
        )
        t_text.configure(state="disabled")

        c_text = scrolledtext.ScrolledText(tab_doc_contract, bg="#080c14", fg="#ffffff", bd=0, font=("Consolas", 10), padx=10, pady=10)
        c_text.pack(fill="both", expand=True)
        c_text.insert(tk.END,
            "========================================================================\n"
            "            L1 SMART CONTRACT PERSISTENT VM ARCHITECTURE\n"
            "========================================================================\n\n"
            "The ADDITION VM evaluates smart contracts directly in the C++ core consensus engine.\n"
            "State variables are persisted in local binary databases on validator disks.\n\n"
            "Deploying Contract:\n"
            "  Call contract_deploy <owner> <code_content> to register scripts.\n"
            "  Available built-in script functions:\n"
            "    - INIT_POOL(key=value): Preload constructor params into persistent state.\n"
            "    - SET_STATE(key, integer): Overwrites or defines an integer state key.\n"
            "    - GET_STATE(key): Reads an integer state key.\n"
            "    - ADD_STATE(key, integer): Increases/decreases a key by the input.\n\n"
            "Example Contract Code:\n"
            "  INIT_POOL(yield_rate=128, max_capacity=1000000);\n"
            "  SET_STATE(\"yield_rate\", 128);\n"
            "  SET_STATE(\"total_staked\", 0);\n\n"
            "Calling Deployed Contracts:\n"
            "  Execute state transitions with contract_call <contract_id> <method> <key> <value>\n"
            "  Supported RPC methods:\n"
            "    - set: Overwrites target key inside contract index space.\n"
            "    - add: Atomically updates key relative to current values.\n"
            "    - get: Performs high-speed reads of contract state values.\n"
        )
        c_text.configure(state="disabled")

        p_text = scrolledtext.ScrolledText(tab_doc_privacy, bg="#080c14", fg="#ffffff", bd=0, font=("Consolas", 10), padx=10, pady=10)
        p_text.pack(fill="both", expand=True)
        p_text.insert(tk.END,
            "========================================================================\n"
            "            L1 ZK-SHIELD & E2EE MESSAGING INTEGRATION MANUAL\n"
            "========================================================================\n\n"
            "1. GOLDILOCKS ZK-SHIELD (Zero-Knowledge Privacy)\n"
            "   Move transparent native coins into private note commitments, allowing untraceable transfers.\n"
            "   - zk_mint (privacy_mint_zk): Shields transparent funds to notes.\n"
            "   - zk_spend (privacy_spend_zk): Spends note commitments using STARK proofs.\n"
            "   - Double-spend protection is guaranteed via spent nullifiers, tracked in local indexes.\n\n"
            "2. E2EE ANONYMOUS MESSAGING (Time-To-Live Mailbox)\n"
            "   ADDITION natively hosts encrypted messages directly inside on-chain ephemeral mempools.\n"
            "   Messages are decrypted locally inside the recipient session. No intermediate servers or routers\n"
            "   can inspect the plain payloads.\n"
            "   - pm_send_ttl: Dispatches messages with absolute Time-To-Live (TTL) expiration limits.\n"
            "   - pm_inbox: Reads active message envelopes. Expired TTL messages are completely purged.\n"
            "   - E2EE Cipher: Diffie-Hellman P-256 / SHA-256 dynamic feedback stream cipher protects transport.\n"
        )
        p_text.configure(state="disabled")

        # 4. Whitepaper Tab Loading
        wp_text = scrolledtext.ScrolledText(tab_doc_whitepaper, bg="#080c14", fg="#ffffff", bd=0, font=("Consolas", 10), padx=10, pady=10)
        wp_text.pack(fill="both", expand=True)
        
        script_dir = os.path.dirname(os.path.abspath(__file__))
        wp_path = os.path.join(script_dir, "Assets", "whitepaper.txt")
        wp_content = ""
        if os.path.exists(wp_path):
            try:
                with open(wp_path, "r", encoding="utf-8") as wp_f:
                    wp_content = wp_f.read()
            except Exception as e:
                wp_content = f"[Error loading whitepaper] {e}"
        else:
            wp_content = "[Error] Assets/whitepaper.txt not found!"
            
        wp_text.insert(tk.END, wp_content)
        wp_text.configure(state="disabled")

    # Keystore & Wallet Accounts Event Handlers
    def on_wallet_account_changed(self, event):
        idx = self.wallet_selector.current()
        if 0 <= idx < len(self.saved_wallets):
            w = self.saved_wallets[idx]
            
            # Load keys into entry text inputs
            self.addr_entry.delete(0, tk.END)
            self.addr_entry.insert(0, w["address"])
            self.pub_entry.delete(0, tk.END)
            self.pub_entry.insert(0, w["pub"])
            self.priv_entry.delete(0, tk.END)
            self.priv_entry.insert(0, w["priv"])
            
            self.wallet_label_entry.delete(0, tk.END)
            self.wallet_label_entry.insert(0, w["label"])

            # Sync with mine and privacy tabs entries
            self.mine_addr.delete(0, tk.END)
            self.mine_addr.insert(0, w["address"])
            self.zk_mint_owner.delete(0, tk.END)
            self.zk_mint_owner.insert(0, w["address"])
            self.msg_sender.delete(0, tk.END)
            self.msg_sender.insert(0, w["address"])
            self.msg_inbox_addr.delete(0, tk.END)
            self.msg_inbox_addr.insert(0, w["address"])
            
            self.current_address = w["address"]
            self.current_pub = w["pub"]
            self.current_priv = w["priv"]
            
            # Auto query balance
            self.refresh_balance()

    def save_current_to_keystore(self):
        addr = self.addr_entry.get().strip()
        pub = self.pub_entry.get().strip()
        priv = self.priv_entry.get().strip()
        label = self.wallet_label_entry.get().strip()

        if not addr or not pub or not priv or not label:
            messagebox.showwarning("Keystore Manager", "Complete Wallet Address, PubKey, PrivKey, and Label fields.")
            return

        # Check if address already exists to overwrite
        existing_idx = -1
        for idx, w in enumerate(self.saved_wallets):
            if w["address"] == addr:
                existing_idx = idx
                break

        wallet_obj = {
            "label": label,
            "address": addr,
            "pub": pub,
            "priv": priv
        }

        if existing_idx != -1:
            self.saved_wallets[existing_idx] = wallet_obj
            msg = f"Account '{label}' updated in keystore successfully."
        else:
            self.saved_wallets.append(wallet_obj)
            msg = f"Account '{label}' registered to keystore persistently."

        self.save_wallets_to_disk()
        self.sync_selectors()
        
        # Keep selected in combobox
        for idx, w in enumerate(self.saved_wallets):
            if w["address"] == addr:
                self.wallet_selector.current(idx)
                break
                
        messagebox.showinfo("Keystore Sync", msg)

    def delete_account_from_keystore(self):
        idx = self.wallet_selector.current()
        if 0 <= idx < len(self.saved_wallets):
            label = self.saved_wallets[idx]["label"]
            if len(self.saved_wallets) <= 1:
                messagebox.showerror("Keystore Error", "Cannot delete the last remaining wallet in your keystore.")
                return
            
            confirm = messagebox.askyesno("Keystore Delete", f"Are you sure you want to permanently delete '{label}'?")
            if confirm:
                self.saved_wallets.pop(idx)
                self.save_wallets_to_disk()
                self.sync_selectors()
                messagebox.showinfo("Keystore Sync", f"Deleted account '{label}' successfully.")
        else:
            messagebox.showwarning("Keystore Selector", "Please select a valid account to delete.")

    def on_node_changed(self, event):
        idx = self.node_selector.current()
        if 0 <= idx < len(self.nodes):
            self.active_node_idx = idx
            cfg = self.nodes[idx]
            self.rpc = RpcClient(cfg["host"], cfg["port"], cfg["token"])
            self.status_label.config(text="● CONNECTING...", fg=self.accent_amber)
            self.refresh_balance()

    def on_cli_preset_selected(self, event):
        sel = self.cli_combobox.get()
        if "--" in sel:
            cmd = sel.split("--")[0].strip()
            self.cli_entry.delete(0, tk.END)
            self.cli_entry.insert(0, cmd)

    def _rpc(self, command: str) -> str:
        return self.rpc.call(command)

    def create_wallet(self):
        res = self._rpc("createwallet")
        if res.startswith("error"):
            messagebox.showerror("Wallet Setup", f"Could not create wallet over RPC:\n{res}")
            return

        parts = {}
        for item in res.split():
            if "=" in item:
                k, v = item.split("=", 1)
                parts[k] = v

        self.current_address = parts.get("address", "")
        self.current_pub = parts.get("pub", "")
        self.current_priv = parts.get("priv", "")

        self.addr_entry.delete(0, tk.END)
        self.addr_entry.insert(0, self.current_address)
        self.pub_entry.delete(0, tk.END)
        self.pub_entry.insert(0, self.current_pub)
        self.priv_entry.delete(0, tk.END)
        self.priv_entry.insert(0, self.current_priv)

        self.wallet_label_entry.delete(0, tk.END)
        self.wallet_label_entry.insert(0, f"Generated Wallet {random.randint(100, 999)}")

        self.mine_addr.delete(0, tk.END)
        self.mine_addr.insert(0, self.current_address)
        self.zk_mint_owner.delete(0, tk.END)
        self.zk_mint_owner.insert(0, self.current_address)
        self.msg_sender.delete(0, tk.END)
        self.msg_sender.insert(0, self.current_address)
        self.msg_inbox_addr.delete(0, tk.END)
        self.msg_inbox_addr.insert(0, self.current_address)

        messagebox.showinfo("Wallet Setup", "Quantum Wallet vectors compiled! Click 'Save to Keystore' to register persistently.")

    def load_wallet_fields(self):
        self.current_address = self.addr_entry.get().strip()
        self.current_pub = self.pub_entry.get().strip()
        self.current_priv = self.priv_entry.get().strip()
        
        if not self.current_address or not self.current_pub or not self.current_priv:
            messagebox.showwarning("Wallet Loader", "Please populate Address, Public Key and Private Key fields.")
            return
            
        self.mine_addr.delete(0, tk.END)
        self.mine_addr.insert(0, self.current_address)
        self.zk_mint_owner.delete(0, tk.END)
        self.zk_mint_owner.insert(0, self.current_address)
        self.msg_sender.delete(0, tk.END)
        self.msg_sender.insert(0, self.current_address)
        self.msg_inbox_addr.delete(0, tk.END)
        self.msg_inbox_addr.insert(0, self.current_address)
        
        messagebox.showinfo("Wallet Loader", "Wallet keys successfully loaded into session.")

    def refresh_balance(self):
        addr = self.addr_entry.get().strip()
        if not addr:
            return
        res = self._rpc(f"getbalance {addr}")
        if res.startswith("error"):
            self.balance_label.config(text="OFFLINE", fg=self.accent_red)
        else:
            try:
                val = float(res)
                if val >= 100000.0:  # satoshis conversion
                    val = val / 100000000.0
                self.balance_label.config(text=f"{val:.2f} ADD", fg=self.accent_red)
            except ValueError:
                if "=" in res:
                    self.balance_label.config(text=f"{res.split('=')[1]} ADD", fg=self.accent_red)
                else:
                    self.balance_label.config(text=f"{res} ADD", fg=self.accent_red)

    def send_transaction(self):
        from_addr = self.addr_entry.get().strip()
        pub = self.pub_entry.get().strip()
        priv = self.priv_entry.get().strip()
        to_addr = self.send_to.get().strip()
        amount = self.send_amount.get().strip()
        fee = self.send_fee.get().strip() or "0.001"
        nonce = self.send_nonce.get().strip() or "1"

        if not all([from_addr, pub, priv, to_addr, amount]):
            messagebox.showwarning("Transfer Error", "Please fill all transaction fields (From, Pub, Priv, To, Amount).")
            return

        # 1. Build unsigned tx
        sign_res = self._rpc(f"tx_build {from_addr} {pub} {to_addr} {amount} {fee} {nonce}")
        if sign_res.startswith("error"):
            messagebox.showerror("Transfer Error", f"tx_build failed: {sign_res}")
            return
        if not sign_res.startswith("sign_hash="):
            messagebox.showerror("Transfer Error", f"Unexpected response from tx_build: {sign_res}")
            return

        sign_hash = sign_res.split("=", 1)[1]
        
        # 2. Local signature generation
        sign_hex = sign_hash.encode("utf-8").hex()
        sig_res = self._rpc(f"sign_message {priv} {sign_hex}")
        if sig_res.startswith("error"):
            messagebox.showerror("Signature Error", f"sign_message failed: {sig_res}")
            return
        if not sig_res.startswith("pq="):
            messagebox.showerror("Signature Error", f"Unexpected response from sign_message: {sig_res}")
            return

        sig_hex_raw = sig_res[3:]
        
        # 3. Submit transaction
        res = self._rpc(f"sendtx_signed_hash {from_addr} {pub} {to_addr} {amount} {fee} {nonce} {sig_hex_raw}")
        if not res.startswith("error"):
            messagebox.showinfo("Success", f"Transaction submitted successfully! tx_hash={res}")
            try:
                self.send_nonce.delete(0, tk.END)
                self.send_nonce.insert(0, str(int(nonce) + 1))
            except Exception:
                pass
            self.refresh_balance()
        else:
            messagebox.showerror("Mempool Error", f"sendtx_signed_hash failed: {res}")

    def mine_block(self):
        addr = self.mine_addr.get().strip()
        cmd = f"mine {addr}" if addr else "mine"
        
        self.mine_once_btn.config(state="disabled", text="Solving...")
        self.root.update()
        
        def run():
            res = self._rpc(cmd)
            self.root.after(0, lambda: self.mine_once_btn.config(state="normal", text="Mine 1 Block"))
            if res.startswith("error"):
                self.root.after(0, lambda: messagebox.showerror("Mine Error", res))
            else:
                self.root.after(0, lambda: messagebox.showinfo("Consensus Secured", f"Block mined successfully!\n{res}"))
                self.root.after(0, self.refresh_balance)
                self.miner_log(f"[Mine Action] Mined block: {res}")
        
        threading.Thread(target=run, daemon=True).start()

    def toggle_mining_loop(self):
        if self.mining_loop_active:
            self.mining_loop_active = False
            self.loop_btn.config(text="Start Continuous Mining Loop", bg=self.accent_amber)
        else:
            self.mining_loop_active = True
            self.loop_btn.config(text="Stop Continuous Mining Loop", bg="#475569")
            t = threading.Thread(target=self.continuous_mine_worker, daemon=True)
            t.start()

    def continuous_mine_worker(self):
        addr = self.mine_addr.get().strip()
        self.miner_log("[Miner Thread] Starting continuous 1 MiB PoMW solver loop...")
        while self.mining_loop_active:
            cmd = f"mine {addr}" if addr else "mine"
            self.miner_log(f"[Miner Thread] Solving block at next height... sending command: {cmd}")
            start_time = time.time()
            res = self.rpc.call(cmd)
            elapsed = time.time() - start_time
            if "error" in res.lower() or res.startswith("error"):
                self.miner_log(f"[Miner Error] Core solver exception or timeout after {elapsed:.2f}s: {res}")
                time.sleep(2)
            else:
                self.miner_log(f"[Miner Success] Block solved in {elapsed:.2f}s! Result: {res}")
                self.root.after(0, self.refresh_balance)
            time.sleep(1)
        self.miner_log("[Miner Thread] Solver loop stopped.")

    def miner_log(self, text):
        ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.miner_console.configure(state="normal")
        self.miner_console.insert(tk.END, f"[{ts}] {text}\n")
        self.miner_console.configure(state="disabled")
        self.miner_console.see(tk.END)

    def stake(self):
        addr = self.addr_entry.get().strip()
        amount = self.stake_amount.get().strip()
        if not addr or not amount:
            messagebox.showwarning("Staking", "Please populate Wallet Address and Stake Amount.")
            return
        res = self._rpc(f"stake {addr} {amount}")
        if res == "ok":
            messagebox.showinfo("Staking Pool", "Stake registered successfully!")
            self.refresh_balance()
        else:
            messagebox.showerror("Staking Error", res)

    def unstake(self):
        addr = self.addr_entry.get().strip()
        amount = self.stake_amount.get().strip()
        if not addr or not amount:
            messagebox.showwarning("Staking", "Please populate Wallet Address and Unstake Amount.")
            return
        res = self._rpc(f"unstake {addr} {amount}")
        if res == "ok":
            messagebox.showinfo("Staking Pool", "Unstaked successfully! Funds unlocked on next block.")
            self.refresh_balance()
        else:
            messagebox.showerror("Staking Error", res)

    def claim_rewards(self):
        addr = self.addr_entry.get().strip()
        if not addr:
            messagebox.showwarning("Staking", "Please populate Wallet Address to claim.")
            return
        res = self._rpc(f"stake_claim {addr}")
        if res.startswith("error"):
            messagebox.showerror("Staking Error", res)
        else:
            messagebox.showinfo("Staking Pool", f"Claimed reward: {res} ADD")
            self.refresh_balance()

    def deploy_custom_token(self):
        sym = self.token_sym.get().strip().upper()
        name = self.token_name.get().strip().replace(" ", "_")
        owner = self.addr_entry.get().strip()
        decimals = self.token_dec.get().strip() or "18"
        max_supply = self.token_max.get().strip()
        initial_mint = self.token_mint.get().strip()
        burnable = "1" if self.token_burn.get().startswith("Yes") else "0"

        if not all([sym, name, owner, max_supply, initial_mint]):
            messagebox.showwarning("Token Factory", "Complete symbol, name, owner address, max supply and initial mint fields.")
            return

        cmd = f"token_create_ex {sym} {name} {owner} {max_supply} {initial_mint} {decimals} {burnable} - 0"
        res = self._rpc(cmd)
        if res.startswith("error"):
            messagebox.showerror("Token Deploy Error", res)
        else:
            messagebox.showinfo("Token Created", f"Token deployed successfully!\nResult: {res}")
            self.amm_token_b.delete(0, tk.END)
            self.amm_token_b.insert(0, sym)

    def create_amm_pool(self):
        token_b = self.amm_token_b.get().strip().upper()
        if not token_b:
            messagebox.showwarning("AMM Pool Factory", "Please enter a valid token ticker.")
            return
        res = self._rpc(f"swap_pool_create ADD {token_b} 30")
        if res.startswith("error"):
            messagebox.showerror("AMM Setup Error", res)
        else:
            messagebox.showinfo("AMM Pool Established", f"AMM Liquidity Pool for ADD / {token_b} created successfully!\nResult: {res}")

    def deploy_contract(self):
        code = self.contract_code.get("1.0", tk.END).strip()
        owner = self.addr_entry.get().strip()
        if not code or not owner:
            messagebox.showwarning("VM Compiler", "Ensure contract script code and Wallet Address (owner) are populated.")
            return

        self.contract_log("[Compiler] Deploying script to L1 VM state manager...")
        
        stripped_lines = []
        for line in code.splitlines():
            line_clean = line.strip()
            if line_clean and not line_clean.startswith("//"):
                stripped_lines.append(line_clean)
        
        compiled_script = " ".join(stripped_lines)
        res = self._rpc(f"contract_deploy {owner} {compiled_script}")
        
        if res.startswith("error"):
            self.contract_log(f"[Compiler Error] VM compilation crashed: {res}")
            messagebox.showerror("VM Error", res)
        else:
            self.contract_log(f"[Success] Contract deployed successfully!\nAddress ID: {res}")
            self.exec_cid.delete(0, tk.END)
            self.exec_cid.insert(0, res)
            messagebox.showinfo("VM Success", f"Smart Contract deployed to L1 Virtual Machine!\nContract Address ID: {res}")

    def execute_contract_call(self):
        cid = self.exec_cid.get().strip()
        method = self.exec_method.get().strip()
        key = self.exec_key.get().strip()
        val = self.exec_val.get().strip() or "0"

        if not all([cid, method, key]):
            messagebox.showwarning("VM Executor", "Please fill contract ID, select a method and enter a state key.")
            return

        self.contract_log(f"[Executor] Invoking contract_call: {method} key='{key}' value={val}...")
        
        res = self._rpc(f"contract_call {cid} {method} {key} {val}")
        if res.startswith("error"):
            self.contract_log(f"[Executor Error] State transition failed: {res}")
            messagebox.showerror("VM Call Error", res)
        else:
            self.contract_log(f"[VM Returned] Result: {res}")

    def contract_log(self, text):
        self.contract_log_box.insert(tk.END, f"\n{text}")
        self.contract_log_box.see(tk.END)

    def refresh_zk_status(self):
        res = self._rpc("privacy_status")
        if res.startswith("error"):
            self.zk_status_lbl.config(text="ZK pool offline.\nEnsure C++ validation daemon is running.", fg=self.accent_red)
        else:
            pretty = res.replace(" ", "\n").replace("=", ": ")
            self.zk_status_lbl.config(text=pretty, fg=self.accent_amber)

    def execute_zk_mint(self):
        owner = self.zk_mint_owner.get().strip()
        amt = self.zk_mint_amt.get().strip()
        commit = self.zk_mint_commit.get().strip()
        proof = self.zk_mint_proof.get().strip()
        
        if not owner or not amt:
            messagebox.showwarning("ZK Shield", "Owner address and Mint Amount are required.")
            return

        if not commit:
            commit = hashlib.sha256(f"note|{amt}|{random.random()}".encode()).hexdigest()
            self.zk_mint_commit.delete(0, tk.END)
            self.zk_mint_commit.insert(0, commit)

        nullifier = hashlib.sha256(f"nf|{random.random()}".encode()).hexdigest()
        
        if not proof:
            proof = f"stark_proof_gf64_mint_{hex(random.randint(100000, 999999))}"
            self.zk_mint_proof.delete(0, tk.END)
            self.zk_mint_proof.insert(0, proof)
            
        vk = f"vk_dilithium5_goldilocks_stark"

        cmd = f"privacy_mint_zk {owner} {amt} {commit} {nullifier} {proof} {vk}"
        res = self._rpc(cmd)
        
        if res.startswith("error"):
            messagebox.showerror("ZK Shield Error", res)
        else:
            messagebox.showinfo("ZK Coins Shielded", f"Successfully shielded {amt} ADD into ZK-Shield!\nResult: {res}")
            self.zk_spend_null.delete(0, tk.END)
            self.zk_spend_null.insert(0, nullifier)
            self.refresh_zk_status()

    def execute_zk_spend(self):
        recip = self.zk_spend_recip.get().strip()
        amt = self.zk_spend_amt.get().strip()
        nullifier = self.zk_spend_null.get().strip()
        proof = self.zk_spend_proof.get().strip()
        owner = self.addr_entry.get().strip() or "miner1"

        if not recip or not amt or not nullifier:
            messagebox.showwarning("ZK Shield", "Recipient address, Spend Amount, and Nullifier are required.")
            return

        if not proof:
            proof = f"stark_proof_gf64_spend_{hex(random.randint(100000, 999999))}"
            self.zk_spend_proof.delete(0, tk.END)
            self.zk_spend_proof.insert(0, proof)

        vk = f"vk_dilithium5_goldilocks_stark"
        note_id = "0"

        cmd = f"privacy_spend_zk {owner} {note_id} {recip} {amt} {nullifier} {proof} {vk}"
        res = self._rpc(cmd)
        
        if res.startswith("error"):
            messagebox.showerror("ZK Shield Spend Error", res)
        else:
            messagebox.showinfo("ZK Shield Spend", f"Successfully spent shielded Note!\nResult: {res}")
            self.refresh_zk_status()

    def show_our_dh_pub(self):
        popup = tk.Toplevel(self.root)
        popup.title("Our Session E2EE DH Keys")
        popup.geometry("600x260")
        popup.configure(bg="#0b0f19")
        popup.grab_set()

        tk.Label(popup, text="Your Diffie-Hellman Session Public Key", bg="#0b0f19", fg=self.accent_red, font=("Segoe UI", 12, "bold"), pady=10).pack()
        
        text_box = scrolledtext.ScrolledText(popup, bg="#161f30", fg="white", bd=0, font=("Consolas", 10), height=6)
        text_box.pack(fill="both", expand=True, padx=15, pady=(0, 15))
        text_box.insert(tk.END, str(self.dh_pub))
        text_box.configure(state="disabled")

    def send_e2ee_message(self):
        sender = self.msg_sender.get().strip()
        recip = self.msg_recipient.get().strip()
        recip_dh_str = self.msg_recip_dh.get().strip()
        ttl = self.msg_ttl.get().strip() or "300"
        body = self.msg_body.get("1.0", tk.END).strip()

        if not sender or not recip or not body:
            messagebox.showwarning("E2EE Messaging", "Sender, Recipient, and Message content are required.")
            return

        if recip_dh_str:
            try:
                their_dh_pub = int(recip_dh_str)
                shared_secret = derive_shared_secret(self.dh_priv, their_dh_pub)
                encrypted_payload = encrypt_payload(shared_secret, body)
                payload_to_send = encrypted_payload
                mode = "[E2EE ENCRYPTED DISPATCH]"
            except ValueError:
                messagebox.showerror("E2EE Error", "Invalid Recipient DH Public Key. Must be a large integer.")
                return
        else:
            payload_to_send = body.encode("utf-8").hex()
            mode = "[PLAIN HEX DISPATCH (NO RECIPIENT DH KEY PROVIDED)]"
            messagebox.showwarning("Messaging Warning", "No Recipient DH Key provided. Message sent in plain hex.")

        cmd = f"pm_send_ttl {sender} {recip} {payload_to_send} {ttl}"
        res = self._rpc(cmd)
        
        if res.startswith("error"):
            messagebox.showerror("Messaging Error", res)
        else:
            messagebox.showinfo("Message Dispatched", f"Message sent successfully! {mode}\nMessage ID: {res}")
            self.msg_body.delete("1.0", tk.END)

    def fetch_inbox_messages(self):
        addr = self.msg_inbox_addr.get().strip()
        if not addr:
            messagebox.showwarning("Messaging Hub", "Please populate your Recipient L1 Address first.")
            return

        self.inbox_console.delete("1.0", tk.END)
        self.inbox_console.insert(tk.END, "[Mailbox] Fetching envelopes from L1 mempool...\n")
        
        res = self._rpc(f"pm_inbox {addr}")
        if res.startswith("error"):
            self.inbox_console.insert(tk.END, f"[Inbox Error] Could not query inbox: {res}\n")
            return

        lines = res.splitlines()
        envelopes_count = 0
        
        for line in lines:
            line = line.strip()
            if not line or "count=" in line:
                continue
            envelopes_count += 1
            
            parts = {}
            for item in line.split(" "):
                if "=" in item:
                    k, v = item.split("=", 1)
                    parts[k] = v

            msg_id = parts.get("id", "N/A")
            msg_sender = parts.get("sender", "N/A")
            msg_time = parts.get("time", "N/A")
            msg_payload = parts.get("payload", "")

            try:
                date_str = datetime.fromtimestamp(int(msg_time)).strftime("%H:%M:%S")
            except Exception:
                date_str = msg_time

            self.inbox_console.insert(tk.END, f"\n----------------------------------------------------\n")
            self.inbox_console.insert(tk.END, f"Envelope ID: {msg_id} | From: {msg_sender[:16]}... | Received: {date_str}\n")
            
            if msg_payload.startswith("e2ee:"):
                self.inbox_console.insert(tk.END, f"Payload type: E2EE Cipher Envelope\n")
                
                def ask_for_dh_pub():
                    return tk.simpledialog.askstring(
                        "E2EE Decryption Hub", 
                        f"Enter Sender's DH Public Key (large integer) for Message {msg_id}:\n"
                        f"(Leave empty to view raw ciphertext)",
                        parent=self.root
                    )
                
                their_dh_str = ask_for_dh_pub()
                if their_dh_str:
                    try:
                        their_pub = int(their_dh_str.strip())
                        shared_secret = derive_shared_secret(self.dh_priv, their_pub)
                        decrypted = decrypt_payload(shared_secret, msg_payload)
                        self.inbox_console.insert(tk.END, f"Content: [E2EE Decrypted Payload]\n>> {decrypted}\n")
                    except Exception as ex:
                        self.inbox_console.insert(tk.END, f"Content: [Decryption Failed: {ex}]\nRaw Payload: {msg_payload}\n")
                else:
                    self.inbox_console.insert(tk.END, f"Content: [Encrypted Payload]\nRaw Payload: {msg_payload}\n")
            else:
                try:
                    dec = bytes.fromhex(msg_payload).decode("utf-8")
                    self.inbox_console.insert(tk.END, f"Content: [Plain Hex Decoded]\n>> {dec}\n")
                except Exception:
                    self.inbox_console.insert(tk.END, f"Content: [Plaintext Raw]\n>> {msg_payload}\n")

        if envelopes_count == 0:
            self.inbox_console.insert(tk.END, "\n[Mailbox] No active messages found in your anonymous L1 mailbox.")

    def execute_cli_command(self):
        cmd = self.cli_entry.get().strip()
        if not cmd:
            return

        self.cli_screen.configure(state="normal")
        self.cli_screen.insert(tk.END, f"\n\n$ addition-cli {cmd}\n")
        self.cli_screen.configure(state="disabled")
        
        def run():
            res = self._rpc(cmd)
            
            def update_ui():
                self.cli_screen.configure(state="normal")
                self.cli_screen.insert(tk.END, res)
                self.cli_screen.configure(state="disabled")
                self.cli_screen.see(tk.END)
                
            self.root.after(0, update_ui)

        threading.Thread(target=run, daemon=True).start()

    def refresh_blocks_grid(self):
        for item in self.explorer_tree.get_children():
            self.explorer_tree.delete(item)

        res = self._rpc("getblocks")
        if res.startswith("error"):
            messagebox.showerror("Explorer Error", f"Could not fetch blocks: {res}")
            return

        lines = res.splitlines()
        for line in lines:
            line = line.strip()
            if not line or line.startswith("count="):
                continue
            
            params = {}
            for item in line.split(" "):
                if "=" in item:
                    k, v = item.split("=", 1)
                    params[k] = v

            h = params.get("height", "")
            h_hash = params.get("hash", "")
            timestamp = params.get("time", "")
            txs_cnt = params.get("txs", "")
            nonce = params.get("nonce", "")
            diff = params.get("diff", "")

            try:
                date_str = datetime.fromtimestamp(int(timestamp)).strftime("%Y-%m-%d %H:%M:%S")
            except Exception:
                date_str = timestamp

            self.explorer_tree.insert("", tk.END, values=(h, h_hash, date_str, txs_cnt, nonce, diff))

    def on_block_double_click(self, event):
        item = self.explorer_tree.selection()
        if not item:
            return
        block_values = self.explorer_tree.item(item, "values")
        h = block_values[0]

        res = self._rpc(f"getblock {h}")
        if res.startswith("error"):
            messagebox.showerror("Block Details", f"Could not get block details:\n{res}")
            return

        params = {}
        txs = []
        for line in res.splitlines():
            line = line.strip()
            if "=" in line:
                k, v = line.split("=", 1)
                if k.startswith("tx_"):
                    txs.append(v)
                else:
                    params[k] = v

        popup = tk.Toplevel(self.root)
        popup.title(f"Detailed Specifications - Block Height #{h}")
        popup.geometry("720x460")
        popup.configure(bg="#0b0f19")
        popup.grab_set()

        title_lbl = tk.Label(popup, text=f"Block height #{h} Details", bg="#0b0f19", fg=self.accent_red, font=("Segoe UI", 14, "bold"), pady=10)
        title_lbl.pack()

        details_box = scrolledtext.ScrolledText(popup, bg="#161f30", fg="white", bd=0, font=("Consolas", 9), padx=10, pady=10)
        details_box.pack(fill="both", expand=True, padx=15, pady=(0, 15))

        summary = (
            f"Consensus Type: Proof of Measurable Work (1 MiB memory-hard)\n"
            f"Block height:   {h}\n"
            f"Block Hash:     {params.get('hash', block_values[1])}\n"
            f"Parent Hash:    {params.get('prev', '0')}\n"
            f"Merkle Root:    {params.get('merkle', 'N/A')}\n"
            f"Timestamp:      {block_values[2]} (Unix: {params.get('time', '')})\n"
            f"Consensus Nonce:{params.get('nonce', '')}\n"
            f"Difficulty:     {params.get('diff', '')}\n"
            f"Tx Count:       {params.get('txs', '0')}\n\n"
            f"Transactions Included ({len(txs)}):\n"
        )
        for i, tx in enumerate(txs):
            summary += f"  [{i}] {tx}\n"

        details_box.insert(tk.END, summary)
        details_box.configure(state="disabled")

    def _poll(self):
        while True:
            res = self.rpc.call("getinfo")
            if "error" in res.lower() or res.startswith("error"):
                self.status_label.config(text="● NODE OFFLINE", fg=self.accent_red)
                self.stats_grid_frame.pack_forget()
                self.offline_error_label.config(
                    text=f"Connection refused to {self.rpc.host}:{self.rpc.port}.\n\nIs additiond.exe running?",
                    fg=self.accent_red
                )
                self.offline_error_label.pack(fill="both", expand=True, pady=10)
            else:
                self.status_label.config(text="● NODE ONLINE", fg="#10b981")
                self.offline_error_label.pack_forget()
                self.stats_grid_frame.pack(fill="both", expand=True, pady=4)
                
                # Parse key-value status pairs
                stats_dict = {}
                for item in res.split(" "):
                    if "=" in item:
                        parts = item.split("=", 1)
                        stats_dict[parts[0].strip()] = parts[1].strip()
                        
                for key, lbl in self.stat_labels.items():
                    val = stats_dict.get(key, "N/A")
                    
                    # Format standard values elegantly
                    if key == "next_reward" and val != "N/A":
                        try:
                            val = f"{float(val)/1e8:.2f} ADD"
                        except:
                            pass
                    elif key == "fees_last_block" and val != "N/A":
                        try:
                            val = f"{float(val)/1e8:.4f} ADD"
                        except:
                            pass
                    elif key == "total_staked" and val != "N/A":
                        try:
                            val = f"{float(val):.2f} ADD"
                        except:
                            pass
                    elif key == "max_supply" and val != "N/A":
                        try:
                            val = f"{float(val):,.0f}"
                        except:
                            pass
                    elif key == "last_mine_ms" and val != "N/A":
                        try:
                            val = f"{int(val)} ms"
                        except:
                            pass
                    
                    # Style flags with custom colors
                    if val in ["enabled", "strict"]:
                        lbl.config(text=val.upper(), fg="#10b981")
                    else:
                        lbl.config(text=val, fg=self.text_white)
                        
                self.root.after(0, self.refresh_balance)

            threading.Event().wait(4)

    def _start_poll_thread(self):
        t = threading.Thread(target=self._poll, daemon=True)
        t.start()


if __name__ == "__main__":
    import tkinter.simpledialog
    root = tk.Tk()
    app = AdditionWalletGUI(root)
    root.mainloop()
