#!/bin/bash

################################################################################
# PHP Detector Library
# Part of Server Toolkit - PHP & Server Optimizer
#
# Purpose: Detect all PHP configurations, pools, versions, and settings
# Author: Server Toolkit Team
# Dependencies: system-detect.sh, user-manager.sh
################################################################################

# Source dependencies (if not already loaded)
if [ -z "$SYS_CONTROL_PANEL" ]; then
    _LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
    source "$_LIB_DIR/lib/system-detect.sh" 2>/dev/null
    source "$_LIB_DIR/lib/user-manager.sh" 2>/dev/null
fi

################################################################################
# PHP Version Detection
################################################################################

# Detect all installed PHP versions on the system
detect_installed_php_versions() {
    local -a php_versions=()

    # cPanel EA-PHP
    if [ -d "/opt/cpanel" ]; then
        while IFS= read -r dir; do
            local version=$(basename "$dir" | sed 's/ea-php//')
            php_versions+=("ea-php$version")
        done < <(find /opt/cpanel -maxdepth 1 -type d -name "ea-php*" 2>/dev/null | sort)
    fi

    # CloudLinux Alt-PHP
    if [ -d "/opt/alt" ]; then
        while IFS= read -r dir; do
            local version=$(basename "$dir" | sed 's/php//')
            php_versions+=("alt-php$version")
        done < <(find /opt/alt -maxdepth 1 -type d -name "php*" 2>/dev/null | grep -E "php[0-9]" | sort)
    fi

    # Plesk PHP
    if [ -d "/opt/plesk/php" ]; then
        while IFS= read -r dir; do
            local version=$(basename "$dir")
            php_versions+=("plesk-php$version")
        done < <(find /opt/plesk/php -maxdepth 1 -type d -name "[0-9]*" 2>/dev/null | sort)
    fi

    # System PHP
    if command -v php &>/dev/null; then
        local sys_version=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;' 2>/dev/null)
        [ -n "$sys_version" ] && php_versions+=("system-php$sys_version")
    fi

    # Return array
    printf '%s\n' "${php_versions[@]}"
}

# Get PHP version for a specific domain/user
detect_php_version_for_domain() {
    local username="$1"
    local domain="$2"

    case "$SYS_CONTROL_PANEL" in
        cpanel)
            # Check userdata for PHP version
            local userdata_file="${SYS_CPANEL_USERDATA_DIR:-/var/cpanel/userdata}/$username/$domain"
            if [ -f "$userdata_file" ]; then
                local php_ver=$(grep "phpversion:" -- "$userdata_file" | awk '{print $2}' | tr -d "'\"")
                echo "$php_ver"
                return 0
            fi

            # Fallback: Check FPM pool config
            local pool_config=$(find /opt/cpanel/ea-php*/root/etc/php-fpm.d/ -name "$username.conf" 2>/dev/null | head -1)
            if [ -n "$pool_config" ]; then
                local php_path=$(dirname "$(dirname "$(dirname "$pool_config")")")
                basename "$php_path"
                return 0
            fi
            ;;

        plesk)
            # Query Plesk database
            if command -v plesk &>/dev/null; then
                plesk bin site -i "$domain" 2>/dev/null | grep "PHP version" | awk '{print $NF}'
                return 0
            fi
            ;;

        interworx)
            # Check SiteWorx config
            local domain_conf="/home/$username/var/$domain/siteworx.conf"
            if [ -f "$domain_conf" ]; then
                grep "php_version" "$domain_conf" | cut -d'=' -f2
                return 0
            fi
            ;;
    esac

    # Fallback: Try to execute PHP as user
    su -s /bin/bash "$username" -c "php -r 'echo PHP_MAJOR_VERSION.\".\".PHP_MINOR_VERSION;'" 2>/dev/null
}

################################################################################
# PHP Configuration File Detection
################################################################################

