#!/usr/bin/env bash
#
# inBOXER Install Script
# ======================
# Deploys the inBOXER binary and configuration to /opt/inboxer
# Creates a systemd service for production deployment.
# Supports Debian (apt) and RHEL (yum/dnf) families.
#
# Usage: sudo ./install.sh
#
set -euo pipefail

# ─── Configuration ───────────────────────────────────────────────────────────
INSTALL_DIR="/opt/inboxer"
SERVICE_USER="inboxer"
SERVICE_GROUP="inboxer"
SERVICE_NAME="inboxer"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"

BIN_DIR="${INSTALL_DIR}/bin"
DATA_DIR="${INSTALL_DIR}/data"
LOGS_DIR="${INSTALL_DIR}/logs"

# Detect script/repo location
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ "$(basename "${SCRIPT_DIR}")" == "bin" ]]; then
    REPO_DIR="$(dirname "${SCRIPT_DIR}")"
else
    REPO_DIR="${SCRIPT_DIR}"
fi

# ─── Terminal colours ────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

info()  { echo -e "${GREEN}[INFO]${NC}  $*"; }
warn()  { echo -e "${YELLOW}[WARN]${NC}  $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }

# ─── Pre-flight checks ───────────────────────────────────────────────────────
if [[ $EUID -ne 0 ]]; then
    error "This script must be run as root (use sudo)."
    exit 1
fi

if ! command -v systemctl &>/dev/null; then
    error "systemd is required but not found on this system."
    exit 1
fi

REQUIRED_FILES=(
    "${REPO_DIR}/bin/inboxer"
    "${REPO_DIR}/bin/config.yaml"
    "${REPO_DIR}/bin/prompt.txt"
)
for f in "${REQUIRED_FILES[@]}"; do
    if [[ ! -f "$f" ]]; then
        error "Required file not found: $f"
        error "Run this script from the inBOXER repository root."
        exit 1
    fi
done

# ─── OS Detection (informational) ───────────────────────────────────────────
if [[ -f /etc/os-release ]]; then
    # shellcheck source=/dev/null
    . /etc/os-release
    info "Detected OS: ${NAME} ${VERSION_ID}"
else
    info "Could not detect OS version (no /etc/os-release)."
fi

# ─── Create system user & group ──────────────────────────────────────────────
info "Creating system user '${SERVICE_USER}'..."

if getent group "${SERVICE_GROUP}" &>/dev/null; then
    info "Group '${SERVICE_GROUP}' already exists."
else
    groupadd --system "${SERVICE_GROUP}"
    info "Group '${SERVICE_GROUP}' created."
fi

if getent passwd "${SERVICE_USER}" &>/dev/null; then
    info "User '${SERVICE_USER}' already exists."
else
    useradd --system \
            --no-create-home \
            --gid "${SERVICE_GROUP}" \
            --shell /sbin/nologin \
            --comment "inBOXER Service User" \
            "${SERVICE_USER}"
    info "User '${SERVICE_USER}' created."
fi

# ─── Create directory structure ──────────────────────────────────────────────
info "Creating directories under ${INSTALL_DIR}..."
mkdir -p "${BIN_DIR}" "${DATA_DIR}" "${LOGS_DIR}"

# ─── Install binary & config files ───────────────────────────────────────────
info "Installing binary..."
install -m 755 "${REPO_DIR}/bin/inboxer" "${BIN_DIR}/inboxer"

info "Installing configuration..."
install -m 644 "${REPO_DIR}/bin/config.yaml" "${BIN_DIR}/config.yaml"
install -m 644 "${REPO_DIR}/bin/prompt.txt"  "${BIN_DIR}/prompt.txt"

# Adjust config paths for /opt/inboxer deployment
info "Adjusting configuration paths for deployment..."
sed -i 's|path: "bin/db.sqlite"|path: "'"${DATA_DIR}"'/db.sqlite"|' "${BIN_DIR}/config.yaml"
sed -i 's|file: "bin/inboxer.log"|file: "'"${LOGS_DIR}"'/inboxer.log"|' "${BIN_DIR}/config.yaml"
# prompt_file: "bin/prompt.txt" works as-is relative to the working directory,
# since WorkingDirectory=/opt/inboxer resolves it to /opt/inboxer/bin/prompt.txt

# ─── Create .env from template ──────────────────────────────────────────────
ENV_FILE="${INSTALL_DIR}/.env"
if [[ ! -f "${ENV_FILE}" ]]; then
    # Prefer .env.example from repo (single source of truth)
    if [[ -f "${REPO_DIR}/.env.example" ]]; then
        info "Copying .env.example from repository to ${ENV_FILE} ..."
        cp "${REPO_DIR}/.env.example" "${ENV_FILE}"
    else
        info "Creating .env template at ${ENV_FILE} ..."
        cat > "${ENV_FILE}" << 'ENVEOF'
# inBOXER Environment Configuration
# ====================================
# Set your credentials below. The service reads these variables on startup.
# You can also set them directly in the systemd EnvironmentFile or via
# the shell environment (godotenv.Load() checks both the .env file and os.Getenv).

# DeepSeek API key – used to classify incoming emails
DEEPSEEK_API_KEY=your_deepseek_api_key_here

# SMTP credentials – used to send one-time passwords (OTP) via email
SMTP_HOST=your.smtp.host
SMTP_PORT=587
SMTP_USER=your-email@example.com
SMTP_PASS=your-smtp-password

# (Optional) Override the session_secret from config.yaml.
# APP_SECRET=change-me-in-production
ENVEOF
    fi
    info ".env file created."
else
    info ".env already exists, keeping existing file."
fi

# ─── Create systemd service unit ─────────────────────────────────────────────
info "Creating systemd service unit at ${SERVICE_FILE} ..."
cat > "${SERVICE_FILE}" << UNITEOF
[Unit]
Description=inBOXER – AI-Powered Email Classifier
Documentation=https://github.com/cclohmar/inboxer
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=${SERVICE_USER}
Group=${SERVICE_GROUP}
WorkingDirectory=${INSTALL_DIR}
EnvironmentFile=${ENV_FILE}
ExecStart=${BIN_DIR}/inboxer
Restart=on-failure
RestartSec=10

# Logging
StandardOutput=append:${LOGS_DIR}/stdout.log
StandardError=append:${LOGS_DIR}/stderr.log

# Security hardening
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
UNITEOF

# ─── Set file permissions ────────────────────────────────────────────────────
info "Setting file ownership and permissions..."
chown -R "${SERVICE_USER}:${SERVICE_GROUP}" "${INSTALL_DIR}"

# Directory permissions
chmod 755 "${BIN_DIR}"
chmod 750 "${DATA_DIR}"   # database file is sensitive
chmod 750 "${LOGS_DIR}"

# .env must be readable by the service user (and owner-only for secrets)
chmod 640 "${ENV_FILE}"

# ─── Register & start service ───────────────────────────────────────────────
info "Reloading systemd daemon..."
systemctl daemon-reload

info "Enabling ${SERVICE_NAME} service (starts on boot)..."
systemctl enable "${SERVICE_NAME}"

info "Starting ${SERVICE_NAME} service..."
systemctl start "${SERVICE_NAME}"

# Brief pause so the service can initialise
sleep 2

# ─── Verify ──────────────────────────────────────────────────────────────────
if systemctl is-active --quiet "${SERVICE_NAME}"; then
    info "Service '${SERVICE_NAME}' is running."
    systemctl status "${SERVICE_NAME}" --no-pager
else
    warn "Service '${SERVICE_NAME}' did not start. Check logs:"
    warn "  journalctl -u ${SERVICE_NAME} --no-pager"
    systemctl status "${SERVICE_NAME}" --no-pager || true
fi

# ─── Summary ─────────────────────────────────────────────────────────────────
echo ""
info "═════════════════════════════════════════════════"
info "  inBOXER Installation Complete"
info "═════════════════════════════════════════════════"
echo ""
info " Install directory:  ${INSTALL_DIR}"
info " Binary:             ${BIN_DIR}/inboxer"
info " Configuration:      ${BIN_DIR}/config.yaml"
info " Prompt file:        ${BIN_DIR}/prompt.txt"
info " Data (SQLite):      ${DATA_DIR}/"
info " Logs:               ${LOGS_DIR}/"
info " Environment:        ${ENV_FILE}"
echo ""
info " Edit the environment file with your credentials:"
info "   sudo nano ${ENV_FILE}"
echo ""
if grep -q "your_deepseek_api_key_here" "${ENV_FILE}" 2>/dev/null; then
    warn " ⚠ The .env file still contains placeholder values!"
    warn "    Edit ${ENV_FILE} before the service will function."
    echo ""
fi
info " Service management:"
info "   sudo systemctl status  ${SERVICE_NAME}"
info "   sudo systemctl restart ${SERVICE_NAME}"
info "   sudo systemctl stop    ${SERVICE_NAME}"
info "   sudo journalctl -u     ${SERVICE_NAME} -f"
echo ""
info " Web interface:  http://$(hostname -s 2>/dev/null || echo "localhost"):8080"
info "═════════════════════════════════════════════════"
echo ""
