#!/usr/bin/env python3
"""
energon-miner.py -- Public CPU miner for the Energon blockchain.

This script connects to YOUR LOCAL energond daemon via RPC and calls
generatetoaddress() to mine blocks.  You must have energond running
locally with RPC enabled.  No credentials are hardcoded.

Usage:
    python3 energon-miner.py --config ~/.energon/miner.conf
    python3 energon-miner.py --rpcuser energon --rpcpass yourpass --address bc1...

The script asks for credentials on first run and saves them to a local
config file (mode 0600) so you do not have to re-enter them.
"""
import os, sys, json, time, subprocess, argparse, configparser, signal

DEFAULT_CONFIG = os.path.expanduser("~/.energon/miner.conf")
SAMPLE_CONF = """[rpc]
user = energon
password = CHANGEME
host = 127.0.0.1
port = 17779

[mining]
address = YOUR_BC1_ADDRESS_HERE
threads = 1
interval = 5
"""

run_flag = True
def stop(sig, frame):
    global run_flag
    run_flag = False
    print("\n[miner] Stopping...")
signal.signal(signal.SIGINT, stop)
signal.signal(signal.SIGTERM, stop)

def read_config(path):
    cp = configparser.ConfigParser()
    if os.path.isfile(path):
        cp.read(path)
    return cp

def save_config(path, cp):
    os.makedirs(os.path.dirname(path), mode=0o700, exist_ok=True)
    with open(path, "w") as f:
        cp.write(f)
    os.chmod(path, 0o600)

def rpc_call(user, password, host, port, method, params=None):
    payload = json.dumps({"jsonrpc": "1.0", "id": method, "method": method, "params": params or []})
    cmd = ["curl", "-s", "--user", f"{user}:{password}",
           "--data-binary", payload, "-H", "content-type: text/plain;",
           f"http://{host}:{port}/"]
    out = subprocess.check_output(cmd, timeout=30, text=True)
    r = json.loads(out)
    if r.get("error"):
        raise RuntimeError(r["error"])
    return r["result"]

def main():
    p = argparse.ArgumentParser(description="Energon CPU miner — mines to your own local daemon.")
    p.add_argument("--config", default=DEFAULT_CONFIG, help="Config file path")
    p.add_argument("--rpcuser", help="RPC username")
    p.add_argument("--rpcpass", help="RPC password")
    p.add_argument("--address", help="Mining payout address (bc1*)")
    p.add_argument("--threads", type=int, default=1, help="Mining threads (energon generatetoaddress blocks)")
    p.add_argument("--init", action="store_true", help="Write a sample config and exit")
    args = p.parse_args()

    if args.init:
        print(f"Writing sample config to {args.config}")
        with open(args.config, "w") as f:
            f.write(SAMPLE_CONF)
        os.chmod(args.config, 0o600)
        print("Done.  Edit it with your real RPC credentials and address, then run again.")
        return

    cp = read_config(args.config)
    user = args.rpcuser or cp.get("rpc", "user", fallback=None) or os.environ.get("ENERGON_RPC_USER")
    password = args.rpcpass or cp.get("rpc", "password", fallback=None) or os.environ.get("ENERGON_RPC_PASS")
    host = cp.get("rpc", "host", fallback="127.0.0.1")
    port = cp.get("rpc", "port", fallback="17779")
    address = args.address or cp.get("mining", "address", fallback=None)
    threads = args.threads or cp.getint("mining", "threads", fallback=1)
    interval = cp.getint("mining", "interval", fallback=5)

    if not all([user, password, address]):
        print("ERROR: Need RPC credentials and mining address.")
        print(f"Run: python3 {sys.argv[0]} --init")
        print("Then edit the config and run again.")
        sys.exit(1)

    # Validate address prefix
    if not address.startswith(("bc1", "1", "3")):
        print("WARNING: Address does not look like a standard Energon address.")

    print("=" * 50)
    print("  ENERGON CPU MINER")
    print("=" * 50)
    print(f"  RPC:     http://{user}:****@{host}:{port}")
    print(f"  Address: {address}")
    print(f"  Threads: {threads}")
    print("  Press Ctrl+C to stop")
    print("=" * 50)

    mined = 0
    while run_flag:
        try:
            # generatetoaddress mines 1 block per call
            hashes = rpc_call(user, password, host, port, "generatetoaddress", [threads, address])
            if hashes:
                mined += len(hashes)
                print(f"[{time.strftime('%H:%M:%S')}] Mined {len(hashes)} block(s) — total {mined} — hash {hashes[0][:16]}...")
            else:
                print(f"[{time.strftime('%H:%M:%S')}] No block mined (still processing?)")
        except subprocess.CalledProcessError:
            print(f"[{time.strftime('%H:%M:%S')}] RPC failed — is energond running? Retrying in {interval}s...")
        except RuntimeError as e:
            print(f"[{time.strftime('%H:%M:%S')}] RPC error: {e}")
        except Exception as e:
            print(f"[{time.strftime('%H:%M:%S')}] Error: {e}")
        if run_flag:
            time.sleep(interval)

if __name__ == "__main__":
    main()
