#!/usr/bin/env bash


set -euo pipefail

# -----------------
# Install display tools based on if display is attached
# -----------------

if [[ -n "${DISPLAY:-}" ]]; then
  if [[ ! -x "$(command -v zenity )" ]]; then
    sudo apt-get update
    sudo apt-get install zenity
  fi
else
  if [[ ! -x "$(command -v dialog)" ]]; then
    sudo apt-get update
    sudo apt-get install dialog
  fi
fi

USE_GUI=0
if [[ -n "${DISPLAY:-}" && -x "$(command -v zenity)" ]]; then
    USE_GUI=1
fi

TEMPFILE=""

cleanup() {
  [[ -n "$TEMPFILE" && -f "$TEMPFILE" ]] && rm -f "$TEMPFILE"
  # [[ "$USE_GUI" -eq 0 && -t 1 ]] && clear
}
trap cleanup EXIT

DEVICE_ID=""
RVC_USER="irf"
RVC_PASS=$( openssl passwd -6 "Fenetuggya001" )
RVC_URL="https://usetup.rvc.digital/setup"
RVC_FOLDER="/home/${RVC_USER}/rvc"
ENV_FILE="${RVC_FOLDER}/.env"


show_error() {
  local msg="$1"
  if [[ "${USE_GUI}" -eq 1 ]]; then
    zenity --error --title="Installation error" --text="$msg"
  elif [[ -x "$(command -v dialog)" ]]; then
    dialog --infobox "$msg" 10 60
  else
    echo "ERROR: $msg"
  fi

  exit 1
}

ensure_entry() {
    local file="$1"
    local key="$2"
    local default="${3:-}"

    # Create file if it doesn't exist
    [ -f "$file" ] || touch "$file"

    # Check if key exists (ignoring comments and spaces)
    if ! grep -qE "^\s*${key}\s*=" "$file"; then
        echo "${key}=${default}" >> "$file"
        echo "Added ${key}=${default} to $file"
    else
        # Optional: update empty value with default
        sed -i "s|^\s*${key}\s*=.*|${key}=${default}|" "$file"
    fi
}


get_device_id_from_user() {
  local __id_var="$1"
  local device_id

  if [[ "$USE_GUI" -eq 1 ]]; then
    DEVICE_DATA=$(zenity --entry \
      --title="Enter device ID" \
      --text="Please enter device ID:" \
      --width=300)

    [[ $? -ne 0 ]] && return 1

    device_id="${DEVICE_DATA}"
  else
    TMPFILE=$(mktemp)
    dialog \
      --inputbox "Please enter device id:" \
      10 40 \
      2>"$TMPFILE" 

    [[ $? -ne 0 ]] && rm -f "$TMPFILE" && return 1

    device_id=$(cat "$TMPFILE")
  fi

  printf -v "$__id_var" "%s" "$device_id"
  return 0
}

hide_function() {
  local title="$2"
  local begin_percent="${3:-10}"
  if [[ $USE_GUI -eq 1 ]]; then
    (
    echo "$begin_percent"; sleep 0.2
    if ! $1 > "/tmp/$title.log" 2>&1; then
      echo "100"
      sleep 0.1
      show_error "Command $1 failed. See /tmp/$title.log"
    fi
    echo "100"
    ) | zenity \
      --progress \
      --title="$title" \
      --text="Please wait ..." \
      --percentage=0 \
      --auto-close \
      --width=400
  else
    (
    echo "$begin_percent"; sleep 0.2
    if ! $1 > "/tmp/$title.log" 2>&1; then
      echo "100"
      sleep 0.1
      show_error "Command $1 failed. See /tmp/$title.log"
    fi
      
    echo "100"
    ) | dialog --gauge "$title ..." 10 70 0
  fi
}

# --------
# Create user
# --------


