#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────
# CITRA Insight — Linux Agent Installer
# ─────────────────────────────────────────────────────────────────────
# One-command install:
#   curl -sSL https://install.citrainsight.in/linux | sudo bash
#
# Supports:
#   - Ubuntu 20.04+
#   - Debian 11+
#   - RHEL 8+ / CentOS Stream 8+
#   - Fedora 36+
#
# What this script does:
#   1. Checks prerequisites (root, Python 3.8+, systemd)
#   2. Creates /opt/citrainsight/ directory
#   3. Downloads the agent package (or copies from local)
#   4. Installs Python dependencies
#   5. Creates the systemd service
#   6. Enables and starts the service
#
# (c) 2026 Code & Clause Systems. All rights reserved.
# ─────────────────────────────────────────────────────────────────────

set -euo pipefail

INSTALL_DIR="/opt/citrainsight"
SERVICE_NAME="citrainsight"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
AGENT_VERSION="1.0.0"
PYTHON_MIN="3.8"

# Colours (if terminal supports them)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Colour

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

# ─────────────────────────────────────────────────────────────────────
# PRE-FLIGHT CHECKS
# ─────────────────────────────────────────────────────────────────────

check_root() {
    if [[ $EUID -ne 0 ]]; then
        error "This installer must be run as root. Use: sudo bash $0"
    fi
}

check_os() {
    if [[ ! -f /etc/os-release ]]; then
        error "Cannot detect OS — /etc/os-release not found"
    fi

    . /etc/os-release

    info "Detected OS: ${PRETTY_NAME:-$ID $VERSION_ID}"

    case "${ID}" in
        ubuntu|debian|rhel|centos|rocky|almalinux|fedora|ol)
            ;;
        *)
            warn "Unsupported distribution: ${ID}. Proceeding anyway…"
            ;;
    esac
}

check_systemd() {
    if ! command -v systemctl &>/dev/null; then
        error "systemd is required but not found"
    fi
    info "systemd: OK"
}

check_python() {
    local python_cmd=""

    for cmd in python3 python; do
        if command -v "$cmd" &>/dev/null; then
            local ver
            ver=$("$cmd" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null)
            if python3 -c "
import sys
min_ver = tuple(map(int, '${PYTHON_MIN}'.split('.')))
cur_ver = (sys.version_info.major, sys.version_info.minor)
sys.exit(0 if cur_ver >= min_ver else 1)
" 2>/dev/null; then
                python_cmd="$cmd"
                info "Python: $ver ($cmd)"
                break
            fi
        fi
    done

    if [[ -z "$python_cmd" ]]; then
        warn "Python ${PYTHON_MIN}+ not found — attempting to install…"
        install_python
        python_cmd="python3"
    fi

    PYTHON_CMD="$python_cmd"
}

install_python() {
    . /etc/os-release

    case "${ID}" in
        ubuntu|debian)
            apt-get update -qq
            apt-get install -y -qq python3 python3-pip python3-venv
            ;;
        rhel|centos|rocky|almalinux|ol)
            dnf install -y python3 python3-pip
            ;;
        fedora)
            dnf install -y python3 python3-pip
            ;;
        *)
            error "Cannot auto-install Python on ${ID}. Please install Python ${PYTHON_MIN}+ manually."
            ;;
    esac
}

# ─────────────────────────────────────────────────────────────────────
# INSTALLATION
# ─────────────────────────────────────────────────────────────────────

create_directories() {
    info "Creating ${INSTALL_DIR}…"
    mkdir -p "${INSTALL_DIR}"
    chmod 755 "${INSTALL_DIR}"
}

install_agent_files() {
    info "Installing agent files…"

    # Check if we're running from a local checkout
    local script_dir
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

    if [[ -f "${script_dir}/main.py" ]]; then
        # Local install — copy from checkout
        info "Installing from local directory: ${script_dir}"
        cp -r "${script_dir}/../agent_linux" "${INSTALL_DIR}/agent_linux"

        # Also copy any shared requirements
        if [[ -f "${script_dir}/../requirements-agent.txt" ]]; then
            cp "${script_dir}/../requirements-agent.txt" "${INSTALL_DIR}/"
        fi
    else
        # Remote install — download from server
        info "Downloading agent v${AGENT_VERSION}…"
        local download_url="https://releases.citrainsight.in/agent/linux/${AGENT_VERSION}/agent_linux.tar.gz"

        if command -v curl &>/dev/null; then
            curl -sSL "${download_url}" -o /tmp/citrainsight-agent.tar.gz
        elif command -v wget &>/dev/null; then
            wget -q "${download_url}" -O /tmp/citrainsight-agent.tar.gz
        else
            error "Neither curl nor wget found. Install one and retry."
        fi

        tar -xzf /tmp/citrainsight-agent.tar.gz -C "${INSTALL_DIR}/"
        rm -f /tmp/citrainsight-agent.tar.gz
    fi
}

