#!/usr/bin/env python3

import os, sys, subprocess, re
import base64
import secrets
import datetime

import mysql.connector
from types import SimpleNamespace
from cryptography.fernet import Fernet

from config_i import config
import database_i
import security_i
import create_wallet_i

IOTA_BIN = os.path.expanduser("~/.cargo/bin/iota")
env = os.environ.copy()
env["LD_LIBRARY_PATH"] = "/usr/lib64/c++-plesk-13.2.0/lib64:" + env.get("LD_LIBRARY_PATH", "")


def atavism_player_exists(user_id) -> bool:
    """Check if Atavism player exists"""
    print(f"{datetime.datetime.now()}: create_iota_user.py | Checking Atavism that user {user_id} does exist.", file=sys.stderr)
    with database_i.get_connection(config.db.atavism.master) as atavism_conn:
        cursor = atavism_conn.cursor()
        cursor.execute("SELECT id FROM account WHERE id = %s", (user_id,))
        if cursor.fetchone() is None:
            cursor.close()
            return False
        cursor.close()
        return True

def tr1_player_exists(user_id) -> bool:
    """Check if TR1 player exists"""
    print(f"{datetime.datetime.now()}: create_iota_user.py | Checking TR1 if user {user_id} does not already exist.", file=sys.stderr)
    with database_i.get_connection(config.db.tr1) as tr1_conn:
        cursor = tr1_conn.cursor()
        cursor.execute("SELECT user_id FROM users WHERE user_id = %s", (user_id,))
        if cursor.fetchone() is None:
            cursor.close()
            return False
        cursor.close()
        return True

def create_iota_user(user_id) -> tuple[str, str]:
    """Create IOTA (Rebased) wallet for the user and save to TR1"""
    print(f"{datetime.datetime.now()}: create_iota_user.py | Creating new user with ID {user_id} ...", file=sys.stderr)

    # Create address via CLI with alias u<user_id>
    alias = f"u{user_id}"
    print(f"{datetime.datetime.now()}: create_iota_user.py | create_iota_user | Running iota client new-address for {alias} ...", file=sys.stderr)
    try:
        proc = subprocess.run(
            [IOTA_BIN, "client", "new-address", "--alias", alias, "--key-scheme", "ed25519", "--word-length", "word24"],
            capture_output=True, text=True, check=True
        )
        print(f"Finished running IOTA command")
        out = proc.stdout
        print(f"{datetime.datetime.now()}: create_iota_user.py|create_iota_user | {proc.returncode}", file=sys.stderr)
        print(f"Finished printing output")
        # Extract address and recovery phrase from the tabular output
        # Example lines:
        # │ address                 │ 0x5f0e...d084 │
        # │ recoveryPhrase          │ word1 word2 ... word24 │
        addr_match = re.search(r"^\s*│\s*address\s*│\s*(0x[0-9a-fA-F]+)\s*│", out, re.MULTILINE)
        mnem_match = re.search(r"^\s*│\s*recoveryPhrase\s*│\s*(.+?)\s*│\s*$", out, re.MULTILINE)

        if not addr_match or not mnem_match:
            raise RuntimeError("Could not parse address/mnemonic from CLI output.")

        wallet_address = addr_match.group(1)
        wallet_mnemonic = mnem_match.group(1)
        print(f"{datetime.datetime.now()}: create_iota_user.py | Wallet address {wallet_address} created for user {user_id}.", file=sys.stderr)

    except Exception as e:
        print(f"Failed to run: {e}")
        return {
            "status": "failure",
            "error": e,
            "message": f"{datetime.datetime.now()}: create_iota_user.py | Failed to create IOTA wallet.",
        }

    try:
        # Encrypt mnemonic (same method as SMR mnemonic)
        wallet_im = security_i.encrypt(wallet_mnemonic)

        # Insert into TR1 DB (store IOTA address + encrypted mnemonic)
        with database_i.get_connection(config.db.tr1) as tr1_conn:
            cursor = tr1_conn.cursor()
            cursor.execute("""
                INSERT INTO users (user_id, wallet_i, wallet_im)
                VALUES (%s, %s, %s)
                ON DUPLICATE KEY UPDATE
                    wallet_i = VALUES(wallet_i),
                    wallet_im = VALUES(wallet_im)
            """, (user_id, wallet_address, wallet_im))
            tr1_conn.commit()
            cursor.close()
            print(f"{datetime.datetime.now()}: create_iota_user.py | User {user_id} with IOTA address {wallet_address} inserted into TR1 DB.", file=sys.stderr)

    except Exception as e:
        return {
            "status": "failure",
            "error": e,
            "message": f"{datetime.datetime.now()}: create_iota_user.py | Failed to insert into TR1 DB.",
        }

    return {
        "status": "success",
        "error": "",
        "message": f"{datetime.datetime.now()}: create_iota_user.py | IOTA wallet created and saved for {user_id} to TR1."
    }



# Main function
def main(user_id : str, TESTING = False, DELETE = False):
    """Main function"""
    #user_id = str(args[0])
    #TESTING = "test" in args
    #DELETE = "delete" in args

    if not atavism_player_exists(user_id):
        print("User ID not found in Atavism DB.")
        return {
            "status"  : "Failure",
            "message" : "Invalid Atavism user."
        }

    # Check TR1 DB for duplicates
#    if tr1_player_exists(user_id):
#        print("User ID already exists in TR1 DB.")
#        return {
#            "status"  : "Failure",
#            "message" : "User ID already exists in TR1 DB."
#        }

    return create_iota_user(user_id)

# Entry point
if __name__ == "__main__":
    if len(sys.argv) < 2 or not sys.argv[1].isdigit():
        print("Usage: create_user.py <user_id> [test] [delete]")
        result = main ("37")
    else:
        result = main([sys.argv[1]])

    print(result)