# Find ALL php.ini files affecting a domain (in priority order)
find_all_php_configs() {
    local username="$1"
    local domain="$2"
    local php_version="${3:-}"  # Optional: e.g., "82" or "8.2" or "ea-php82"

    declare -a config_files=()

    # Normalize PHP version format
    local php_ver_short=$(echo "$php_version" | grep -oE '[0-9]+' | head -c2)
    local php_ver_dot="${php_ver_short:0:1}.${php_ver_short:1}"

    # PRIORITY 1: Per-Directory .user.ini files
    if [ -d "/home/$username" ]; then
        while IFS= read -r file; do
            config_files+=("P1|$file|.user.ini")
        done < <(find "/home/$username" -name ".user.ini" -type f 2>/dev/null)
    fi

    # Check Plesk domain root
    if [ -d "/var/www/vhosts/$domain" ]; then
        while IFS= read -r file; do
            config_files+=("P1|$file|.user.ini")
        done < <(find "/var/www/vhosts/$domain" -name ".user.ini" -type f 2>/dev/null)
    fi

    # PRIORITY 2: User-Specific php.ini files
    local user_configs=(
        "/home/$username/public_html/php.ini"
        "/home/$username/php.ini"
        "/home/$username/.php/$php_ver_dot/php.ini"
        "/home/$username/.php/$php_ver_short/php.ini"
        "/home/$username/etc/php.ini"
        "/home/$username/etc/php$php_ver_short/php.ini"
        "/home/$username/var/$domain/etc/php.ini"  # InterWorx
        "/var/www/vhosts/system/$domain/etc/php.ini"  # Plesk
    )

    for config in "${user_configs[@]}"; do
        [ -f "$config" ] && config_files+=("P2|$config|user php.ini")
    done

    # PRIORITY 3: Pool/Version-Specific php.ini
    if [ -n "$php_ver_short" ]; then
        # cPanel EA-PHP
        local cpanel_ini="/opt/cpanel/ea-php${php_ver_short}/root/etc/php.ini"
        [ -f "$cpanel_ini" ] && config_files+=("P3|$cpanel_ini|pool php.ini")

        # cPanel EA-PHP additional .ini files
        if [ -d "/opt/cpanel/ea-php${php_ver_short}/root/etc/php.d" ]; then
            while IFS= read -r file; do
                config_files+=("P3|$file|pool php.d")
            done < <(find "/opt/cpanel/ea-php${php_ver_short}/root/etc/php.d" -name "*.ini" -type f 2>/dev/null | sort)
        fi

        # CloudLinux Alt-PHP
        local alt_ini="/opt/alt/php${php_ver_short}/etc/php.ini"
        [ -f "$alt_ini" ] && config_files+=("P3|$alt_ini|alt-php ini")

        # Plesk PHP
        local plesk_ini="/opt/plesk/php/$php_ver_dot/etc/php.ini"
        [ -f "$plesk_ini" ] && config_files+=("P3|$plesk_ini|plesk php.ini")
    fi

    # PRIORITY 4: System-Wide
    [ -f "/etc/php.ini" ] && config_files+=("P4|/etc/php.ini|system php.ini")

    # Return the array (priority|path|description)
    printf '%s\n' "${config_files[@]}"
}

# Get effective value of a PHP setting for a specific user
get_effective_php_setting() {
    local username="$1"
    local setting="$2"

    # Query PHP directly as the user (most accurate!)
    su -s /bin/bash "$username" -c "php -r 'echo ini_get(\"$setting\");'" 2>/dev/null
}

# Get all effective PHP settings for a user
get_all_php_settings() {
    local username="$1"

    # Get all settings in parseable format
    su -s /bin/bash "$username" -c "php -r 'foreach(ini_get_all() as \$k=>\$v) { echo \$k.\"=\".\$v[\"local_value\"].\"\\n\"; }'" 2>/dev/null
}

################################################################################
# PHP-FPM Pool Detection
################################################################################

