#!/bin/sh
# Clawdie Shell — SSH & System User Password Module
# Purpose: Configure SSH keys and system user passwords
# Author: Clawdie Project
# POSIX-compliant (no bash-isms)

set -eu

# Configuration (can be overridden for testing)
LOG_FILE="${LOG_FILE:-/var/log/clawdie-firstboot.log}"
PROGRESS_FILE="${PROGRESS_FILE:-/var/log/clawdie-firstboot.progress}"
EMERGENCY_PASSWORD_FILE="${EMERGENCY_PASSWORD_FILE:-/root/.firstboot-emergency-password}"

# Derived from wizard/build inputs (caller sets these)
# SSH_PUBLIC_KEY            - Optional SSH public key (ssh-ed25519 or ssh-rsa)
# ROOT_PASSWORD             - Optional root password (if empty, auto-generate)
# CLAWDIE_USER_PASSWORD     - Optional clawdie user password (if empty, auto-generate)

# ============================================================================
# MAIN ENTRY POINT
# ============================================================================

clawdie_shell_ssh_setup() {
  # Main orchestrator
  # 1. Configure SSH keys (if provided)
  # 2. Set system passwords (if provided or auto-generate)
  # 3. Configure SSH auth methods (key-only or key+password)
  # 4. Seed SSH client defaults (~/.ssh/config)

  log_msg "[ssh] Starting SSH and password setup"

  # Generate emergency root password if not provided
  if [ -z "${ROOT_PASSWORD:-}" ]; then
    ROOT_PASSWORD=$(gen_secret)
  fi

  # Generate clawdie user password if not provided
  if [ -z "${CLAWDIE_USER_PASSWORD:-}" ]; then
    CLAWDIE_USER_PASSWORD=$(gen_secret)
  fi

  # Setup SSH keys if provided
  if [ -n "${SSH_PUBLIC_KEY:-}" ]; then
    clawdie_shell_ssh_install_pubkey
    clawdie_shell_ssh_disable_password_auth
    clawdie_shell_ssh_seed_client_config
    log_msg "[ssh] SSH public key installed, password auth disabled, client config seeded"
  else
    clawdie_shell_ssh_enable_password_auth
    log_msg "[ssh] No SSH key provided, password auth enabled (less secure)"
  fi

  # Set system user passwords
  clawdie_shell_ssh_set_passwords "$ROOT_PASSWORD" "$CLAWDIE_USER_PASSWORD"
  log_msg "[ssh] System user passwords set"

  # Save emergency root password to file
  clawdie_shell_ssh_save_emergency_password "$ROOT_PASSWORD"
  log_msg "[ssh] Emergency root password saved"

  echo "[SSH] COMPLETE" >> "$PROGRESS_FILE"
  log_msg "[ssh] SSH setup complete"
}

# ============================================================================
# SSH PUBLIC KEY INSTALLATION
# ============================================================================

clawdie_shell_ssh_install_pubkey() {
  # Install SSH_PUBLIC_KEY to authorized_keys for both root and clawdie user

  local root_ssh_dir="/root/.ssh"
  local clawdie_ssh_dir="/home/clawdie/.ssh"

  # Setup root authorized_keys
  if [ ! -d "$root_ssh_dir" ]; then
    mkdir -p "$root_ssh_dir"
    chmod 700 "$root_ssh_dir"
  fi

  echo "$SSH_PUBLIC_KEY" >> "$root_ssh_dir/authorized_keys" 2>/dev/null || {
    log_msg "[ssh] ERROR: Failed to install SSH key for root"
    return 1
  }

  chmod 600 "$root_ssh_dir/authorized_keys"
  log_msg "[ssh] Installed SSH key for root user"

  # Setup clawdie authorized_keys
  if [ ! -d "$clawdie_ssh_dir" ]; then
    mkdir -p "$clawdie_ssh_dir"
    chmod 700 "$clawdie_ssh_dir"
  fi

  echo "$SSH_PUBLIC_KEY" >> "$clawdie_ssh_dir/authorized_keys" 2>/dev/null || {
    log_msg "[ssh] ERROR: Failed to install SSH key for clawdie"
    return 1
  }

  chmod 600 "$clawdie_ssh_dir/authorized_keys"
  chown -R clawdie:clawdie "$clawdie_ssh_dir"
  log_msg "[ssh] Installed SSH key for clawdie user"

  return 0
}

# ============================================================================
# SSH CLIENT CONFIGURATION (seed ~/.ssh/config)
# ============================================================================

clawdie_shell_ssh_seed_client_config() {
  # Seed SSH client defaults for the clawdie user.
  # .profile / .bashrc / .tmux.conf are handled by shell-system.sh
  # (which runs after this module).
  # Run after clawdie_shell_ssh_install_pubkey (requires user to exist).

  local ssh_config="/home/clawdie/.ssh/config"

  # --- ~/.ssh/config: auto-load key on first use, no agent forwarding ---
  if [ ! -f "$ssh_config" ]; then
    cat > "$ssh_config" <<'SSHEOF'
Host *
    AddKeysToAgent yes
    ForwardAgent no
SSHEOF
    chmod 600 "$ssh_config"
    chown clawdie:clawdie "$ssh_config" 2>/dev/null || true
    log_msg "[ssh] Seeded ~/.ssh/config with AddKeysToAgent yes"
  else
    if ! grep -q 'AddKeysToAgent' "$ssh_config" 2>/dev/null; then
      printf '\nHost *\n    AddKeysToAgent yes\n    ForwardAgent no\n' >> "$ssh_config"
      log_msg "[ssh] Appended AddKeysToAgent to existing ~/.ssh/config"
    fi
  fi

  return 0
}

# ============================================================================
# SSH AUTH METHOD CONFIGURATION
# ============================================================================

