#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=_config.sh
source "${SCRIPT_DIR}/_config.sh"

log() { printf '[setup] %s\n' "$*"; }
die() { printf '[setup][error] %s\n' "$*" >&2; exit 1; }

# --- Local prerequisites ---

command -v kubectl >/dev/null 2>&1 || die "Missing locally: kubectl (https://kubernetes.io/docs/tasks/tools/)"

# --- Server connection ---

SERVER_HOST="$(cfg_require server.host "Server IP or SSH alias")"
SERVER_USER="$(cfg server.user)"
SERVER_USER="${SERVER_USER:-root}"
SSH_KEY="$(cfg server.ssh_key | sed "s|~|${HOME}|g")"

SSH_OPTS=()
if [[ -n "${SSH_KEY}" && -f "${SSH_KEY}" ]]; then
  SSH_OPTS+=(-i "${SSH_KEY}")
fi
SSH_OPTS+=(-o StrictHostKeyChecking=accept-new)

ssh_cmd() {
  ssh "${SSH_OPTS[@]}" "${SERVER_USER}@${SERVER_HOST}" "$@"
}

log "Testing SSH connection to ${SERVER_USER}@${SERVER_HOST}..."
ssh_cmd "echo 'SSH connection OK'" || die "Cannot SSH into ${SERVER_HOST}"

# --- Server prerequisites ---

log "Setting up server prerequisites..."

ssh_cmd 'bash -s' <<'REMOTE_SETUP'
set -euo pipefail

log() { printf '[setup][remote] %s\n' "$*"; }

# --- System updates ---
log "Updating system packages..."
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get upgrade -y -qq

# --- SSH hardening ---
log "Hardening SSH..."
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
systemctl reload sshd 2>/dev/null || systemctl reload ssh 2>/dev/null || true

# --- fail2ban ---
if ! command -v fail2ban-client >/dev/null 2>&1; then
  log "Installing fail2ban..."
  apt-get install -y -qq fail2ban
  systemctl enable --now fail2ban
else
  log "fail2ban already installed"
fi

# --- Unattended security upgrades ---
if ! dpkg -l | grep -q unattended-upgrades; then
  log "Installing unattended-upgrades..."
  apt-get install -y -qq unattended-upgrades
  dpkg-reconfigure -plow unattended-upgrades
else
  log "unattended-upgrades already installed"
fi

# --- Firewall (ufw) ---
if command -v ufw >/dev/null 2>&1; then
  log "Configuring firewall..."
  ufw default deny incoming
  ufw default allow outgoing
  ufw allow 22/tcp     # SSH
  ufw allow 443/tcp    # HTTPS (Traefik)
  ufw allow 6443/tcp   # K3s API
  ufw allow 80/tcp     # HTTP (Let's Encrypt ACME challenge)
  ufw --force enable
else
  log "Installing ufw..."
  apt-get install -y -qq ufw
  ufw default deny incoming
  ufw default allow outgoing
  ufw allow 22/tcp
  ufw allow 443/tcp
  ufw allow 6443/tcp
  ufw allow 80/tcp
  ufw --force enable
fi

log "Server prerequisites complete."
REMOTE_SETUP

# --- Install K3s ---

log "Installing K3s on ${SERVER_HOST}..."
log "  This takes about 1-2 minutes."

ssh_cmd "curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC='server --secrets-encryption' sh -"

# --- Wait for K3s to be ready ---

log "Waiting for K3s to be ready..."
ssh_cmd "until kubectl get nodes >/dev/null 2>&1; do sleep 2; done"

# --- Copy kubeconfig ---

KUBECONFIG_PATH="${DEPLOY_DIR}/kubeconfig"

log "Copying kubeconfig..."
ssh_cmd "sudo cat /etc/rancher/k3s/k3s.yaml" > "${KUBECONFIG_PATH}"

# Replace 127.0.0.1 with the server's actual IP/hostname
# If SERVER_HOST is an SSH alias, resolve the actual IP
ACTUAL_HOST="${SERVER_HOST}"
if ! echo "${SERVER_HOST}" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
  # Try to resolve from SSH config
  RESOLVED="$(ssh -G "${SERVER_HOST}" 2>/dev/null | awk '/^hostname / {print $2}')"
  if [[ -n "${RESOLVED}" && "${RESOLVED}" != "${SERVER_HOST}" ]]; then
    ACTUAL_HOST="${RESOLVED}"
  fi
fi

sed -i.bak "s|https://127.0.0.1:6443|https://${ACTUAL_HOST}:6443|g" "${KUBECONFIG_PATH}"
rm -f "${KUBECONFIG_PATH}.bak"
chmod 600 "${KUBECONFIG_PATH}"

# --- Verify ---

export KUBECONFIG="${KUBECONFIG_PATH}"
log "Verifying cluster..."
kubectl get nodes

log ""
log "K3s installed successfully on ${SERVER_HOST}."
log "Server hardened: SSH key-only, fail2ban, ufw firewall, unattended-upgrades."
log ""
log "Next steps:"
log "  export KUBECONFIG=${KUBECONFIG_PATH}"
log "  kubectl get nodes"
log "  ./scripts/02-setup-secrets.sh"