# Find PHP-FPM pool configuration for a user/domain
find_fpm_pool_config() {
    local username="$1"
    local domain="$2"
    local php_version="${3:-}"

    local pool_config=""

    # cPanel EA-PHP pools - search username FIRST (this is how cPanel works!)
    if [ -n "$php_version" ]; then
        # Try username-based config (most common)
        pool_config="/opt/cpanel/$php_version/root/etc/php-fpm.d/$username.conf"
        [ -f "$pool_config" ] && echo "$pool_config" && return 0

        # Try domain-based config (rare, but possible)
        if [ -n "$domain" ]; then
            pool_config="/opt/cpanel/$php_version/root/etc/php-fpm.d/$domain.conf"
            [ -f "$pool_config" ] && echo "$pool_config" && return 0
        fi
    fi

    # Search all EA-PHP versions - try username FIRST, then domain
    pool_config=$(find /opt/cpanel/ea-php*/root/etc/php-fpm.d/ -name "$username.conf" 2>/dev/null | head -1)
    [ -n "$pool_config" ] && echo "$pool_config" && return 0

    if [ -n "$domain" ]; then
        pool_config=$(find /opt/cpanel/ea-php*/root/etc/php-fpm.d/ -name "$domain.conf" 2>/dev/null | head -1)
        [ -n "$pool_config" ] && echo "$pool_config" && return 0
    fi

    # Plesk pools
    if [ -n "$domain" ]; then
        pool_config="/etc/php-fpm.d/plesk-php*-fpm/$domain.conf"
        [ -f "$pool_config" ] && echo "$pool_config" && return 0
    fi

    # InterWorx pools
    if [ -n "$domain" ]; then
        pool_config="/home/$username/var/$domain/php-fpm.conf"
        [ -f "$pool_config" ] && echo "$pool_config" && return 0
    fi

    return 1
}

