import psutil
import os


def get_folder_size(folder_path: str) -> int:
    total_size = 0
    try:
        for dirpath, dirnames, filenames in os.walk(folder_path):
            for file in filenames:
                file_path = os.path.join(dirpath, file)
                try:
                    total_size += os.path.getsize(file_path)
                except BaseException:
                    pass
    except BaseException:
        pass
    return total_size


def top_processes() -> dict:
    # Get the process information
    processes = [p for p in psutil.process_iter(['pid', 'name', 'username', 'cpu_percent', 'memory_info']) if p.info['name'] != '']
    num_cores = psutil.cpu_count()
    # Calculate memory usage, RAM usage, and CPU usage for each process
    memory_usage = {}
    ram_usage = {}
    cpu_usage = {}
    for p in processes:
        name = p.info['name']
        if p.info['username']=="hiddify-panel":
            name = "Hiddify"
        # mem_info = p.info['memory_full_info']
        # if mem_info is None:
        #     continue
        # mem_usage = mem_info.uss
        mem_usage = p.info['memory_info'].rss
        cpu_percent = p.info['cpu_percent'] / num_cores
        if name in memory_usage:
            memory_usage[name] += mem_usage / (1024 ** 3)
            ram_usage[name] += mem_usage / (1024 ** 3)
            cpu_usage[name] += cpu_percent
        else:
            memory_usage[name] = mem_usage / (1024 ** 3)
            ram_usage[name] = mem_usage / (1024 ** 3)
            cpu_usage[name] = cpu_percent

    while len(cpu_usage) < 5:
        cpu_usage[" " * len(cpu_usage)] = 0
    while len(ram_usage) < 5:
        ram_usage[" " * len(ram_usage)] = 0
    while len(memory_usage) < 5:
        memory_usage[" " * len(memory_usage)] = 0
    # Sort the processes by memory usage, RAM usage, and CPU usage
    top_memory = sorted(memory_usage.items(), key=lambda x: x[1], reverse=True)[:5]
    top_ram = sorted(ram_usage.items(), key=lambda x: x[1], reverse=True)[:5]
    top_cpu = sorted(cpu_usage.items(), key=lambda x: x[1], reverse=True)[:5]

    # Return the top processes for memory usage, RAM usage, and CPU usage
    return {
        "memory": top_memory,
        "ram": top_ram,
        "cpu": top_cpu
    }


def system_stats() -> dict:
    # CPU usage
    cpu_percent = psutil.cpu_percent(interval=1)

    # RAM usage
    ram_stats = psutil.virtual_memory()
    ram_used = ram_stats.used / 1024**3
    ram_total = ram_stats.total / 1024**3

    # Disk usage (in GB)
    disk_stats = psutil.disk_usage('/')
    disk_used = disk_stats.used / 1024**3
    disk_total = disk_stats.total / 1024**3

    hiddify_used = get_folder_size('/opt/hiddify-manager/') / 1024**3

    # Network usage
    net_stats = psutil.net_io_counters()
    bytes_sent_cumulative = net_stats.bytes_sent
    bytes_recv_cumulative = net_stats.bytes_recv
    bytes_sent = net_stats.bytes_sent - getattr(system_stats, 'prev_bytes_sent', 0)
    bytes_recv = net_stats.bytes_recv - getattr(system_stats, 'prev_bytes_recv', 0)
    system_stats.prev_bytes_sent = net_stats.bytes_sent
    system_stats.prev_bytes_recv = net_stats.bytes_recv

    # Total connections and unique IPs
    connections = psutil.net_connections()
    total_connections = len(connections)
    unique_ips = set([conn.raddr.ip for conn in connections if conn.status == 'ESTABLISHED' and conn.raddr])
    total_unique_ips = len(unique_ips)

    # Load average
    num_cpus = psutil.cpu_count()
    load_avg = [avg / num_cpus for avg in os.getloadavg()]
    # Return the system information
    return {
        "cpu_percent": cpu_percent / num_cpus,
        "ram_used": ram_used,
        "ram_total": ram_total,
        "disk_used": disk_used,
        "disk_total": disk_total,
        "hiddify_used": hiddify_used,
        "bytes_sent": bytes_sent,
        "bytes_recv": bytes_recv,
        "bytes_sent_cumulative": bytes_sent_cumulative,
        "bytes_recv_cumulative": bytes_recv_cumulative,
        "net_sent_cumulative_GB": bytes_sent_cumulative / 1024**3,
        "net_total_cumulative_GB": (bytes_sent_cumulative + bytes_recv_cumulative) / 1024**3,
        "total_connections": total_connections,
        "total_unique_ips": total_unique_ips,
        "load_avg_1min": load_avg[0],
        "load_avg_5min": load_avg[1],
        "load_avg_15min": load_avg[2],
        'num_cpus': num_cpus
    }
