#!/bin/sh
set -eu

# Trình cài đặt một lệnh cho TAURIN.
#
# Cách dùng sau khi deploy:
#   curl -sfL https://your-server.example/taurin/install.sh | sh -
#
# Tùy chọn:
#   TAURIN_INSTALL_DIR=$HOME/.local/share/taurin
#   TAURIN_BRANCH=main
#   TAURIN_SKIP_SERVICE=true
#   TAURIN_SKIP_FREERDP=true
#   TAURIN_FORCE=true
#   TELEGRAM_BOT_TOKEN=...
#   GROQ_API_KEY=...
#   TELEGRAM_ALLOWED_USER_ID=...
#   TAURIN_OWNER_NAME=anh Ryan

TAURIN_INSTALL_DIR="${TAURIN_INSTALL_DIR:-$HOME/.local/share/taurin}"
TAURIN_SERVICE_NAME="${TAURIN_SERVICE_NAME:-taurin}"
TAURIN_BRANCH="${TAURIN_BRANCH:-main}"
TAURIN_DEFAULT_SOURCE_URL="https://troly-taurin.pages.dev/taurin.tar.gz"
TAURIN_SOURCE_URL="${TAURIN_SOURCE_URL:-$TAURIN_DEFAULT_SOURCE_URL}"
TAURIN_GIT_URL="${TAURIN_GIT_URL:-}"
TAURIN_SKIP_SERVICE="${TAURIN_SKIP_SERVICE:-false}"
TAURIN_SKIP_FREERDP="${TAURIN_SKIP_FREERDP:-false}"
TAURIN_FORCE="${TAURIN_FORCE:-false}"
TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN:-}"
GROQ_API_KEY="${GROQ_API_KEY:-}"
GROQ_BASE_URL="${GROQ_BASE_URL:-https://api.groq.com/openai/v1}"
TELEGRAM_ALLOWED_USER_ID="${TELEGRAM_ALLOWED_USER_ID:-}"
TAURIN_OWNER_NAME="${TAURIN_OWNER_NAME:-anh}"
PRESERVE_DIR=""

log() {
  printf '%s\n' "$*"
}

fail() {
  log "LỖI: $*" >&2
  exit 1
}

need_cmd() {
  command -v "$1" >/dev/null 2>&1 || fail "Thiếu lệnh bắt buộc: $1"
}

has_tty() {
  [ -r /dev/tty ] && [ -w /dev/tty ]
}

prompt() {
  label="$1"
  default_value="${2:-}"
  if ! has_tty; then
    fail "Không thể hỏi thông tin vì không có TTY. Hãy truyền TELEGRAM_BOT_TOKEN, GROQ_API_KEY và TELEGRAM_ALLOWED_USER_ID bằng biến môi trường."
  fi
  if [ -n "$default_value" ]; then
    printf "%s [%s]: " "$label" "$default_value" > /dev/tty
  else
    printf "%s: " "$label" > /dev/tty
  fi
  IFS= read -r value < /dev/tty
  if [ -z "$value" ]; then
    value="$default_value"
  fi
  printf '%s' "$value"
}

prompt_secret() {
  label="$1"
  if ! has_tty; then
    fail "Không thể hỏi thông tin vì không có TTY. Hãy truyền TELEGRAM_BOT_TOKEN, GROQ_API_KEY và TELEGRAM_ALLOWED_USER_ID bằng biến môi trường."
  fi
  printf "%s: " "$label" > /dev/tty
  stty -echo < /dev/tty 2>/dev/null || true
  IFS= read -r value < /dev/tty
  stty echo < /dev/tty 2>/dev/null || true
  printf "\n" > /dev/tty
  printf '%s' "$value"
}

confirm() {
  label="$1"
  default="${2:-n}"
  if ! has_tty; then
    [ "$default" = "y" ]
    return
  fi
  answer="$(prompt "$label (c/k)" "$default")"
  case "$answer" in
    c|C|co|có|Co|Có|y|Y|yes|YES|Yes) return 0 ;;
    *) return 1 ;;
  esac
}