user_add_user() {
  sudo useradd \
   -m \
   -s /bin/bash \
   -p "$RVC_PASS" \
   -G sudo,video,adm \
   "$RVC_USER"
  USER_ADDED=$?
  echo "USER ADDED $USER_ADDED"
  if [[ $USER_ADDED -eq 0 ]]; then
    echo

    TMPFILE=$(mktemp)
    echo "$RVC_USER ALL=(ALL) NOPASSWD:ALL" > "$TMPFILE"

    sudo visudo -cf "$TMPFILE" || {
        echo "Invalid sudoers syntax"
        rm -f "$TMPFILE"
        exit 1
    }

    sudo mv "$TMPFILE" /etc/sudoers.d/$RVC_USER
    sudo chmod 0440 /etc/sudoers.d/$RVC_USER

  elif [[ $USER_ADDED -eq 9 ]]; then
    echo
  else
    show_error "Failed to add user"
  fi

}

# --------
# Install necessary apps
# --------

install_dependencies() {
  sudo apt update
  sudo apt-get install --no-install-recommends -y \
    micro \
    python3-requests \
    unzip \
    libssl-dev \
    kitty-terminfo \
    pipx \
    libgl1 \
    libglib2.0-0 \
    build-essential \
    git \
    openssh-server

  sudo systemctl enable ssh

  (sudo crontab -l 2>/dev/null; echo "0 6,22 * * * /sbin/shutdown -r now") | sudo crontab -
}


install_tailscale() {
  curl -fsSL https://tailscale.com/install.sh | sh && sudo tailscale up --auth-key=tskey-auth-kCcnU8YRpC11CNTRL-wCW8Mfqt1jDmcm489uwpiD4PmmmASsAg --hostname "irfcam${DEVICE_ID}"
}



# --------
# Install deadsnakes python PPA
# --------

install_deadsnakes() {
  sudo apt update
  sudo add-apt-repository ppa:deadsnakes/ppa
}
# --------
# Install python 3.12
# --------

install_python() {
  sudo apt-get install --no-install-recommends -y \
  python3.12 \
  python3.12-dev \
  python3.12-venv
}  

# --------
# Create venv
# --------

user_create_venv() {
  sudo -u "${RVC_USER}" bash <<EOF
    echo "Switched user: $(id)"
    cd ~
    echo "Swiched path: $(pwd)"

    python3.12 -m venv rvc --copies
    cd rvc

    curl -fsSL "$RVC_URL/files/rvc_lib-0.10.10-py3-none-any.whl" -o ./rvc_lib-0.10.10-py3-none-any.whl

    bin/pip3 install \
      --index-url https://download.pytorch.org/whl/cpu \
      "torch==2.4.0" \
       torchvision 

    bin/pip3 install \
      --extra-index-url="https://rvc:longirfpassword@pip.rvc.digital/simple" \
      "./rvc_lib-0.10.10-py3-none-any.whl[detection]"

EOF


}


# --------
# Install systemd script
# --------

user_create_service() {
  sudo -u "${RVC_USER}" RVC_USER="${RVC_USER}" bash <<'EOF'
  cd ~

  sudo loginctl enable-linger "$RVC_USER"
  mkdir -p ~/.config/systemd/user/

  cat << EOP > /home/$RVC_USER/.config/systemd/user/rvcdigital.service
[Unit]
Description=RVC Digital Camera Service
After=network.target

[Service]
Type=simple
Environment=PYTHONBUFFERED=1
EnvironmentFile=%h/rvc/.env
WorkingDirectory=%h/rvc
ExecStart=%h/rvc/bin/python3 -m src
Restart=on-failure
RestartSec=30

[Install]
WantedBy=default.target
EOP

EOF


}


# --------
# Get and set device ID
# --------