clawdie_shell_ssh_disable_password_auth() {
  # Disable password authentication in sshd_config
  # Keep PubkeyAuthentication enabled

  local sshd_config="/etc/ssh/sshd_config"

  if [ ! -f "$sshd_config" ]; then
    log_msg "[ssh] WARNING: sshd_config not found"
    return 1
  fi

  # Ensure PubkeyAuthentication is enabled
  if grep -q "^#*PubkeyAuthentication" "$sshd_config"; then
    sed -i '' 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' "$sshd_config"
  else
    echo "PubkeyAuthentication yes" >> "$sshd_config"
  fi

  # Disable PasswordAuthentication
  if grep -q "^#*PasswordAuthentication" "$sshd_config"; then
    sed -i '' 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' "$sshd_config"
  else
    echo "PasswordAuthentication no" >> "$sshd_config"
  fi

  # Disable PermitRootLogin with password (allow pubkey only)
  if grep -q "^#*PermitRootLogin" "$sshd_config"; then
    sed -i '' 's/^#*PermitRootLogin.*/PermitRootLogin prohibit-password/' "$sshd_config"
  else
    echo "PermitRootLogin prohibit-password" >> "$sshd_config"
  fi

  log_msg "[ssh] Disabled password auth in sshd_config"
  return 0
}

clawdie_shell_ssh_enable_password_auth() {
  # Enable password authentication in sshd_config (fallback)
  # Less secure but prevents lockout if user loses SSH key

  local sshd_config="/etc/ssh/sshd_config"

  if [ ! -f "$sshd_config" ]; then
    log_msg "[ssh] WARNING: sshd_config not found"
    return 1
  fi

  # Enable PasswordAuthentication
  if grep -q "^#*PasswordAuthentication" "$sshd_config"; then
    sed -i '' 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' "$sshd_config"
  else
    echo "PasswordAuthentication yes" >> "$sshd_config"
  fi

  # Allow root login with password
  if grep -q "^#*PermitRootLogin" "$sshd_config"; then
    sed -i '' 's/^#*PermitRootLogin.*/PermitRootLogin yes/' "$sshd_config"
  else
    echo "PermitRootLogin yes" >> "$sshd_config"
  fi

  log_msg "[ssh] WARNING: Password auth enabled (less secure)"
  return 0
}

# ============================================================================
# PASSWORD MANAGEMENT
# ============================================================================

clawdie_shell_ssh_set_passwords() {
  local root_pwd="$1"
  local clawdie_pwd="$2"

  # Set root password using echo | pw usermod
  echo "$root_pwd" | pw usermod root -h 0 2>/dev/null || {
    log_msg "[ssh] ERROR: Failed to set root password"
    return 1
  }

  log_msg "[ssh] Root password set"

  # Set clawdie user password
  # Create user if it doesn't exist. Prefer bash when the package is present;
  # fall back to /bin/sh during partial recovery states.
  local clawdie_shell="/bin/sh"
  if [ -x /usr/local/bin/bash ]; then
    clawdie_shell="/usr/local/bin/bash"
    if ! grep -qx '/usr/local/bin/bash' /etc/shells 2>/dev/null; then
      echo '/usr/local/bin/bash' >> /etc/shells 2>/dev/null || true
    fi
  fi
  if [ -x /usr/local/bin/zsh ] && ! grep -qx '/usr/local/bin/zsh' /etc/shells 2>/dev/null; then
    echo '/usr/local/bin/zsh' >> /etc/shells 2>/dev/null || true
  fi
  if ! id clawdie >/dev/null 2>&1; then
    pw useradd -n clawdie -u 1000 -g wheel -m -s "$clawdie_shell" 2>/dev/null || {
      log_msg "[ssh] ERROR: Failed to create clawdie user"
      return 1
    }
    log_msg "[ssh] Created clawdie user"
  elif [ "$clawdie_shell" = "/usr/local/bin/bash" ]; then
    pw usermod clawdie -s /usr/local/bin/bash 2>/dev/null || true
  fi

  echo "$clawdie_pwd" | pw usermod clawdie -h 0 2>/dev/null || {
    log_msg "[ssh] ERROR: Failed to set clawdie password"
    return 1
  }

  log_msg "[ssh] Clawdie user password set"
  return 0
}

clawdie_shell_ssh_save_emergency_password() {
  local root_pwd="$1"

  # Save emergency password to file (root-only, readable only by root)
  {
    echo "EMERGENCY ROOT PASSWORD"
    echo "=============================="
    echo ""
    echo "Generated at: $(date)"
    echo "Password: $root_pwd"
    echo ""
    echo "Access:"
    echo "  ssh root@<domain>"
    echo ""
    echo "WARNING: Store this securely."
    echo "This file should be moved to secure storage and deleted from this system."
  } > "$EMERGENCY_PASSWORD_FILE" 2>/dev/null || {
    log_msg "[ssh] WARNING: Could not save emergency password file"
    return 1
  }

  chmod 600 "$EMERGENCY_PASSWORD_FILE"
  log_msg "[ssh] Emergency password saved to $EMERGENCY_PASSWORD_FILE"
  return 0
}

# ============================================================================
# UTILITY: Logging & Secret Generation
# ============================================================================

log_msg() {
  local msg="$1"
  echo "$msg" >> "$LOG_FILE" 2>/dev/null || true
}

gen_secret() {
  openssl rand -base64 32 | tr -d '\n/+=' | head -c 32
}

# ============================================================================
# Export for use by firstboot.sh
# ============================================================================

case "${0##*/}" in
  shell-ssh.sh)
    # Direct execution (for testing)
    clawdie_shell_ssh_setup
    ;;
  *)
    # Sourced from another script — functions available
    ;;
esac