as_root() {
  if [ "$(id -u)" -eq 0 ]; then
    "$@"
  elif command -v sudo >/dev/null 2>&1; then
    sudo "$@"
  else
    fail "Cần quyền root. Hãy cài sudo hoặc chạy bằng root."
  fi
}

install_system_packages() {
  if command -v apt-get >/dev/null 2>&1; then
    log "[1/7] Đang cài package hệ thống bằng apt..."
    as_root apt-get update
    packages="python3 python3-venv python3-pip curl ca-certificates git unzip"
    if [ "$TAURIN_SKIP_FREERDP" != "true" ]; then
      packages="$packages freerdp3-x11"
    fi
    # shellcheck disable=SC2086
    as_root apt-get install -y $packages
    return
  fi

  fail "Chưa hỗ trợ package manager này. Installer hiện chỉ hỗ trợ Ubuntu/Debian dùng apt."
}

prepare_install_dir() {
  log "[2/7] Đang chuẩn bị thư mục cài đặt: $TAURIN_INSTALL_DIR"
  if [ -e "$TAURIN_INSTALL_DIR" ]; then
    if [ "$TAURIN_FORCE" != "true" ]; then
      log "Đã phát hiện TAURIN đang được cài tại: $TAURIN_INSTALL_DIR"
      if ! confirm "Cài lại code TAURIN và giữ nguyên data/cấu hình" "y"; then
        fail "Đã hủy cài đặt."
      fi
    fi

    PRESERVE_DIR="$(mktemp -d)"
    for item in data secrets logs .env config.yaml; do
      if [ -e "$TAURIN_INSTALL_DIR/$item" ]; then
        cp -a "$TAURIN_INSTALL_DIR/$item" "$PRESERVE_DIR/"
      fi
    done
    rm -rf "$TAURIN_INSTALL_DIR"
  fi

  mkdir -p "$TAURIN_INSTALL_DIR"
}

restore_preserved_files() {
  if [ -n "$PRESERVE_DIR" ] && [ -d "$PRESERVE_DIR" ]; then
    log "Đang khôi phục data/cấu hình cũ..."
    cp -a "$PRESERVE_DIR"/. "$TAURIN_INSTALL_DIR"/
    rm -rf "$PRESERVE_DIR"
  fi
}

download_source() {
  log "[3/7] Đang tải mã nguồn TAURIN..."

  if [ -n "$TAURIN_SOURCE_URL" ]; then
    tmp_file="$(mktemp)"
    curl -fsSL "$TAURIN_SOURCE_URL" -o "$tmp_file"
    case "$TAURIN_SOURCE_URL" in
      *.tar.gz|*.tgz)
        tar -xzf "$tmp_file" -C "$TAURIN_INSTALL_DIR" --strip-components=1
        ;;
      *.zip)
        need_cmd unzip
        tmp_dir="$(mktemp -d)"
        unzip -q "$tmp_file" -d "$tmp_dir"
        first_dir="$(find "$tmp_dir" -mindepth 1 -maxdepth 1 -type d | head -n 1)"
        [ -n "$first_dir" ] || fail "File zip không chứa thư mục dự án."
        cp -R "$first_dir"/. "$TAURIN_INSTALL_DIR"/
        rm -rf "$tmp_dir"
        ;;
      *)
        fail "Định dạng TAURIN_SOURCE_URL chưa hỗ trợ. Hãy dùng .tar.gz, .tgz hoặc .zip."
        ;;
    esac
    rm -f "$tmp_file"
    return
  fi

  if [ -n "$TAURIN_GIT_URL" ]; then
    need_cmd git
    git clone --depth 1 --branch "$TAURIN_BRANCH" "$TAURIN_GIT_URL" "$TAURIN_INSTALL_DIR"
    return
  fi

  fail "Hãy cấu hình TAURIN_SOURCE_URL hoặc TAURIN_GIT_URL trước khi chạy installer."
}

