#!/usr/bin/env bash
set -u

APP_NAME="FileSV Terminal"
VERSION="1.1.0"
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/filesv"
CONFIG_FILE="$CONFIG_DIR/config"
BASE_URL="https://filesv.vnstech.cloud"
PROXY_URL=""
DOWNLOAD_DIR="$HOME/Downloads"
CURRENT_PATH="/"

if [ -t 1 ]; then
  RESET='\033[0m'; BOLD='\033[1m'; DIM='\033[2m'
  CYAN='\033[36m'; GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; BLUE='\033[34m'
else
  RESET=''; BOLD=''; DIM=''; CYAN=''; GREEN=''; YELLOW=''; RED=''; BLUE=''
fi

say() { printf '%b\n' "$*"; }
pause() { printf '\n%b' "${DIM}Press Enter to continue...${RESET}"; read -r _unused; }

header() {
  clear 2>/dev/null || printf '\033c'
  say "${CYAN}${BOLD}+----------------------------------------------------------+${RESET}"
  say "${CYAN}${BOLD}|                    FILESV TERMINAL                       |${RESET}"
  say "${CYAN}${BOLD}+----------------------------------------------------------+${RESET}"
  say "${DIM}  Remote: ${BASE_URL}${RESET}"
  say "${DIM}  Local : ${DOWNLOAD_DIR}${RESET}"
  if [ -n "$PROXY_URL" ]; then say "${DIM}  Proxy : ${PROXY_URL}${RESET}"; fi
  printf '\n'
}

save_config() {
  mkdir -p "$CONFIG_DIR"
  umask 077
  {
    printf 'BASE_URL=%s\n' "$BASE_URL"
    printf 'PROXY_URL=%s\n' "$PROXY_URL"
    printf 'DOWNLOAD_DIR=%s\n' "$DOWNLOAD_DIR"
  } > "$CONFIG_FILE"
}

read_config_value() {
  key="$1"
  [ -f "$CONFIG_FILE" ] || return 0
  sed -n "s/^${key}=//p" "$CONFIG_FILE" | tail -n 1
}

load_config() {
  value="$(read_config_value BASE_URL)"; [ -n "$value" ] && BASE_URL="$value"
  value="$(read_config_value PROXY_URL)"; [ -n "$value" ] && PROXY_URL="$value"
  value="$(read_config_value DOWNLOAD_DIR)"; [ -n "$value" ] && DOWNLOAD_DIR="$value"
}

curl_run() {
  if [ -n "$PROXY_URL" ]; then
    curl --proxy "$PROXY_URL" "$@"
  else
    curl "$@"
  fi
}

is_snap_curl() {
  case "$(command -v curl 2>/dev/null)" in
    /snap/*) return 0 ;;
    *) return 1 ;;
  esac
}

expand_home_path() {
  case "$1" in
    "~") printf '%s' "$HOME" ;;
    "~/"*) printf '%s/%s' "$HOME" "${1#~/}" ;;
    *) printf '%s' "$1" ;;
  esac
}

ensure_download_dir() {
  if ! mkdir -p -- "$DOWNLOAD_DIR" 2>/dev/null; then
    say "${RED}Cannot create download folder:${RESET} ${DOWNLOAD_DIR}"
    say "${DIM}Choose another folder in Settings or check its permissions.${RESET}"
    return 1
  fi

  write_test="${DOWNLOAD_DIR}/.filesv-write-test.$$"
  if ! : > "$write_test" 2>/dev/null; then
    say "${RED}Download folder is not writable:${RESET} ${DOWNLOAD_DIR}"
    say "${DIM}Choose another folder in Settings or check its permissions.${RESET}"
    return 1
  fi
  rm -f -- "$write_test"
}

download_to_file() {
  url="$1"
  output="$2"

  if is_snap_curl && command -v wget >/dev/null 2>&1; then
    say "${YELLOW}Snap curl detected. Using wget to access the selected folder.${RESET}"
    if [ -n "$PROXY_URL" ]; then
      https_proxy="$PROXY_URL" http_proxy="$PROXY_URL" wget --progress=bar:force:noscroll -O "$output" "$url"
    else
      wget --progress=bar:force:noscroll -O "$output" "$url"
    fi
    return
  fi

  curl_run -fL --progress-bar "$url" -o "$output"
}

url_decode() {
  value="${1//+/ }"
  printf '%b' "${value//%/\\x}"
}

fetch_listing() {
  curl_run -fsSL --connect-timeout 10 --max-time 30 "${BASE_URL}${CURRENT_PATH}"
}

browse() {
  while :; do
    header
    say "${BLUE}${BOLD}Browse: ${CURRENT_PATH}${RESET}"
    printf '\n'

    html="$(fetch_listing 2>/dev/null)" || {
      say "${RED}Cannot load file list. Check the connection or proxy setting.${RESET}"
      pause
      return
    }

    hrefs=()
    labels=()
    while IFS= read -r href; do
      [ -n "$href" ] || continue
      [ "$href" = "../" ] && continue
      hrefs+=("$href")
      decoded="$(url_decode "$href")"
      if [[ "$href" == */ ]]; then
        labels+=("[DIR]  $decoded")
      else
        labels+=("[FILE] $decoded")
      fi
    done < <(printf '%s\n' "$html" | sed -n 's/.*href="\([^"]*\)".*/\1/p')

    if [ "$CURRENT_PATH" != "/" ]; then say "${YELLOW}  0) [UP]   ../${RESET}"; fi
    if [ "${#hrefs[@]}" -eq 0 ]; then say "${DIM}  This directory is empty.${RESET}"; fi
    i=0
    while [ "$i" -lt "${#hrefs[@]}" ]; do
      printf '  %b%2d)%b %s\n' "$GREEN" "$((i + 1))" "$RESET" "${labels[$i]}"
      i=$((i + 1))
    done
    say "${DIM}  b) Back to main menu${RESET}"
    printf '\n%b' "${BOLD}Select an item: ${RESET}"
    read -r choice

    case "$choice" in
      b|B) return ;;
      0)
        if [ "$CURRENT_PATH" != "/" ]; then
          CURRENT_PATH="$(printf '%s' "$CURRENT_PATH" | sed 's#[^/]*/$##')"
          [ -n "$CURRENT_PATH" ] || CURRENT_PATH="/"
        fi
        ;;
      ''|*[!0-9]*) ;;
      *)
        index=$((choice - 1))
        if [ "$index" -ge 0 ] && [ "$index" -lt "${#hrefs[@]}" ]; then
          href="${hrefs[$index]}"
          if [[ "$href" == */ ]]; then
            CURRENT_PATH="${CURRENT_PATH}${href}"
          else
            download_file "$href"
          fi
        fi
        ;;
    esac
  done
}

