#!/usr/bin/env python3
import sys
import subprocess
import urllib.request
import random
import time
import datetime
import os
import platform
import shutil

PROGRAM_NAME = "babicli"
VERSION = "0.2.0"


# ------------------------------------------------------------
# NETINFO
# ------------------------------------------------------------
def cmd_netinfo():
    print("== Network Information ==")

    local = subprocess.getoutput("hostname -I").strip()
    local_ips = [ip for ip in local.split() if ip]

    print("Local IPs:")
    if not local_ips:
        print("  none")
    else:
        for ip in local_ips:
            print(f"  - {ip}")

    try:
        public_ip = urllib.request.urlopen("https://api.ipify.org", timeout=4).read().decode().strip()
    except Exception:
        public_ip = "Unavailable"

    print(f"Public IP: {public_ip}")


# ------------------------------------------------------------
# UPDATE
# ------------------------------------------------------------
def cmd_update():
    print(f"{PROGRAM_NAME} {VERSION}\n")
    print("To update this tool, run:")
    print(f"  pip install --upgrade {PROGRAM_NAME}")


# ------------------------------------------------------------
# SYSINFO (GEAVANCEERD ZONDER EXTERNE LIBS)
# ------------------------------------------------------------
def get_uptime():
    try:
        with open("/proc/uptime", "r") as f:
            seconds = float(f.read().split()[0])
        mins = seconds / 60
        hours = mins / 60
        days = hours / 24
        return f"{int(days)}d {int(hours % 24)}h {int(mins % 60)}m"
    except:
        return "Unknown"


def cmd_sysinfo():
    print("== System Information ==\n")

    print(f"OS:        {platform.system()} {platform.release()}")
    print(f"Kernel:    {platform.version()}")
    print(f"Machine:   {platform.machine()}")
    print(f"Hostname:  {platform.node()}")
    print(f"Python:    {platform.python_version()}")
    print(f"Uptime:    {get_uptime()}")
    print()

    # CPU INFO
    print("== CPU ==")
    print(f"CPU:       {platform.processor() or 'Unknown'}")
    try:
        load = subprocess.getoutput("cat /proc/loadavg").split()[0]
        print(f"Load:      {load}")
    except:
        print("Load:      Unknown")

    # RAM (Linux only)
    print("\n== Memory ==")
    try:
        meminfo = {}
        with open("/proc/meminfo") as f:
            for line in f:
                k, v = line.split(":")
                meminfo[k] = int(v.strip().split()[0])

        total = meminfo["MemTotal"] // 1024
        free = meminfo["MemAvailable"] // 1024
        used = total - free

        print(f"Total:     {total} MB")
        print(f"Used:      {used} MB")
        print(f"Free:      {free} MB")
    except:
        print("Memory info unavailable")

    # DISK
    print("\n== Storage ==")
    try:
        total, used, free = shutil.disk_usage("/")
        print(f"Total:     {total // (1024**3)} GB")
        print(f"Used:      {used // (1024**3)} GB")
        print(f"Free:      {free // (1024**3)} GB")
    except:
        print("Disk info unavailable")


# ------------------------------------------------------------
# RANUM (100–250 COMPLEXE CALCULATIES + 32 CHARS)
# ------------------------------------------------------------
def cmd_ranum():
    # Startmateriaal
    seed = (
        int(time.time_ns()) ^
        int(datetime.datetime.utcnow().timestamp() * 1_000_000) ^
        os.getpid() ^
        random.getrandbits(64)
    )
    random.seed(seed)

    ENTROPY = [
        9872657338790,
        86798605590822222222222,
        12893712983719283791823,
        998877665544332211,
        55555555555555555,
        11223344556677889900,
        324399102873419912938039284,
        7766554433221100,
        12345678901234567890,
        102938475610293847561029384756,
        56473829105647382910,
        1928374655647382910,
        11111111111111111111,
        22222222222222222222,
        9876789102398127364890,
    ]

    # 2 basisnummers
    a = random.getrandbits(256) ^ random.choice(ENTROPY)
    b = random.getrandbits(256) ^ int(time.time_ns())

    result = abs(a * b)

    # 100–250 iteraties
    loops = random.randint(100, 250)

    for _ in range(loops):
        r = (
            random.getrandbits(256) ^
            int(time.time_ns()) ^
            random.choice(ENTROPY)
        )

        op = random.choice(["+", "-", "*", "/"])

        if op == "+":
            result += r
        elif op == "-":
            result = abs(result - r)
        elif op == "*":
            result *= r
        elif op == "/":
            r = r or 1
            result //= r

        if result < 0:
            result = abs(result)

    s = str(result)

    # kort → verlengen
    if len(s) < 32:
        s = s + str(random.getrandbits(256))

    # lang → random 32 chars
    if len(s) > 32:
        idx = sorted(random.sample(range(len(s)), 32))
        s = "".join(s[i] for i in idx)

    print(s)


# ------------------------------------------------------------
# HELP
# ------------------------------------------------------------
def cmd_help():
    print(f"""{PROGRAM_NAME} – commandline utility (v{VERSION})

USAGE:
  {PROGRAM_NAME} help
  {PROGRAM_NAME} netinfo
  {PROGRAM_NAME} update
  {PROGRAM_NAME} sysinfo
  {PROGRAM_NAME} ranum

COMMANDS:
  help        Show help
  netinfo     Show IP information
  update      Show pip update command
  sysinfo     Advanced system information
  ranum       32-char advanced random generator
""")


# ------------------------------------------------------------
# MAIN ENTRY
# ------------------------------------------------------------
def main():
    if len(sys.argv) < 2:
        cmd_help()
        return

    cmd = sys.argv[1].lower()

    commands = {
        "help": cmd_help,
        "netinfo": cmd_netinfo,
        "update": cmd_update,
        "sysinfo": cmd_sysinfo,
        "ranum": cmd_ranum,
    }

    if cmd not in commands:
        print(f"Unknown command: {cmd}\n")
        cmd_help()
        return

    commands[cmd]()


if __name__ == "__main__":
    main()