stop_existing_service() {
  if [ "$TAURIN_SKIP_SERVICE" = "true" ]; then
    return
  fi
  if command -v systemctl >/dev/null 2>&1; then
    systemctl --user stop "$TAURIN_SERVICE_NAME" >/dev/null 2>&1 || true
  fi
}

setup_python() {
  log "[4/7] Đang tạo môi trường Python..."
  cd "$TAURIN_INSTALL_DIR"
  python3 -m venv venv
  # shellcheck disable=SC1091
  . venv/bin/activate
  python -m pip install --upgrade pip
  pip install -r requirements.txt
}

bootstrap_config() {
  log "[5/7] Đang tạo file cấu hình local..."
  cd "$TAURIN_INSTALL_DIR"
  bash scripts/bootstrap_config.sh
}

validate_telegram_token() {
  token="$1"
  [ -n "$token" ] || return 1
  tmp_file="$(mktemp)"
  if curl -fsS "https://api.telegram.org/bot${token}/getMe" -o "$tmp_file" >/dev/null 2>&1 \
    && grep -q '"ok"[[:space:]]*:[[:space:]]*true' "$tmp_file"; then
    rm -f "$tmp_file"
    return 0
  fi
  rm -f "$tmp_file"
  return 1
}

validate_groq_key() {
  key="$1"
  [ -n "$key" ] || return 1
  code="$(
    curl -sS -o /dev/null -w "%{http_code}" \
      -H "Authorization: Bearer $key" \
      "$GROQ_BASE_URL/models" 2>/dev/null || true
  )"
  [ "$code" = "200" ]
}

validate_allowed_user_id() {
  case "$1" in
    ''|*[!0-9]*) return 1 ;;
    *) return 0 ;;
  esac
}

collect_runtime_config() {
  log "[6/7] Đang cấu hình Telegram, Groq, user được phép và danh xưng..."

  while ! validate_telegram_token "$TELEGRAM_BOT_TOKEN"; do
    if [ -n "$TELEGRAM_BOT_TOKEN" ]; then
      log "Telegram bot token không hợp lệ. Vui lòng nhập lại."
    fi
    TELEGRAM_BOT_TOKEN="$(prompt_secret "Telegram bot token")"
  done
  log "Telegram bot token hợp lệ."

  while ! validate_groq_key "$GROQ_API_KEY"; do
    if [ -n "$GROQ_API_KEY" ]; then
      log "Groq API key không hợp lệ. Vui lòng nhập lại."
    fi
    GROQ_API_KEY="$(prompt_secret "Groq API key")"
  done
  log "Groq API key hợp lệ."

  while ! validate_allowed_user_id "$TELEGRAM_ALLOWED_USER_ID"; do
    if [ -n "$TELEGRAM_ALLOWED_USER_ID" ]; then
      log "Telegram allowed user ID phải là số."
    fi
    TELEGRAM_ALLOWED_USER_ID="$(prompt "Telegram user ID dạng số từ @userinfobot")"
  done

  TAURIN_OWNER_NAME="$(prompt "Danh xưng TAURIN dùng để gọi bạn" "$TAURIN_OWNER_NAME")"
  if [ -z "$TAURIN_OWNER_NAME" ]; then
    TAURIN_OWNER_NAME="anh"
  fi
}

