#!/usr/bin/env bash

set -euo pipefail
umask 022

LOGFILE="/var/log/setup.log"
TINET_SOURCE="/mnt/c/tinet/tinet"
TINET_DEST="/usr/bin/tinet"

RESOLV_EXPECTED='nameserver 8.8.8.8
nameserver 1.1.1.1'

WSL_CONF_EXPECTED='[network]
hostname = UBUNTU
generateResolvConf = false
[boot]
systemd = true
command = systemctl start docker
[user]
default = root'

###############################################################################
# Logging
###############################################################################

log() {
    printf '%s\n' "$1" | tee -a "$LOGFILE"
}

section() {
    printf '\n========================================================\n' | tee -a "$LOGFILE"
    printf '%s\n' "$1" | tee -a "$LOGFILE"
    printf '========================================================\n\n' | tee -a "$LOGFILE"
}

run() {
    local desc="$1"
    shift

    log ">> $desc"
    "$@" >> "$LOGFILE" 2>&1
}

###############################################################################
# Utility Functions
###############################################################################

is_wsl() {
    grep -qi microsoft /proc/version 2>/dev/null
}

file_equals() {
    local file="$1"
    local content="$2"

    [ -f "$file" ] || return 1
    diff -u "$file" <(printf '%s\n' "$content") >/dev/null 2>&1
}

is_immutable() {
    lsattr "$1" 2>/dev/null | awk '{print $1}' | grep -q 'i'
}

write_file() {
    local file="$1"
    local content="$2"

    printf '%s\n' "$content" > "$file"
}

###############################################################################
# Step 1: resolv.conf
###############################################################################

configure_resolv() {
    section "[1/5] Configuring /etc/resolv.conf"

    local need_update=0

    if [ -L /etc/resolv.conf ]; then
        need_update=1
    fi

    if ! file_equals /etc/resolv.conf "$RESOLV_EXPECTED"; then
        need_update=1
    fi

    if ! is_immutable /etc/resolv.conf; then
        need_update=1
    fi

    if [ "$need_update" -eq 0 ]; then
        log "resolv.conf is already correct. Skipping."
        return
    fi

    if is_immutable /etc/resolv.conf; then
        run "Removing immutable flag" chattr -i /etc/resolv.conf
    fi

    run "Removing existing resolv.conf" rm -f /etc/resolv.conf

    log ">> Writing resolv.conf"
    write_file /etc/resolv.conf "$RESOLV_EXPECTED"

    run "Applying immutable flag" chattr +i /etc/resolv.conf

    log "resolv.conf configured."
}

###############################################################################
# Step 2: System Update
###############################################################################

update_system() {
    section "[2/5] Updating system (this may take some time)"

    run "Checking connectivity" ping -c 2 8.8.8.8

    run "apt-get update" apt-get update

    run "apt-get upgrade" \
        env DEBIAN_FRONTEND=noninteractive apt-get upgrade -y

    log "System update completed."
}

###############################################################################
# Step 3: Docker
###############################################################################

install_docker() {
    section "[3/5] Installing Docker (this may take some time)"

    if dpkg -s docker.io >/dev/null 2>&1; then
        log "docker.io already installed."
    else
        run "Installing docker.io" \
            env DEBIAN_FRONTEND=noninteractive apt-get install -y docker.io
    fi

    if ! systemctl is-enabled docker >/dev/null 2>&1; then
        run "Enabling docker" systemctl enable docker
    fi

    if ! systemctl is-active docker >/dev/null 2>&1; then
        run "Starting docker" systemctl start docker
    fi

    log "Docker ready."
}

###############################################################################
# Step 4: tinet
###############################################################################

install_tinet() {
    section "[4/5] Installing tinet"

    if [ ! -f "$TINET_SOURCE" ]; then
        echo "ERROR: $TINET_SOURCE not found" >&2
        exit 1
    fi

    run "Copying tinet" cp "$TINET_SOURCE" "$TINET_DEST"
    run "Setting executable" chmod +x "$TINET_DEST"

    log "tinet installed."
}

###############################################################################
# Step 5: wsl.conf
###############################################################################

configure_wsl_conf() {
    section "[5/5] Configuring /etc/wsl.conf"

    if file_equals /etc/wsl.conf "$WSL_CONF_EXPECTED"; then
        log "wsl.conf already correct."
        return
    fi

    log ">> Writing wsl.conf"
    write_file /etc/wsl.conf "$WSL_CONF_EXPECTED"

    log "wsl.conf configured."
}

###############################################################################
# Main
###############################################################################

main() {
    if [ "$(id -u)" -ne 0 ]; then
        echo "ERROR: This script must be run as root." >&2
        exit 1
    fi

    : > "$LOGFILE"

    section "Starting setup"

    if ! is_wsl; then
        log "WARNING: This environment does not appear to be WSL."
    fi

    configure_resolv
    update_system
    install_docker
    install_tinet
    configure_wsl_conf

    section "Setup completed — please restart this WSL instance"
}

main "$@"
