#!/bin/sh
# bee-tui: interactive text menu for debug LiveCD operations.

set -u

if ! command -v dialog >/dev/null 2>&1; then
    echo "ERROR: dialog is required but not installed"
    exit 1
fi

pause() {
    echo
    printf 'Press Enter to continue... '
    read -r _
}

header() {
    clear
    echo "=============================================="
    echo " bee TUI (debug)"
    echo "=============================================="
    echo
}

menu_choice() {
    title="$1"
    prompt="$2"
    shift 2
    dialog --clear --stdout --title "$title" --menu "$prompt" 20 90 12 "$@"
}

list_ifaces() {
    ip -o link show \
        | awk -F': ' '{print $2}' \
        | grep -v '^lo$' \
        | grep -vE '^(docker|virbr|veth|tun|tap|br-|bond|dummy)' \
        | sort
}

show_network_status() {
    header
    echo "Network interfaces"
    echo
    for iface in $(list_ifaces); do
        state=$(ip -o link show "$iface" | awk '{print $9}')
        ipv4=$(ip -o -4 addr show dev "$iface" | awk '{print $4}' | paste -sd ',')
        [ -n "$ipv4" ] || ipv4="(no IPv4)"
        echo "- $iface: state=$state ip=$ipv4"
    done
    echo
    ip route | sed 's/^/  route: /'
    pause
}

choose_interface() {
    ifaces="$(list_ifaces)"
    if [ -z "$ifaces" ]; then
        echo "No physical interfaces found"
        return 1
    fi

    set --
    for iface in $ifaces; do
        set -- "$@" "$iface" "$iface"
    done
    iface=$(menu_choice "Network" "Select interface" "$@") || return 1

    CHOSEN_IFACE="$iface"
    return 0
}

network_dhcp_one() {
    header
    echo "DHCP on one interface"
    echo
    choose_interface || { pause; return; }

    iface="$CHOSEN_IFACE"
    echo
    echo "Starting DHCP on $iface..."
    ip link set "$iface" up 2>/dev/null || true
    udhcpc -i "$iface" -t 5 -T 3
    pause
}

network_dhcp_all() {
    header
    echo "Restarting DHCP on all physical interfaces..."
    echo
    /usr/local/bin/bee-net-restart
    pause
}

network_static_one() {
    header
    echo "Static IPv4 setup"
    echo
    choose_interface || { pause; return; }

    iface="$CHOSEN_IFACE"
    echo
    printf 'IPv4 address (example 192.168.1.10): '
    read -r ip
    if [ -z "$ip" ]; then
        echo "IP address is required"
        pause
        return
    fi

    # derive default gateway: first three octets of IP + .1
    ip_base="$(echo "$ip" | cut -d. -f1-3)"
    default_gw="${ip_base}.1"

    printf 'Netmask [24]: '
    read -r mask
    [ -z "$mask" ] && mask="24"
    prefix=$(mask_to_prefix "$mask")
    if [ -z "$prefix" ]; then
        echo "Invalid netmask: $mask"
        pause
        return
    fi
    cidr="$ip/$prefix"

    printf 'Default gateway [%s]: ' "$default_gw"
    read -r gw
    [ -z "$gw" ] && gw="$default_gw"

    printf 'DNS servers [77.88.8.8 77.88.8.1 1.1.1.1 8.8.8.8]: '
    read -r dns

    ip link set "$iface" up 2>/dev/null || true
    ip addr flush dev "$iface"
    if ! ip addr add "$cidr" dev "$iface"; then
        echo "Failed to set IP"
        pause
        return
    fi

    if [ -n "$gw" ]; then
        ip route del default >/dev/null 2>&1 || true
        ip route add default via "$gw" dev "$iface"
    fi

    if [ -z "$dns" ]; then
        dns="77.88.8.8 77.88.8.1 1.1.1.1 8.8.8.8"
    fi
    : > /etc/resolv.conf
    for d in $dns; do
        printf 'nameserver %s\n' "$d" >> /etc/resolv.conf
    done

    echo
    echo "Static config applied to $iface"
    pause
}

