package main

import (
    "io/ioutil"
    "log"
    "fmt"
    "net"
    "net/http"
    "os/exec"
    "runtime"
    "errors"
)

func getLocalIP() (string, error) {
    addrs, err := net.InterfaceAddrs()
    if err != nil {
        return "", err
    }

    for _, addr := range addrs {
        if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
            if ipnet.IP.To4() != nil {
                return ipnet.IP.String(), nil
            }
        }
    }

    return "", errors.New("cannot find local IP address")
}

func ipHandler(w http.ResponseWriter, r *http.Request) {
    ip, err := getLocalIP()
    if err != nil {
        http.Error(w, "Error getting IP address: "+err.Error(), http.StatusInternalServerError)
        return
    }

    fmt.Fprintf(w, "%s", ip)
}

func rebootSystem() error {
    var cmd *exec.Cmd

    switch runtime.GOOS {
    case "linux":
        cmd = exec.Command("sudo", "reboot")
    case "windows":
        cmd = exec.Command("shutdown", "/r", "/t", "0")
    default:
        return errors.New("unsupported platform")
    }

    return cmd.Start()
}

func rebootHandler(w http.ResponseWriter, r *http.Request) {
    err := rebootSystem()
    if err != nil {
         http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Reboot initiated"))
}

func commandHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != "POST" {
        w.WriteHeader(http.StatusMethodNotAllowed)
        return
    }

    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        log.Printf("Error reading request body: %s", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
    defer r.Body.Close()

    command := string(body)
    var cmd *exec.Cmd
    if runtime.GOOS == "windows" {
        cmd = exec.Command("cmd.exe", "/C", command)
    } else {
        cmd = exec.Command("/bin/bash", "-c", command)
    }
    output, err := cmd.CombinedOutput()
    if err != nil {
        log.Printf("Error executing command: %s, Error: %s", command, err)
        w.WriteHeader(http.StatusInternalServerError)
        w.Write([]byte(err.Error()))
        return
    }

    w.WriteHeader(http.StatusOK)
    w.Write(output)
}

func osHandler(w http.ResponseWriter, r *http.Request) {
    osInfo := runtime.GOOS
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Operating System: " + osInfo))
}

func main() {
    http.HandleFunc("/reboot", rebootHandler)
    http.HandleFunc("/command", commandHandler)
    http.HandleFunc("/os", osHandler)
    http.HandleFunc("/ip", ipHandler)

    log.Fatal(http.ListenAndServe("0.0.0.0:99", nil))
}