# Parse PHP-FPM pool config and extract all settings
parse_fpm_pool_config() {
    local pool_config="$1"

    [ ! -f "$pool_config" ] && return 1

    # Extract key settings
    local pm=$(grep "^pm\s*=" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
    local max_children=$(grep "^pm.max_children" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
    local start_servers=$(grep "^pm.start_servers" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
    local min_spare=$(grep "^pm.min_spare_servers" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
    local max_spare=$(grep "^pm.max_spare_servers" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
    local max_requests=$(grep "^pm.max_requests" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
    local idle_timeout=$(grep "^pm.process_idle_timeout" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
    local request_terminate=$(grep "^request_terminate_timeout" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
    local slowlog_timeout=$(grep "^request_slowlog_timeout" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')

    # Output in key=value format
    echo "pm=$pm"
    echo "pm.max_children=$max_children"
    echo "pm.start_servers=$start_servers"
    echo "pm.min_spare_servers=$min_spare"
    echo "pm.max_spare_servers=$max_spare"
    echo "pm.max_requests=$max_requests"
    echo "pm.process_idle_timeout=$idle_timeout"
    echo "request_terminate_timeout=$request_terminate"
    echo "request_slowlog_timeout=$slowlog_timeout"
}

# Get current FPM process count for a pool
get_fpm_process_count() {
    [ -z "$1" ] && return 1
    local pool_name="$1"  # Usually username or domain

    local count=$(ps aux | grep -E "php-fpm.*pool\s+${pool_name}" | grep -v grep | wc -l || echo 0)
    echo "$count"
}

# Get memory usage per FPM process for a pool
get_fpm_memory_usage() {
    [ -z "$1" ] && return 1
    local pool_name="$1"

    # Get average memory per process (in KB)
    ps aux | grep -E "php-fpm.*pool\s+${pool_name}" | grep -v grep | awk '{sum+=$6; count++} END {if(count>0) print int(sum/count); else print 0}'
}

################################################################################
# PHP Log File Detection
################################################################################

# Find PHP error logs for a user/domain
find_php_error_logs() {
    local username="$1"
    local domain="$2"

    declare -a log_files=()

    # Common error log locations
    local possible_logs=(
        "/home/$username/logs/error_log"
        "/home/$username/public_html/error_log"
        "/home/$username/logs/$domain.error_log"
        "/var/www/vhosts/$domain/logs/error_log"
        "/home/$username/var/$domain/logs/error_log"
    )

    for log in "${possible_logs[@]}"; do
        [ -f "$log" ] && log_files+=("$log")
    done

    printf '%s\n' "${log_files[@]}"
}

# Find PHP-FPM error logs
find_fpm_error_logs() {
    local username="$1"
    local php_version="${2:-}"

    declare -a log_files=()

    if [ -n "$php_version" ]; then
        # Specific version
        log_files+=("/opt/cpanel/$php_version/root/usr/var/log/php-fpm/$username-error.log")
    else
        # All versions
        while IFS= read -r log; do
            log_files+=("$log")
        done < <(find /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/ -name "$username-error.log" 2>/dev/null)
    fi

    printf '%s\n' "${log_files[@]}"
}

# Find PHP-FPM slow logs
find_fpm_slow_logs() {
    local username="$1"
    local php_version="${2:-}"

    declare -a log_files=()

    if [ -n "$php_version" ]; then
        log_files+=("/opt/cpanel/$php_version/root/usr/var/log/php-fpm/$username-slow.log")
    else
        while IFS= read -r log; do
            log_files+=("$log")
        done < <(find /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/ -name "$username-slow.log" 2>/dev/null)
    fi

    printf '%s\n' "${log_files[@]}"
}

################################################################################
# OPcache Detection
################################################################################

# Check if OPcache is enabled for a user
check_opcache_enabled() {
    local username="$1"

    su -s /bin/bash "$username" -c "php -r 'echo (function_exists(\"opcache_get_status\") && opcache_get_status() !== false) ? \"1\" : \"0\";'" 2>/dev/null
}

# Get OPcache statistics for a user
get_opcache_stats() {
    local username="$1"

    su -s /bin/bash "$username" -c "php -r 'if(function_exists(\"opcache_get_status\")) { \$s=opcache_get_status(); echo \"enabled=\".(\$s!==false?1:0).\"\\n\"; if(\$s) { echo \"memory_used=\".\$s[\"memory_usage\"][\"used_memory\"].\"\\n\"; echo \"memory_free=\".\$s[\"memory_usage\"][\"free_memory\"].\"\\n\"; echo \"memory_wasted=\".\$s[\"memory_usage\"][\"wasted_memory\"].\"\\n\"; echo \"num_cached_scripts=\".\$s[\"opcache_statistics\"][\"num_cached_scripts\"].\"\\n\"; echo \"max_cached_scripts=\".\$s[\"opcache_statistics\"][\"max_cached_scripts\"].\"\\n\"; echo \"hits=\".\$s[\"opcache_statistics\"][\"hits\"].\"\\n\"; echo \"misses=\".\$s[\"opcache_statistics\"][\"misses\"].\"\\n\"; } }'" 2>/dev/null
}

# Calculate OPcache hit rate
calculate_opcache_hit_rate() {
    local username="$1"

    local stats=$(get_opcache_stats "$username")
    [ -z "$stats" ] && echo "0" && return 1

    local hits=$(echo "$stats" | grep "^hits=" | cut -d'=' -f2)
    local misses=$(echo "$stats" | grep "^misses=" | cut -d'=' -f2)

    [ -z "$hits" ] || [ -z "$misses" ] && echo "0" && return 1
    [ "$hits" -eq 0 ] && [ "$misses" -eq 0 ] && echo "0" && return 1

    local total=$((hits + misses))
    local hit_rate=$((hits * 100 / total))

    echo "$hit_rate"
}

################################################################################
# Helper Functions
################################################################################

# Check if PHP-FPM is in use (vs mod_php)
is_using_php_fpm() {
    # Check if any PHP-FPM processes are running
    pgrep php-fpm &>/dev/null && return 0
    return 1
}

# Get PHP binary path for a specific version
get_php_binary_path() {
    local php_version="$1"

    case "$php_version" in
        ea-php*)
            echo "/opt/cpanel/$php_version/root/usr/bin/php"
            ;;
        alt-php*)
            local ver=$(echo "$php_version" | sed 's/alt-php//')
            echo "/opt/alt/php$ver/usr/bin/php"
            ;;
        plesk-php*)
            local ver=$(echo "$php_version" | sed 's/plesk-php//')
            echo "/opt/plesk/php/$ver/bin/php"
            ;;
        *)
            which php
            ;;
    esac
}

# Export all functions
export -f detect_installed_php_versions
export -f detect_php_version_for_domain
export -f find_all_php_configs
export -f get_effective_php_setting
export -f get_all_php_settings
export -f find_fpm_pool_config
export -f parse_fpm_pool_config
export -f get_fpm_process_count
export -f get_fpm_memory_usage
export -f find_php_error_logs
export -f find_fpm_error_logs
export -f find_fpm_slow_logs
export -f check_opcache_enabled
export -f get_opcache_stats
export -f calculate_opcache_hit_rate
export -f is_using_php_fpm
export -f get_php_binary_path