install_dependencies() {
    info "Installing Python dependencies…"

    # Create virtual environment
    "${PYTHON_CMD}" -m venv "${INSTALL_DIR}/venv" 2>/dev/null || true

    local pip="${INSTALL_DIR}/venv/bin/pip"
    if [[ ! -f "$pip" ]]; then
        pip="${PYTHON_CMD} -m pip"
    fi

    # Install cryptography (required for token vault)
    $pip install --quiet --upgrade pip 2>/dev/null || true
    $pip install --quiet cryptography 2>/dev/null || {
        warn "Failed to install cryptography via pip."
        warn "Trying system package…"

        . /etc/os-release
        case "${ID}" in
            ubuntu|debian)
                apt-get install -y -qq python3-cryptography
                ;;
            rhel|centos|rocky|almalinux|fedora|ol)
                dnf install -y python3-cryptography 2>/dev/null || \
                    yum install -y python3-cryptography 2>/dev/null || true
                ;;
        esac
    }

    info "Dependencies installed"
}

create_config() {
    local config_file="${INSTALL_DIR}/config.json"

    if [[ -f "$config_file" ]]; then
        info "Config already exists — preserving"
        return
    fi

    info "Creating default config…"
    cat > "$config_file" <<'CONFIGEOF'
{
  "server_url": "",
  "scan_profile": "standard",
  "full_scan_interval": 86400,
  "delta_scan_interval": 21600,
  "heartbeat_interval": 60,
  "retry_interval": 120,
  "support_email": "support@citrainsight.in"
}
CONFIGEOF

    chmod 600 "$config_file"
}

create_service() {
    info "Creating systemd service…"

    local python_path="${INSTALL_DIR}/venv/bin/python"
    if [[ ! -f "$python_path" ]]; then
        python_path="${PYTHON_CMD}"
    fi

    cat > "${SERVICE_FILE}" <<SERVICEEOF
[Unit]
Description=CITRA Insight IT Asset Intelligence Agent
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=${python_path} -m agent_linux.main run
WorkingDirectory=${INSTALL_DIR}
Restart=on-failure
RestartSec=30
StandardOutput=journal
StandardError=journal
SyslogIdentifier=citrainsight
Environment=PYTHONUNBUFFERED=1

[Install]
WantedBy=multi-user.target
SERVICEEOF

    systemctl daemon-reload
    systemctl enable "${SERVICE_NAME}"
    info "Service created and enabled"
}

start_service() {
    info "Starting ${SERVICE_NAME}…"
    systemctl start "${SERVICE_NAME}"

    # Brief pause to check status
    sleep 2

    if systemctl is-active --quiet "${SERVICE_NAME}"; then
        info "Service is running"
    else
        warn "Service may not have started correctly. Check: journalctl -u ${SERVICE_NAME}"
    fi
}

# ─────────────────────────────────────────────────────────────────────
# UNINSTALL
# ─────────────────────────────────────────────────────────────────────

uninstall() {
    info "Uninstalling CITRA Insight Agent…"

    systemctl stop "${SERVICE_NAME}" 2>/dev/null || true
    systemctl disable "${SERVICE_NAME}" 2>/dev/null || true

    rm -f "${SERVICE_FILE}"
    systemctl daemon-reload

    info "Service removed."
    info "Data directory preserved at ${INSTALL_DIR}"
    info "To remove all data: rm -rf ${INSTALL_DIR}"
}

# ─────────────────────────────────────────────────────────────────────
# MAIN
# ─────────────────────────────────────────────────────────────────────

usage() {
    echo "CITRA Insight Linux Agent Installer v${AGENT_VERSION}"
    echo ""
    echo "Usage: sudo bash $0 [command]"
    echo ""
    echo "Commands:"
    echo "  install     Install the agent (default)"
    echo "  uninstall   Remove the agent service"
    echo "  --help      Show this help"
}

main() {
    local cmd="${1:-install}"

    case "$cmd" in
        install)
            echo ""
            echo "╔══════════════════════════════════════════════╗"
            echo "║   CITRA Insight — Linux Agent Installer      ║"
            echo "║   v${AGENT_VERSION}                                    ║"
            echo "╚══════════════════════════════════════════════╝"
            echo ""

            check_root
            check_os
            check_systemd
            check_python

            create_directories
            install_agent_files
            install_dependencies
            create_config
            create_service
            start_service

            echo ""
            info "Installation complete!"
            echo ""
            echo "  Next steps:"
            echo "    1. Configure your server URL:"
            echo "       Edit ${INSTALL_DIR}/config.json"
            echo ""
            echo "    2. Set your API token:"
            echo "       sudo ${INSTALL_DIR}/venv/bin/python -c \\"
            echo "         \"from agent_linux.uploader import store_token; store_token('YOUR_TOKEN')\""
            echo ""
            echo "    3. Check status:"
            echo "       sudo systemctl status ${SERVICE_NAME}"
            echo ""
            echo "    4. View logs:"
            echo "       journalctl -u ${SERVICE_NAME} -f"
            echo ""
            ;;
        uninstall)
            check_root
            uninstall
            ;;
        --help|-h)
            usage
            ;;
        *)
            error "Unknown command: $cmd. Use --help for usage."
            ;;
    esac
}

main "$@"