mask_to_prefix() {
    mask="$(echo "$1" | tr -d '[:space:]')"
    case "$mask" in
        0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32)
            echo "$mask"
            return 0
            ;;
    esac
    case "$mask" in
        255.0.0.0) echo 8 ;;
        255.128.0.0) echo 9 ;;
        255.192.0.0) echo 10 ;;
        255.224.0.0) echo 11 ;;
        255.240.0.0) echo 12 ;;
        255.248.0.0) echo 13 ;;
        255.252.0.0) echo 14 ;;
        255.254.0.0) echo 15 ;;
        255.255.0.0) echo 16 ;;
        255.255.128.0) echo 17 ;;
        255.255.192.0) echo 18 ;;
        255.255.224.0) echo 19 ;;
        255.255.240.0) echo 20 ;;
        255.255.248.0) echo 21 ;;
        255.255.252.0) echo 22 ;;
        255.255.254.0) echo 23 ;;
        255.255.255.0) echo 24 ;;
        255.255.255.128) echo 25 ;;
        255.255.255.192) echo 26 ;;
        255.255.255.224) echo 27 ;;
        255.255.255.240) echo 28 ;;
        255.255.255.248) echo 29 ;;
        255.255.255.252) echo 30 ;;
        255.255.255.254) echo 31 ;;
        255.255.255.255) echo 32 ;;
        *) return 1 ;;
    esac
}

network_menu() {
    while true; do
        choice=$(menu_choice "Network" "Select action" \
            "1" "Show network status" \
            "2" "DHCP on all interfaces" \
            "3" "DHCP on one interface" \
            "4" "Set static IPv4 on one interface" \
            "5" "Back") || return

        case "$choice" in
            1) show_network_status ;;
            2) network_dhcp_all ;;
            3) network_dhcp_one ;;
            4) network_static_one ;;
            5) return ;;
            *) echo "Invalid choice"; pause ;;
        esac
    done
}

bee_services_list() {
    for path in /etc/init.d/bee-*; do
        [ -e "$path" ] || continue
        basename "$path"
    done
}

services_status_all() {
    header
    echo "bee service status"
    echo
    for svc in $(bee_services_list); do
        if rc-service "$svc" status >/dev/null 2>&1; then
            echo "- $svc: running"
        else
            echo "- $svc: stopped"
        fi
    done
    pause
}

choose_service() {
    svcs="$(bee_services_list)"
    if [ -z "$svcs" ]; then
        echo "No bee-* services found"
        return 1
    fi

    set --
    for svc in $svcs; do
        set -- "$@" "$svc" "$svc"
    done
    svc=$(menu_choice "bee Services" "Select service" "$@") || return 1

    CHOSEN_SERVICE="$svc"
    return 0
}

service_action_menu() {
    header
    echo "Service action"
    echo
    choose_service || { pause; return; }
    svc="$CHOSEN_SERVICE"

    act=$(menu_choice "Service: $svc" "Select action" \
        "1" "status" \
        "2" "restart" \
        "3" "start" \
        "4" "stop" \
        "5" "toggle start/stop" \
        "6" "Back") || return

    case "$act" in
        1) rc-service "$svc" status || true ;;
        2) rc-service "$svc" restart || true ;;
        3) rc-service "$svc" start || true ;;
        4) rc-service "$svc" stop || true ;;
        5)
            if rc-service "$svc" status >/dev/null 2>&1; then
                rc-service "$svc" stop || true
            else
                rc-service "$svc" start || true
            fi
            ;;
        6) return ;;
        *) echo "Invalid action" ;;
    esac
    pause
}

services_menu() {
    while true; do
        choice=$(menu_choice "bee Services" "Select action" \
            "1" "Status of all bee-* services" \
            "2" "Manage one service (status/restart/start/stop/toggle)" \
            "3" "Back") || return

        case "$choice" in
            1) services_status_all ;;
            2) service_action_menu ;;
            3) return ;;
            *) echo "Invalid choice"; pause ;;
        esac
    done
}

confirm_phrase() {
    phrase="$1"
    prompt="$2"
    echo
    printf '%s (%s): ' "$prompt" "$phrase"
    read -r value
    [ "$value" = "$phrase" ]
}

