#!/bin/bash
#
# glm - Gen Linux MDM CLI
#
# Usage: glm <command> [options]
#

set -euo pipefail

# Resolve script location
SCRIPT_PATH="$0"
[[ -L "$SCRIPT_PATH" ]] && SCRIPT_PATH=$(readlink -f "$SCRIPT_PATH")
BASE_DIR=$(dirname "$SCRIPT_PATH")
APP_DIR=$(realpath "${BASE_DIR}/..")

# Configuration
CONF_FILE="${APP_DIR}/conf/gen-mdm.conf"
PLUGIN_DIR="${APP_DIR}/plugins"
SERVICE_PREFIX="gen-mdm"

# Load configuration
[[ -f "$CONF_FILE" ]] && source "$CONF_FILE"

# Plugin support
declare -A PLUGIN_COMMANDS
declare -A PLUGIN_DESCRIPTIONS

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

#------------------------------------------------------------------------------
# Plugin System
#------------------------------------------------------------------------------

load_plugins() {
    [[ ! -d "$PLUGIN_DIR" ]] && return 0

    for plugin_path in "${PLUGIN_DIR}"/*; do
        [[ ! -d "$plugin_path" ]] && continue

        local plugin_name=$(basename "$plugin_path")
        local conf_file="${plugin_path}/plugin.conf"
        local commands_file="${plugin_path}/commands.sh"

        [[ ! -f "$conf_file" ]] || [[ ! -f "$commands_file" ]] && continue

        # Source plugin
        unset PLUGIN_NAME PLUGIN_VERSION PLUGIN_DESCRIPTION PLUGIN_CMDS
        source "$conf_file"

        [[ -z "${PLUGIN_NAME:-}" ]] && continue

        source "$commands_file"

        PLUGIN_COMMANDS["$PLUGIN_NAME"]="${PLUGIN_CMDS:-}"
        PLUGIN_DESCRIPTIONS["$PLUGIN_NAME"]="${PLUGIN_DESCRIPTION:-Plugin: $PLUGIN_NAME}"
    done
}

is_plugin_command() {
    [[ -n "${PLUGIN_COMMANDS[$1]:-}" ]]
}

execute_plugin_command() {
    local plugin_name="$1"
    shift

    local handler_func="${plugin_name}_command"
    if declare -f "$handler_func" > /dev/null; then
        "$handler_func" "$@"
    else
        echo -e "${RED}Error:${NC} Plugin '$plugin_name' not properly configured"
        return 1
    fi
}

#------------------------------------------------------------------------------
# Help
#------------------------------------------------------------------------------

show_help() {
    cat << EOF
Gen Linux MDM - Device Management CLI

Usage: glm <command> [options]

Commands:
  status          Show MDM service status
  logs            Show MDM logs from boot
  update          Run provisioning playbooks
    system        Run system playbooks only
    user [name]   Run user playbooks only

  compliance      Compliance operations
    check         Show compliance state (visual)
    report        Show compliance report (key-value)
    report-json   Show compliance report (JSON)
    sync          Force sync compliance to server

  enroll          Enroll device with MDM server
  environment     Switch MDM repository branch
  boot            Boot options (kernel, show, vars)
  version         Show MDM version

  start           Start MDM timers and task poller
  stop            Stop MDM timers and task poller
EOF

    # Show plugin commands
    if [[ ${#PLUGIN_COMMANDS[@]} -gt 0 ]]; then
        echo
        echo "Plugin commands:"
        for plugin in "${!PLUGIN_COMMANDS[@]}"; do
            printf "  %-14s %s\n" "$plugin" "${PLUGIN_DESCRIPTIONS[$plugin]}"
        done
    fi
    echo
}

show_help_environment() {
    local current_branch="main"
    [[ -f "${APP_DIR}/conf/branch" ]] && current_branch=$(cat "${APP_DIR}/conf/branch")

    cat << EOF
Switch MDM repository branch

Usage: glm environment [branch-name]

Current branch: ${current_branch}
EOF
}

#------------------------------------------------------------------------------
# Commands
#------------------------------------------------------------------------------

cmd_status() {
    systemctl status ${SERVICE_PREFIX}-provision.timer --no-pager || true
    echo
    systemctl status ${SERVICE_PREFIX}-compliance.timer --no-pager || true
    echo
    echo "--- Task Poller ---"
    systemctl status ${SERVICE_PREFIX}-tasks.service --no-pager 2>/dev/null || true
    echo
    local state_file="/run/gen-mdm/task-poller.state"
    if [[ -f "$state_file" ]]; then
        local EMPTY_STREAK=0 LAST_RUN_EPOCH=0 LAST_TASK_EPOCH=0 MODE=fast
        source "$state_file" 2>/dev/null || true
        local threshold="${MDM_TASK_BACKOFF_THRESHOLD:-7}"
        local last_run_fmt="never"
        if [[ "${LAST_RUN_EPOCH:-0}" -gt 0 ]]; then
            last_run_fmt=$(date -d "@${LAST_RUN_EPOCH}" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "@${LAST_RUN_EPOCH}")
        fi
        local last_task_fmt="never"
        if [[ "${LAST_TASK_EPOCH:-0}" -gt 0 ]]; then
            last_task_fmt=$(date -d "@${LAST_TASK_EPOCH}" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "@${LAST_TASK_EPOCH}")
        fi
        echo "  Mode:         ${MODE}"
        echo "  Empty streak: ${EMPTY_STREAK} / ${threshold}"
        echo "  Last poll:    ${last_run_fmt}"
        echo "  Last task:    ${last_task_fmt}"
        local next_info
        next_info=$(systemctl list-timers --all 2>/dev/null | \
            grep "gen-mdm-tasks.service" | awk '{print $1, $2, $3, $4}' | head -1 || true)
        [[ -n "$next_info" ]] && echo "  Next poll:    ${next_info}"
    else
        echo "  No state yet — poller has not run since boot"
    fi
}

cmd_logs() {
    journalctl -b -u ${SERVICE_PREFIX}-provision.service --no-pager
}

cmd_start() {
    sudo systemctl start ${SERVICE_PREFIX}-provision.timer
    sudo systemctl start ${SERVICE_PREFIX}-compliance.timer
    sudo systemd-run --on-active=5s --unit=${SERVICE_PREFIX}-tasks.service \
        --description="Gen MDM task poller (manual start)" 2>/dev/null || true
    echo -e "${GREEN}MDM timers started${NC}"
}

cmd_stop() {
    sudo systemctl stop ${SERVICE_PREFIX}-provision.timer
    sudo systemctl stop ${SERVICE_PREFIX}-compliance.timer
    sudo systemctl stop ${SERVICE_PREFIX}-tasks.service 2>/dev/null || true
    local pending_timer
    pending_timer=$(systemctl list-timers --all 2>/dev/null | \
        grep "${SERVICE_PREFIX}-tasks.service" | grep -oE '[^[:space:]]+\.timer' | head -1 || true)
    [[ -n "$pending_timer" ]] && sudo systemctl stop "$pending_timer" 2>/dev/null || true
    echo -e "${YELLOW}MDM timers stopped${NC}"
}

cmd_update() {
    local category="${1:-all}"
    local user="${2:-}"

    case "$category" in
        system)
            echo "Running system playbooks..."
            sudo "${APP_DIR}/bin/ansible-runner" --category=system
            ;;
        user)
            if [[ -n "$user" ]]; then
                echo "Running user playbooks for: $user"
                sudo "${APP_DIR}/bin/ansible-runner" --category=user --user="$user"
            else
                echo "Running user playbooks for all users..."
                sudo "${APP_DIR}/bin/ansible-runner" --category=user
            fi
            ;;
        all|*)
            echo "Running all playbooks..."
            sudo "${APP_DIR}/bin/ansible-runner" --category=system
            sudo "${APP_DIR}/bin/ansible-runner" --category=user
            ;;
    esac
}

cmd_compliance() {
    local action="${1:-check}"

    case "$action" in
        check)
            echo "Checking compliance state..."
            sudo "${APP_DIR}/tooling/compliance.sh" check
            ;;
        report)
            sudo "${APP_DIR}/tooling/compliance.sh" report
            ;;
        report-json)
            sudo "${APP_DIR}/tooling/compliance.sh" report-json
            ;;
        sync)
            echo "Syncing compliance report..."
            sudo "${APP_DIR}/tooling/compliance.sh" sync
            ;;
        *)
            echo -e "${RED}Unknown compliance action:${NC} $action"
            echo "Available: check, report, report-json, sync"
            return 1
            ;;
    esac
}

cmd_enroll() {
    if [[ -f "${APP_DIR}/tooling/enroll.sh" ]]; then
        sudo "${APP_DIR}/tooling/enroll.sh"
    else
        echo -e "${RED}Error:${NC} Enrollment script not found"
        return 1
    fi
}

cmd_environment() {
    local new_branch="${1:-}"

    if [[ -z "$new_branch" ]]; then
        show_help_environment
        return 0
    fi

    echo "$new_branch" | sudo tee "${APP_DIR}/conf/branch" > /dev/null
    echo -e "${GREEN}Switched to branch:${NC} $new_branch"
    echo "Run 'glm update' to apply changes"
}

cmd_boot() {
    local action="${1:-}"

    case "$action" in
        show)
            echo "Boot options:"
            cat /boot/grub/grub.cfg /boot/grub/custom.cfg 2>/dev/null | \
                awk -F\' '$1=="menuentry " || $1=="submenu " {print i++ " : " $2}; /\tmenuentry / {print "" i-1">"j++ " : " $2};'
            ;;
        vars)
            echo "GRUB environment:"
            grub-editenv list
            ;;
        kernel)
            echo "Requested kernel:"
            if [[ -f /var/eus/mdm/vars/common.yaml ]]; then
                grep KERNEL_VERSION /var/eus/mdm/vars/common.yaml || echo "Not specified"
            else
                echo "Config not found. Run 'glm update' first."
            fi
            ;;
        *)
            echo "Boot subcommands: show, vars, kernel"
            ;;
    esac
}

cmd_version() {
    if [[ -f "${APP_DIR}/version" ]]; then
        cat "${APP_DIR}/version"
    else
        echo "unknown"
    fi
}

#------------------------------------------------------------------------------
# Main
#------------------------------------------------------------------------------

# Load plugins
load_plugins

# No arguments - show help
if [[ $# -eq 0 ]]; then
    show_help
    exit 0
fi

# Process command
command="$1"
shift

case "$command" in
    status)
        cmd_status
        ;;
    logs)
        cmd_logs
        ;;
    start)
        cmd_start
        ;;
    stop)
        cmd_stop
        ;;
    update)
        cmd_update "$@"
        ;;
    compliance)
        cmd_compliance "$@"
        ;;
    enroll)
        cmd_enroll
        ;;
    environment)
        cmd_environment "$@"
        ;;
    boot)
        cmd_boot "$@"
        ;;
    version)
        cmd_version
        ;;
    help|--help|-h)
        show_help
        ;;
    *)
        # Check for plugin command
        if is_plugin_command "$command"; then
            execute_plugin_command "$command" "$@"
        else
            echo -e "${RED}Unknown command:${NC} $command"
            echo
            show_help
            exit 1
        fi
        ;;
esac