#!/usr/bin/env bash
# -*- coding:Utf-8; -*
# SPDX-FileCopyrightText: 2024-2026 Medulla / Natsu, http://www.medulla-tech.io
# SPDX-License-Identifier: GPL-3.0-or-later

# File name: check_itsm_access.sh
# Download URL: https://dl.medulla-tech.io/nc/check_itsm_access.sh

set -euo pipefail

# Configuration
readonly CONFIG_FILE="/etc/mmc/plugins/glpi.ini.local"
readonly ADMIN_CONFIG_FILE="/etc/mmc/plugins/admin.ini.local"
readonly REQUIRED_TABLES=(glpi_computers glpi_users glpi_profiles glpi_entities glpi_groups glpi_softwares glpi_networkports glpi_printers glpi_monitors glpi_peripherals glpi_tickets glpi_changes glpi_problems glpi_projects glpi_locations glpi_plugin_glpiinventory_collects)
readonly REQUIRED_VIEWS=(glpi_computers_pulse glpi_view_computers_items_printer glpi_view_computers_items_peripheral glpi_view_peripherals_manufacturers)
readonly timeout=10

# Track results
FAILED_CHECKS=0
PASSED_CHECKS=0

# Helper functions
log_info() {
    echo "[=] $*"
}

log_success() {
    echo "[✓] $*" >&2
}

log_error() {
    echo "[✗] $*" >&2
}

log_warning() {
    echo "[!] $*"
}