shutdown_menu() {
    while true; do
        choice=$(menu_choice "Shutdown/Reboot Tests" "Select action" \
            "1" "Reboot now" \
            "2" "Power off now" \
            "3" "Schedule poweroff in 60s" \
            "4" "Cancel scheduled shutdown" \
            "5" "IPMI chassis power status" \
            "6" "IPMI chassis power soft" \
            "7" "IPMI chassis power cycle" \
            "8" "Back") || return

        case "$choice" in
            1)
                confirm_phrase "REBOOT" "Type confirmation" || { echo "Canceled"; pause; continue; }
                reboot
                ;;
            2)
                confirm_phrase "POWEROFF" "Type confirmation" || { echo "Canceled"; pause; continue; }
                poweroff
                ;;
            3)
                confirm_phrase "SCHEDULE" "Type confirmation" || { echo "Canceled"; pause; continue; }
                shutdown -P +1 "bee test: scheduled poweroff in 60 seconds"
                echo "Scheduled"
                pause
                ;;
            4)
                shutdown -c || true
                echo "Canceled (if any schedule existed)"
                pause
                ;;
            5)
                ipmitool chassis power status || echo "ipmitool power status failed"
                pause
                ;;
            6)
                confirm_phrase "IPMI-SOFT" "Type confirmation" || { echo "Canceled"; pause; continue; }
                ipmitool chassis power soft || echo "ipmitool soft power failed"
                pause
                ;;
            7)
                confirm_phrase "IPMI-CYCLE" "Type confirmation" || { echo "Canceled"; pause; continue; }
                ipmitool chassis power cycle || echo "ipmitool power cycle failed"
                pause
                ;;
            8)
                return
                ;;
            *)
                echo "Invalid choice"
                pause
                ;;
        esac
    done
}

gpu_burn_10m() {
    header
    echo "GPU Burn (10 minutes)"
    echo
    if ! command -v gpu_burn >/dev/null 2>&1; then
        echo "gpu_burn binary not found in PATH"
        echo "Expected command: gpu_burn"
        pause
        return
    fi
    if ! command -v nvidia-smi >/dev/null 2>&1 || ! nvidia-smi -L >/dev/null 2>&1; then
        echo "NVIDIA driver/GPU not ready (nvidia-smi failed)"
        pause
        return
    fi

    confirm_phrase "GPU-BURN" "Type confirmation to start benchmark" || { echo "Canceled"; pause; return; }
    echo "Running: gpu_burn 600"
    echo "Log: /var/log/bee-gpuburn.log"
    gpu_burn 600 2>&1 | tee /var/log/bee-gpuburn.log
    echo
    echo "GPU Burn finished"
    pause
}

gpu_benchmarks_menu() {
    while true; do
        choice=$(menu_choice "Benchmarks -> GPU" "Select action" \
            "1" "GPU Burn (10 minutes)" \
            "2" "Back") || return

        case "$choice" in
            1) gpu_burn_10m ;;
            2) return ;;
            *) echo "Invalid choice"; pause ;;
        esac
    done
}

benchmarks_menu() {
    while true; do
        choice=$(menu_choice "Benchmarks" "Select category" \
            "1" "GPU" \
            "2" "Back") || return

        case "$choice" in
            1) gpu_benchmarks_menu ;;
            2) return ;;
            *) echo "Invalid choice"; pause ;;
        esac
    done
}

run_cmd_log() {
    label="$1"
    cmd="$2"
    log_file="$3"

    {
        echo "=== $label ==="
        echo "time: $(date -u '+%Y-%m-%dT%H:%M:%SZ')"
        echo "cmd:  $cmd"
        echo
        sh -c "$cmd"
    } >"$log_file" 2>&1
    return $?
}

