#!/usr/bin/env bash
#
# inBOXER Install Script
# ======================
# Downloads the latest inBOXER release from the git repository and
# deploys it to /opt/inboxer as a systemd service.
# Supports Debian (apt) and RHEL (yum/dnf) families.
#
# Usage:
#   curl -sSL https://git.lohmar.co.uk/cclohmar/inboxer/raw/branch/main/install.sh | sudo bash
#
set -euo pipefail

# --- Configuration -----------------------------------------------------------
INSTALL_DIR="/opt/inboxer"
BIN_DIR="${INSTALL_DIR}/bin"
DATA_DIR="${INSTALL_DIR}/data"
LOGS_DIR="${INSTALL_DIR}/logs"

SERVICE_USER="inboxer"
SERVICE_GROUP="inboxer"
SERVICE_NAME="inboxer"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"

# Repository raw content base URL
REPO_BASE="https://git.lohmar.co.uk/cclohmar/inboxer/raw/branch/main"

# --- 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

# Prefer curl; fall back to wget
DOWNLOADER=""
if command -v curl &>/dev/null; then
    DOWNLOADER="curl -sSL"
elif command -v wget &>/dev/null; then
    DOWNLOADER="wget -q -O"
else
    error "Neither curl nor wget found. Install one of them and re-run."
    exit 1
fi

# --- OS Detection (informational) -------------------------------------------
if [[ -f /etc/os-release ]]; then
    # shellcheck source=/dev/null
    . /etc/os-release
    info "Detected OS: ${NAME} ${VERSION_ID}"
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}"
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}"
fi

# --- Create directory structure ----------------------------------------------
WEB_DIR="${INSTALL_DIR}/web"
TEMPLATES_DIR="${WEB_DIR}/templates"
STATIC_DIR="${WEB_DIR}/static"

info "Creating directories under ${INSTALL_DIR}..."
mkdir -p "${BIN_DIR}" "${DATA_DIR}" "${LOGS_DIR}" "${TEMPLATES_DIR}" "${STATIC_DIR}"

# --- Download helper ---------------------------------------------------------
download() {
    local src_url="$1"
    local dest_path="$2"
    local mode="$3"

    local tmpfile
    tmpfile="$(mktemp)"

    if [[ "${DOWNLOADER}" == curl* ]]; then
        curl -sSL "${src_url}" -o "${tmpfile}"
    else
        wget -q -O "${tmpfile}" "${src_url}"
    fi

    # Check that the downloaded content is non-empty and not an HTML error page
    if [[ ! -s "${tmpfile}" ]]; then
        rm -f "${tmpfile}"
        error "Downloaded empty file from ${src_url}"
        return 1
    fi

    # Gitea returns HTML on 404; detect by checking first bytes
    if head -c 100 "${tmpfile}" | grep -qi "<html\|<!DOCTYPE"; then
        rm -f "${tmpfile}"
        error "File not found at ${src_url}"
        return 1
    fi

    install -m "${mode}" "${tmpfile}" "${dest_path}"
    rm -f "${tmpfile}"
    info "  ${src_url##*/} -> ${dest_path}"
}

# --- Download release files --------------------------------------------------
info "Downloading inBOXER release from ${REPO_BASE}/bin/ ..."

download "${REPO_BASE}/bin/inboxer"     "${BIN_DIR}/inboxer"     755
download "${REPO_BASE}/bin/config.yaml" "${BIN_DIR}/config.yaml" 644
download "${REPO_BASE}/bin/prompt.txt"  "${BIN_DIR}/prompt.txt"  644

# Web templates and static assets
info "Downloading web templates and static assets..."
download "${REPO_BASE}/web/templates/base.html"       "${TEMPLATES_DIR}/base.html"       644
download "${REPO_BASE}/web/templates/login.html"      "${TEMPLATES_DIR}/login.html"      644
download "${REPO_BASE}/web/templates/verify.html"     "${TEMPLATES_DIR}/verify.html"     644
download "${REPO_BASE}/web/templates/dashboard.html"  "${TEMPLATES_DIR}/dashboard.html"  644
download "${REPO_BASE}/web/templates/settings.html"   "${TEMPLATES_DIR}/settings.html"   644
download "${REPO_BASE}/web/static/style.css"           "${STATIC_DIR}/style.css"          644

# 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"

# --- 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://git.lohmar.co.uk/cclohmar/inboxer
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=${SERVICE_USER}
Group=${SERVICE_GROUP}
WorkingDirectory=${INSTALL_DIR}
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

# Data and logs directories need write access (overrides ProtectSystem=full)
ReadWritePaths=${DATA_DIR} ${LOGS_DIR}

[Install]
WantedBy=multi-user.target
UNITEOF

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

chmod 755 "${BIN_DIR}"
chmod 750 "${DATA_DIR}"
chmod 750 "${LOGS_DIR}"
chmod 640 "${BIN_DIR}/config.yaml"

# --- 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 (with 30s timeout)..."
timeout 30 systemctl start "${SERVICE_NAME}" || warn "'systemctl start ${SERVICE_NAME}' timed out or failed — the service may need manual investigation"

# 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}/"
echo ""
info " *  Edit config.yaml with your credentials before first start:"
info "    sudo nano ${BIN_DIR}/config.yaml"
echo ""
info "    Required settings:"
info "      - ai.api_key             (DeepSeek API key)"
info "      - smtp.host / port       (SMTP server for OTP emails)"
info "      - smtp.username / pass   (SMTP login credentials)"
info "      - server.session_secret  (change from the default)"
echo ""
if grep -q "your_deepseek_api_key_here\|your.smtp.host\|change-me-in-production" \
    "${BIN_DIR}/config.yaml" 2>/dev/null; then
    warn " !  config.yaml still contains placeholder values!"
    warn "     Edit ${BIN_DIR}/config.yaml 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 ""