write_runtime_config() {
  cd "$TAURIN_INSTALL_DIR"
  "$TAURIN_INSTALL_DIR/venv/bin/python" - "$TELEGRAM_BOT_TOKEN" "$GROQ_API_KEY" "$GROQ_BASE_URL" "$TELEGRAM_ALLOWED_USER_ID" "$TAURIN_OWNER_NAME" <<'PY'
from pathlib import Path
import os
import stat
import sys
import yaml

token, groq_key, groq_base_url, allowed_user_id, owner_name = sys.argv[1:]
root = Path.cwd()
env_path = root / ".env"
config_path = root / "config.yaml"

def update_env(path: Path, values: dict[str, str]) -> None:
    current: dict[str, str] = {}
    order: list[str] = []
    if path.exists():
        for line in path.read_text(encoding="utf-8").splitlines():
            if not line or line.lstrip().startswith("#") or "=" not in line:
                continue
            key, value = line.split("=", 1)
            key = key.strip()
            current[key] = value
            order.append(key)
    current.update(values)
    for key in values:
        if key not in order:
            order.append(key)
    text = "\n".join(f"{key}={current[key]}" for key in order if key in current) + "\n"
    path.write_text(text, encoding="utf-8")
    path.chmod(stat.S_IRUSR | stat.S_IWUSR)

update_env(
    env_path,
    {
        "TELEGRAM_BOT_TOKEN": token,
        "GROQ_API_KEY": groq_key,
        "GROQ_BASE_URL": groq_base_url,
    },
)

data = {}
if config_path.exists():
    data = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {}

data.setdefault("security", {})["allowed_users"] = [int(allowed_user_id)]
data.setdefault("owner", {})["name"] = owner_name or "anh"

config_path.write_text(yaml.safe_dump(data, allow_unicode=True, sort_keys=False), encoding="utf-8")
config_path.chmod(stat.S_IRUSR | stat.S_IWUSR)
PY
}

install_user_service() {
  if [ "$TAURIN_SKIP_SERVICE" = "true" ]; then
    log "[7/7] Bỏ qua systemd user service."
    return
  fi

  if ! command -v systemctl >/dev/null 2>&1; then
    log "[7/7] Không tìm thấy systemctl. Bỏ qua cài service."
    return
  fi

  log "[7/7] Đang cài systemd user service..."
  service_dir="$HOME/.config/systemd/user"
  service_file="$service_dir/$TAURIN_SERVICE_NAME.service"
  mkdir -p "$service_dir"

  cat > "$service_file" <<EOF
[Unit]
Description=TAURIN - Trợ lý điều khiển Ubuntu qua Telegram
After=graphical-session.target

[Service]
Type=simple
WorkingDirectory=$TAURIN_INSTALL_DIR
ExecStart=$TAURIN_INSTALL_DIR/venv/bin/python $TAURIN_INSTALL_DIR/main.py
Restart=always
RestartSec=5

[Install]
WantedBy=default.target
EOF

  systemctl --user daemon-reload || true
  systemctl --user import-environment DISPLAY WAYLAND_DISPLAY XAUTHORITY XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS XDG_CURRENT_DESKTOP XDG_SESSION_TYPE || true
  systemctl --user enable "$TAURIN_SERVICE_NAME" || true
}

start_user_service() {
  if [ "$TAURIN_SKIP_SERVICE" = "true" ]; then
    return
  fi
  if command -v systemctl >/dev/null 2>&1; then
    systemctl --user restart "$TAURIN_SERVICE_NAME" || true
  fi
}

print_next_steps() {
  cat <<EOF

TAURIN đã được cài tại:
  $TAURIN_INSTALL_DIR

Cấu hình đã lưu:
  $TAURIN_INSTALL_DIR/.env
  $TAURIN_INSTALL_DIR/config.yaml

Service:
  systemctl --user status $TAURIN_SERVICE_NAME
  journalctl --user -u $TAURIN_SERVICE_NAME -f

Telegram:
  Hãy nhắn /start cho bot Telegram của bạn.
EOF
}

main() {
  need_cmd curl
  need_cmd tar
  install_system_packages
  stop_existing_service
  prepare_install_dir
  download_source
  restore_preserved_files
  setup_python
  bootstrap_config
  collect_runtime_config
  write_runtime_config
  install_user_service
  start_user_service
  print_next_steps
}

main "$@"