run_gpu_nvidia_acceptance_test() {
    header
    echo "System acceptance tests -> GPU NVIDIA"
    echo
    confirm_phrase "SAT-GPU" "Type confirmation to start tests" || { echo "Canceled"; pause; return; }

    ts="$(date -u '+%Y%m%d-%H%M%S')"
    base_dir="/var/log/bee-sat"
    run_dir="$base_dir/gpu-nvidia-$ts"
    archive="$base_dir/gpu-nvidia-$ts.tar.gz"
    mkdir -p "$run_dir"

    summary="$run_dir/summary.txt"
    : >"$summary"

    echo "Running acceptance commands..."
    echo "Logs directory: $run_dir"
    echo "Archive target: $archive"
    echo

    c1="nvidia-smi -q"
    c2="dmidecode -t baseboard"
    c3="dmidecode -t system"
    c4="nvidia-bug-report.sh --output $run_dir/nvidia-bug-report.log"

    run_cmd_log "nvidia_smi_q" "$c1" "$run_dir/01-nvidia-smi-q.log"; rc1=$?
    run_cmd_log "dmidecode_baseboard" "$c2" "$run_dir/02-dmidecode-baseboard.log"; rc2=$?
    run_cmd_log "dmidecode_system" "$c3" "$run_dir/03-dmidecode-system.log"; rc3=$?
    run_cmd_log "nvidia_bug_report" "$c4" "$run_dir/04-nvidia-bug-report.log"; rc4=$?

    {
        echo "run_at_utc=$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
        echo "cmd_nvidia_smi_q_rc=$rc1"
        echo "cmd_dmidecode_baseboard_rc=$rc2"
        echo "cmd_dmidecode_system_rc=$rc3"
        echo "cmd_nvidia_bug_report_rc=$rc4"
    } >>"$summary"

    tar -czf "$archive" -C "$base_dir" "gpu-nvidia-$ts"
    tar_rc=$?
    echo "archive_rc=$tar_rc" >>"$summary"

    echo
    echo "Done."
    echo "- Logs:    $run_dir"
    echo "- Archive: $archive (rc=$tar_rc)"
    pause
}

gpu_nvidia_sat_menu() {
    while true; do
        choice=$(menu_choice "System acceptance tests -> GPU NVIDIA" "Select action" \
            "1" "Run command pack" \
            "2" "Back") || return

        case "$choice" in
            1) run_gpu_nvidia_acceptance_test ;;
            2) return ;;
            *) echo "Invalid choice"; pause ;;
        esac
    done
}

system_acceptance_tests_menu() {
    while true; do
        choice=$(menu_choice "System acceptance tests" "Select category" \
            "1" "GPU NVIDIA" \
            "2" "Back") || return

        case "$choice" in
            1) gpu_nvidia_sat_menu ;;
            2) return ;;
            *) echo "Invalid choice"; pause ;;
        esac
    done
}

run_audit_now() {
    header
    echo "Run audit now"
    echo
    /usr/local/bin/audit --output stdout > /var/log/bee-audit.json 2>/var/log/bee-audit.log
    rc=$?
    if [ "$rc" -eq 0 ]; then
        echo "Audit completed successfully"
    else
        echo "Audit finished with errors (rc=$rc)"
    fi
    echo "Logs: /var/log/bee-audit.log, /var/log/bee-audit.json"
    pause
}

check_required_tools() {
    header
    echo "Required tools check"
    echo
    for tool in dmidecode smartctl nvme ipmitool lspci audit nvidia-smi gpu_burn dialog; do
        if command -v "$tool" >/dev/null 2>&1; then
            echo "- $tool: OK ($(command -v "$tool"))"
        else
            echo "- $tool: MISSING"
        fi
    done
    pause
}

main_menu() {
    while true; do
        choice=$(menu_choice "Bee TUI (debug)" "Select action" \
            "1" "Network setup" \
            "2" "bee service management" \
            "3" "Shutdown/reboot tests" \
            "4" "Benchmarks" \
            "5" "System acceptance tests" \
            "6" "Run audit now" \
            "7" "Check required tools" \
            "8" "Show last audit log tail" \
            "9" "Exit to console") || exit 0

        case "$choice" in
            1) network_menu ;;
            2) services_menu ;;
            3) shutdown_menu ;;
            4) benchmarks_menu ;;
            5) system_acceptance_tests_menu ;;
            6) run_audit_now ;;
            7) check_required_tools ;;
            8)
                header
                tail -n 40 /var/log/bee-audit.log 2>/dev/null || echo "No /var/log/bee-audit.log"
                echo
                tail -n 20 /var/log/bee-audit.json 2>/dev/null || true
                pause
                ;;
            9) exit 0 ;;
            *) echo "Invalid choice"; pause ;;
        esac
    done
}

main_menu