download_file() {
  href="$1"
  filename="$(url_decode "$href")"
  filename="${filename##*/}"
  header
  say "${BLUE}${BOLD}Downloading${RESET}"
  say "  File : ${filename}"
  say "  To   : ${DOWNLOAD_DIR}/${filename}"
  printf '\n'
  if ! ensure_download_dir; then
    pause
    return
  fi
  if download_to_file "${BASE_URL}${CURRENT_PATH}${href}" "${DOWNLOAD_DIR}/${filename}"; then
    printf '\n'
    say "${GREEN}${BOLD}Download completed.${RESET}"
  else
    rm -f -- "${DOWNLOAD_DIR}/${filename}"
    printf '\n'
    say "${RED}${BOLD}Download failed.${RESET}"
    if is_snap_curl && ! command -v wget >/dev/null 2>&1; then
      say "${YELLOW}Your Snap curl cannot access some folders.${RESET}"
      say "${DIM}Install native curl or wget, or choose a folder inside your home directory.${RESET}"
    fi
  fi
  pause
}

settings() {
  while :; do
    header
    say "${BLUE}${BOLD}Settings${RESET}"
    say "  1) Proxy URL       : ${PROXY_URL:-disabled}"
    say "  2) Download folder : ${DOWNLOAD_DIR}"
    say "  3) Reset defaults"
    say "  b) Back"
    printf '\n%b' "${BOLD}Choose: ${RESET}"
    read -r choice
    case "$choice" in
      1)
        printf '\nProxy URL (empty disables proxy): '
        read -r PROXY_URL
        save_config
        ;;
      2)
        printf '\nDownload folder: '
        read -r value
        if [ -n "$value" ]; then
          old_download_dir="$DOWNLOAD_DIR"
          DOWNLOAD_DIR="$(expand_home_path "$value")"
          if ensure_download_dir; then
            save_config
          else
            DOWNLOAD_DIR="$old_download_dir"
            pause
          fi
        fi
        ;;
      3)
        BASE_URL="https://filesv.vnstech.cloud"
        PROXY_URL=""
        DOWNLOAD_DIR="$HOME/Downloads"
        save_config
        ;;
      b|B) return ;;
    esac
  done
}

check_dependencies() {
  for command_name in curl sed tail mkdir; do
    command -v "$command_name" >/dev/null 2>&1 || {
      say "${RED}Missing required command: ${command_name}${RESET}"
      exit 1
    }
  done
}

main() {
  check_dependencies
  load_config
  while :; do
    header
    say "${BLUE}${BOLD}Main Menu${RESET}"
    say "  ${GREEN}1)${RESET} Browse and download files"
    say "  ${GREEN}2)${RESET} Settings"
    say "  ${GREEN}3)${RESET} Connection test"
    say "  ${GREEN}q)${RESET} Quit"
    printf '\n%b' "${BOLD}Choose: ${RESET}"
    read -r choice
    case "$choice" in
      1) browse ;;
      2) settings ;;
      3)
        header
        if curl_run -fsSI --connect-timeout 10 "${BASE_URL}/" >/dev/null; then
          say "${GREEN}${BOLD}Connection is ready.${RESET}"
        else
          say "${RED}${BOLD}Connection failed. Check network or proxy settings.${RESET}"
        fi
        pause
        ;;
      q|Q) header; say "${CYAN}Goodbye.${RESET}"; exit 0 ;;
    esac
  done
}

main "$@"