check_prerequisites() {
    local missing_tools=()
    
    for tool in crudini mysql curl; do
        if ! command -v "$tool" &> /dev/null; then
            missing_tools+=("$tool")
        fi
    done
    
    if [[ ${#missing_tools[@]} -gt 0 ]]; then
        log_error "Missing required tools: ${missing_tools[*]}"
        return 1
    fi
    
    if [[ ! -f "$CONFIG_FILE" ]]; then
        log_error "Configuration file not found: $CONFIG_FILE"
        return 1
    fi
    
    if [[ ! -r "$CONFIG_FILE" ]]; then
        log_error "Configuration file is not readable: $CONFIG_FILE"
        return 1
    fi
    
    return 0
}

load_database_config() {
    log_info "Loading ITSM database configuration from $CONFIG_FILE"
    
    ITSM_DBHOST=$(crudini --get "$CONFIG_FILE" main dbhost 2>/dev/null || echo "")
    ITSM_DBPORT=$(crudini --get "$CONFIG_FILE" main dbport 2>/dev/null || echo "")
    ITSM_DBUSER=$(crudini --get "$CONFIG_FILE" main dbuser 2>/dev/null || echo "")
    ITSM_DBPASSWD=$(crudini --get "$CONFIG_FILE" main dbpasswd 2>/dev/null || echo "")
    ITSM_DBNAME=$(crudini --get "$CONFIG_FILE" main dbname 2>/dev/null || echo "")
    
    # Validate that all required parameters were loaded
    if [[ -z "$ITSM_DBUSER" ]] || [[ -z "$ITSM_DBHOST" ]] || [[ -z "$ITSM_DBNAME" ]]; then
        log_error "Failed to load database configuration. Missing required parameters."
        return 1
    fi
    
    # Set default port if not specified
    ITSM_DBPORT="${ITSM_DBPORT:-3306}"
    
    return 0
}

load_api_config() {
    log_info "Loading ITSM API configuration"
    
    ITSM_API_URL=$(crudini --get "$CONFIG_FILE" webservices glpi_base_url 2>/dev/null || echo "")
    ITSM_API_USER=$(crudini --get "$CONFIG_FILE" webservices glpi_username 2>/dev/null || echo "")
    ITSM_API_PASSWORD=$(crudini --get "$CONFIG_FILE" webservices glpi_password 2>/dev/null || echo "")

    ADMIN_DBHOST=$(crudini --get "$ADMIN_CONFIG_FILE" main dbhost 2>/dev/null || echo "")
    ADMIN_DBPORT=$(crudini --get "$ADMIN_CONFIG_FILE" main dbport 2>/dev/null || echo "")
    ADMIN_DBUSER=$(crudini --get "$ADMIN_CONFIG_FILE" main dbuser 2>/dev/null || echo "")
    ADMIN_DBPASSWD=$(crudini --get "$ADMIN_CONFIG_FILE" main dbpasswd 2>/dev/null || echo "")
    ADMIN_DBNAME='admin'

    ITSM_APP_TOKEN=$(mysql -h "$ADMIN_DBHOST" -P "$ADMIN_DBPORT" -u "$ADMIN_DBUSER" ${ADMIN_DBPASSWD:+-p"$ADMIN_DBPASSWD"} "$ADMIN_DBNAME" \
        -sse "SELECT setting_value FROM saas_application WHERE setting_name='glpi_mmc_app_token'" 2>/dev/null || echo "")
    ITSM_USER_TOKEN=$(mysql -h "$ADMIN_DBHOST" -P "$ADMIN_DBPORT" -u "$ADMIN_DBUSER" ${ADMIN_DBPASSWD:+-p"$ADMIN_DBPASSWD"} "$ADMIN_DBNAME" \
        -sse "SELECT setting_value FROM saas_application WHERE setting_name='glpi_root_user_token'" 2>/dev/null || echo "")
}

test_database_connection() {
    log_info "Testing database connection..."
    
    if mysql -h "$ITSM_DBHOST" -P "$ITSM_DBPORT" -u "$ITSM_DBUSER" \
        ${ITSM_DBPASSWD:+-p"$ITSM_DBPASSWD"} "$ITSM_DBNAME" \
        -e "SELECT 1" &> /dev/null; then
        log_success "Database connection successful"
        ((PASSED_CHECKS++))
        return 0
    else
        log_error "Failed to connect to database"
        ((FAILED_CHECKS++))
        return 1
    fi
}

check_tables() {
    log_info "Checking for required tables..."
    
    local missing_tables=()
    
    for table in "${REQUIRED_TABLES[@]}"; do
        if ! mysql -h "$ITSM_DBHOST" -P "$ITSM_DBPORT" -u "$ITSM_DBUSER" \
            ${ITSM_DBPASSWD:+-p"$ITSM_DBPASSWD"} "$ITSM_DBNAME" \
            -e "SHOW TABLES LIKE '$table'" 2>/dev/null | grep -q "$table"; then
            missing_tables+=("$table")
        fi
    done
    
    if [[ ${#missing_tables[@]} -eq 0 ]]; then
        log_success "All ${#REQUIRED_TABLES[@]} required tables found"
        ((PASSED_CHECKS++))
        return 0
    else
        log_error "Missing tables: ${missing_tables[*]}"
        ((FAILED_CHECKS++))
        return 1
    fi
}

check_views() {
    log_info "Checking for required views..."
    
    local missing_views=()
    
    for view in "${REQUIRED_VIEWS[@]}"; do
        if ! mysql -h "$ITSM_DBHOST" -P "$ITSM_DBPORT" -u "$ITSM_DBUSER" \
            ${ITSM_DBPASSWD:+-p"$ITSM_DBPASSWD"} "$ITSM_DBNAME" \
            -e "SHOW FULL TABLES WHERE TABLE_TYPE='VIEW' AND Tables_in_$ITSM_DBNAME='$view'" 2>/dev/null | grep -q "$view"; then
            missing_views+=("$view")
        fi
    done
    
    if [[ ${#missing_views[@]} -eq 0 ]]; then
        log_success "All ${#REQUIRED_VIEWS[@]} required views found"
        ((PASSED_CHECKS++))
        return 0
    else
        log_error "Missing views: ${missing_views[*]}"
        ((FAILED_CHECKS++))
        return 1
    fi
}

test_basic_api_connectivity() {
    local api_url="$1"
    
    log_info "Testing basic connectivity to API server..."
    
    if curl -s -m "$timeout" -o /dev/null -w "%{http_code}" "$api_url" 2>/dev/null | grep -qE "^[1234]"; then
        log_success "API server reachable at $api_url"
        ((PASSED_CHECKS++))
        return 0
    else
        log_error "Cannot reach API server at $api_url"
        ((FAILED_CHECKS++))
        return 1
    fi
}

test_api_credential_auth() {
    local api_url="$1"
    local username="$2"
    local password="$3"
    local app_token="$4"
    
    log_info "Testing API authentication with user credentials..."
    local endpoint="${api_url%/}/initSession"
    local http_code
    
    http_code=$(curl -s -m "$timeout" -u "$username:$password" \
        -H "App-Token: $app_token" \
        -o /dev/null -w "%{http_code}" \
        "$endpoint" 2>/dev/null)
    
    if [[ "$http_code" == "200" ]]; then
        log_success "Credential authentication successful"
        ((PASSED_CHECKS++))
        return 0
    else
        log_error "Credential auth failed with HTTP status $http_code"
        log_error "To troubleshoot from the Medulla server, run:"
        log_error "curl -u $username:***PASSWORD*** -H \"App-Token: $app_token\" $endpoint"
        ((FAILED_CHECKS++))
        return 1
    fi
}

test_api_token_auth() {
    local api_url="$1"
    local user_token="$2"
    local app_token="$3"
    
    local endpoint="${api_url%/}/initSession?get_full_session=true"
    local http_code
    
    http_code=$(curl -s -m "$timeout" \
        -H "App-Token: $app_token" \
        -H "Authorization: user_token $user_token" \
        -o /dev/null -w "%{http_code}" \
        "$endpoint" 2>/dev/null)
    
    if [[ "$http_code" == "200" ]]; then
        log_success "Token authentication successful"
        ((PASSED_CHECKS++))
        return 0
    else
        log_error "Token auth failed with HTTP status $http_code"
        log_error "To troubleshoot from the Medulla server, run:"
        log_error "curl -H \"App-Token: $app_token\" -H \"Authorization: user_token ***TOKEN***\" $endpoint"
        ((FAILED_CHECKS++))
        return 1
    fi
}


main() {
    echo "=========================================="
    echo "ITSM Database Access Check"
    echo "=========================================="
    echo ""
    
    if ! check_prerequisites; then
        return 1
    fi
    
    if ! load_database_config; then
        return 1
    fi
    
    if ! test_database_connection; then
        echo ""
        echo "=========================================="
        echo "Database connectivity check failed!"
        echo "=========================================="
        return 1
    fi
    
    check_tables || true
    check_views || true
    

    echo ""
    echo "=========================================="
    echo "ITSM API Access Check"
    echo "=========================================="
    echo ""
    
    if ! load_api_config; then
        return 1
    fi
    
    if ! test_basic_api_connectivity "$ITSM_API_URL"; then
        echo ""
        echo "=========================================="
        echo "API connectivity check failed!"
        echo "=========================================="
        return 1
    fi
    
    test_api_credential_auth "$ITSM_API_URL" "$ITSM_API_USER" "$ITSM_API_PASSWORD" "$ITSM_APP_TOKEN" || true
    test_api_token_auth "$ITSM_API_URL" "$ITSM_USER_TOKEN" "$ITSM_APP_TOKEN" || true
    
    
    echo ""
    echo "=========================================="
    if [[ $FAILED_CHECKS -eq 0 ]]; then
        echo "All checks passed! ($PASSED_CHECKS checks)"
        echo "=========================================="
        return 0
    else
        echo "Some checks failed! (Failed: $FAILED_CHECKS, Passed: $PASSED_CHECKS)"
        echo "=========================================="
        return 1
    fi
}

main "$@"