set_device_id() {
  sudo -u "${RVC_USER}" ENV_FILE="$ENV_FILE" DEVICE_ID="$DEVICE_ID" RVC_FOLDER="$RVC_FOLDER" bash <<'EOF'

  ensure_entry() {
      local file="$1"
      local key="$2"
      local default="${3:-}"

      # Create file if it doesn't exist
      [ -f "$file" ] || touch "$file"

      # Check if key exists (ignoring comments and spaces)
      if ! grep -qE "^\s*${key}\s*=" "$file"; then
          echo "${key}=\"${default}\"" >> "$file"
          # echo "Added ${key}=${default} to $file"
      else
          # Optional: update empty value with default
          sed -i "s|^\s*${key}\s*=.*|${key}=${default}|" "$file"
      fi
  }
    ensure_entry "${ENV_FILE}" "RVC_DEVICE_ID" "${DEVICE_ID}"
    ensure_entry "${ENV_FILE}" "RVC_CAMERA__SOURCE" "/dev/video0"
    ensure_entry "${ENV_FILE}" "RVC_DEVICE__PERSIST__URI" "sqlite:///${RVC_FOLDER}/db.sqlite"
EOF
}
  
# ----------
# Move models if downloaded
# ----------

errs=0

wait_for_job() {
    local pid="$1"
    local name="$2"

    if ! wait "$pid"; then
        echo "Job '$name' (PID $pid) failed with exit $?"
        errs=$((errs+1))
    fi
}


set_up_app() {
sudo -u "${RVC_USER}" RVC_FOLDER="${RVC_FOLDER}" RVC_USER="${RVC_USER}"  bash <<'EOF'
  mkdir -p "${RVC_FOLDER}/models"
  sudo mv /tmp/rvc_prod_other_0019.7z "${RVC_FOLDER}/models/"
  sudo mv /tmp/rvc_prod_face_0008.7z "${RVC_FOLDER}/models/"
  sudo mv /tmp/rvc_prod_face_0010.7z "${RVC_FOLDER}/models/"
  sudo mv /tmp/rvc_prod_age_0002.7z "${RVC_FOLDER}/models/"
  tar -xavf /tmp/certs.tar.gz -C "${RVC_FOLDER}/"
  sudo chown -R "${RVC_USER}:${RVC_USER}" "${RVC_FOLDER}/certs"
EOF

sudo -u "${RVC_USER}" ENV_FILE="$ENV_FILE" RVC_FOLDER="$RVC_FOLDER" bash <<'EOF'

ensure_entry() {
    local file="$1"
    local key="$2"
    local default="${3:-}"

    # Create file if it doesn't exist
    [ -f "$file" ] || touch "$file"

    # Check if key exists (ignoring comments and spaces)
    if ! grep -qE "^\s*${key}\s*=" "$file"; then
        echo "${key}=${default}" >> "$file"
        # echo "Added ${key}=${default} to $file"
    else
        # Optional: update empty value with default
        sed -i "s|^\s*${key}\s*=.*|${key}=${default}|" "$file"
    fi
}
  ensure_entry "${ENV_FILE}" "RVC_MODEL_DIR" "${RVC_FOLDER}/models/"
EOF
}

set_up_utils() {
sudo -u "${RVC_USER}" RVC_URL="$RVC_URL" ENV_FILE="$ENV_FILE" RVC_FOLDER="$RVC_FOLDER" DEVICE_ID="$DEVICE_ID" bash <<'EOF'
    cd ~
    curl -fsSL "$RVC_URL/files/hl" -o hl
    chmod a+x ./hl
    sudo mv ./hl /usr/local/bin
    rm -rf ./hl

    sudo chmod a+x /tmp/agent
    sudo mv /tmp/agent /usr/local/bin/

  cat << EOP > rvc-agent.service
[Unit]
Description=Device Agent Service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple

# --- Binary ---
ExecStart=/usr/local/bin/agent

# --- Environment variables ---
Environment="RVC_DEVICE_ID=${DEVICE_ID}"

# --- Restart policy ---
Restart=on-failure
RestartSec=20

# --- Logging ---
StandardOutput=journal
StandardError=journal
SyslogIdentifier=rvc-agent

# --- Resource safety (optional but useful for fleets) ---
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOP

    sudo mv rvc-agent.service /etc/systemd/system/rvc-agent.service
    sudo systemctl daemon-reload
    sudo systemctl enable --now rvc-agent.service
EOF
}

check_service_running() {
  # 1) Check if the camera device exists
  if [[ ! -e /dev/video0 ]]; then
    echo "camera_missing"
    return 1
  fi

  # 2) Check service state as the RVC_USER
  if ! sudo systemctl --machine="${RVC_USER}"@.host --user is-enabled --quiet rvcdigital.service; then
    echo "service_disabled"
    return 2
  fi

  if ! sudo systemctl --machine="${RVC_USER}"@.host --user is-active --quiet rvcdigital.service; then
    echo "service_inactive"
    return 3
  fi

  echo "ok"
  return 0
}



# -----------------------------------------------------------------------------
# Install
# -----------------------------------------------------------------------------

if ! get_device_id_from_user DEVICE_ID; then
  show_error "Failed to get id from user"
fi

if ! user_add_user; then
  echo "Failed to add user"
fi

curl -fsSL --tlsv1.2 --retry 5 --retry-delay 3 "$RVC_URL/files/rvc_prod_other_0019.7z" -o /tmp/rvc_prod_other_0019.7z > "/tmp/DWNDL1.log" 2>&1 &
DWNDL1=$!
curl -fsSL --tlsv1.2 --retry 5 --retry-delay 3 "$RVC_URL/files/rvc_prod_face_0008.7z" -o /tmp/rvc_prod_face_0008.7z > "/tmp/DWNDL2.log" 2>&1 &
DWNDL2=$!
curl -fsSL --tlsv1.2 --retry 5 --retry-delay 3 "$RVC_URL/files/rvc_prod_face_0010.7z" -o /tmp/rvc_prod_face_0010.7z > "/tmp/DWNDL3.log" 2>&1 &
DWNDL3=$!
curl -fsSL --tlsv1.2 --retry 5 --retry-delay 3 "$RVC_URL/files/rvc_prod_age_0002.7z" -o /tmp/rvc_prod_age_0002.7z > "/tmp/DWNDL4.log" 2>&1 &
DWNDL4=$!
curl -fsSL --tlsv1.2 --retry 5 --retry-delay 3 "$RVC_URL/files/certs.tar.gz" -o /tmp/certs.tar.gz > "/tmp/DWNDL5.log" 2>&1 &
DWNDL5=$!
curl -fsSL --tlsv1.2 --retry 5 --retry-delay 3 "$RVC_URL/files/agent" -o /tmp/agent > "/tmp/DWNDL6.log" 2>&1 &
DWNDL6=$!


hide_function install_dependencies "Install dependencies" "10"
# hide_function install_tailscale "Install tailscale" "15"
hide_function install_deadsnakes "Install PPA" "20"
hide_function install_python "Install python" "30"
# if ! hide_function user_create_venv "Creating environment" "50"; then
#   show_error "Failed to create environment"
# fi
hide_function user_create_service "Creating service" "90"
hide_function set_device_id "Setting device id" "91"

# wait_for_job "$DWNDL1" "download1"
# wait_for_job "$DWNDL2" "download2"
# wait_for_job "$DWNDL3" "download3"
# wait_for_job "$DWNDL4" "download4"
# wait_for_job "$DWNDL5" "download5"
# wait_for_job "$DWNDL6" "download6"

# if [[ $errs -gt 0 ]]; then
#     echo "Some background tasks failed ($errs total)"
#     exit 1
# fi

hide_function set_up_app "App setup" "93"
hide_function set_up_utils "Setting up utilities" 95

sudo systemctl --machine="${RVC_USER}"@.host --user daemon-reload
sudo systemctl --machine="${RVC_USER}"@.host --user enable --now rvcdigital.service

if [[ "$USE_GUI" -eq 1 ]]; then
  zenity --info --text="Setup complete"
else
  dialog --infobox "Setup complete" 10 40
fi
sleep 50

set +e 
output=$(check_service_running)
status=$?
set -e
if [[ $status -eq 0 ]]; then
  if [[ "$USE_GUI" -eq 1 ]]; then
    zenity --info --text="Service is running"
  else
    dialog --title="Check" --infobox "Service is running" 10 40
  fi
  sleep 10
else
  show_error "Problem: $status ($output)"
fi
