<?php

namespace FleekDash\Core;

/**
 * Debug Logger with Zero Performance Impact
 * Only activates when FleekDash debug override is enabled
 */
class DebugLogger
{
    /** @var bool|null Cached flag; null until first resolution */
    private static ?bool $debugStatusCache = null;

    private static bool $cacheChecked = false;

    /**
     * Default: do not hide PHP notices globally.
     */
    const HIDE_PHP_NOTICES_DEFAULT = false;

    /**
     * Initialize debug logging override (called once on plugins_loaded)
     * ZERO performance impact when debug is OFF
     */
    public static function init(): void
    {
        // Only check once per request
        if (self::$cacheChecked) {
            return;
        }

        self::$cacheChecked = true;

        // Fast check: if no override option exists, skip entirely
        $force_debug_option = \get_option('fleekdash_force_debug', null);
        if ($force_debug_option === false || $force_debug_option === null) {
            // No override set - zero performance impact
            self::$debugStatusCache = false;

            return;
        }

        // Only proceed if there's an actual override
        $override_result = self::shouldOverrideDebugLog();
        self::$debugStatusCache = $override_result['should_log'];

        if ($override_result['should_log']) {
            self::enableDebugLogging();
        } elseif ($override_result['force_disable']) {
            self::disableDebugLogging();
        }
    }

    /**
     * Apply site-wide masking of noisy PHP levels (see ErrorHandler).
     */
    private static function suppressPhpNotices(): void
    {
        if (\class_exists(ErrorHandler::class)) {
            ErrorHandler::applyGlobalReportingMask();
        }
    }

    /**
     * Check if PHP notices suppression is enabled
     */
    public static function isPhpNoticesSuppressed(): bool
    {
        $hide_notices = \get_option('fleekdash_hide_php_notices', self::HIDE_PHP_NOTICES_DEFAULT);

        if (is_string($hide_notices)) {
            return $hide_notices === '1' || $hide_notices === 'true';
        }

        return (bool) $hide_notices;
    }

    /**
     * Update PHP notices suppression setting
     *
     * @return bool Success status
     */
    public static function setPhpNoticesSuppression(bool $enabled): bool
    {
        $success = \update_option('fleekdash_hide_php_notices', $enabled ? '1' : '0');

        // Apply immediately if setting changed
        if ($success) {
            if ($enabled) {
                self::suppressPhpNotices();
            } else {
                self::restorePhpNotices();
            }

            // Clear error handler cache to apply new setting immediately
            if (\class_exists(ErrorHandler::class)) {
                ErrorHandler::clearCache();
            }
        }

        return $success;
    }

    /**
     * Restore PHP notices (stop suppressing them)
     */
    private static function restorePhpNotices(): void
    {
        if (\class_exists(ErrorHandler::class)) {
            ErrorHandler::restoreGlobalReportingMask();
        }
    }

    /**
     * Check if we should override debug logging
     * Only called when override option exists
     *
     * @return array{should_log: bool, force_disable: bool}
     */
    private static function shouldOverrideDebugLog(): array
    {
        $force_debug_option = \get_option('fleekdash_force_debug', null);

        // Convert to boolean (supports both string and numeric values)
        $force_debug = null;
        if (is_string($force_debug_option)) {
            $force_debug = $force_debug_option === '1' || $force_debug_option === 'true';
        } elseif (is_numeric($force_debug_option)) {
            $force_debug = (int) $force_debug_option === 1;
        } else {
            $force_debug = (bool) $force_debug_option;
        }

        // Return structured result indicating what action to take
        if ($force_debug === true) {
            // Force Debug ON - enable logging
            return [
                'should_log' => true,
                'force_disable' => false,
            ];
        }

        if ($force_debug === false) {
            // Force Debug OFF - actively disable logging
            return [
                'should_log' => false,
                'force_disable' => true,
            ];
        }

        // This shouldn't happen since we check for option existence first
        return [
            'should_log' => false,
            'force_disable' => false,
        ];
    }

    /**
     * Enable debug logging (only called when override is needed)
     */
    private static function enableDebugLogging(): void
    {
        // FIXED: Always ensure WP_DEBUG_LOG is true when Force Debug is active
        if (!defined('WP_DEBUG_LOG')) {
            define('WP_DEBUG_LOG', true);
        }

        // FIXED: Always ensure WP_DEBUG is true when Force Debug is active
        if (!defined('WP_DEBUG')) {
            define('WP_DEBUG', true);
        }

        // CRITICAL SECURITY FIX: Always disable WP_DEBUG_DISPLAY to prevent users seeing errors
        if (!defined('WP_DEBUG_DISPLAY')) {
            define('WP_DEBUG_DISPLAY', false);
        }

        // Ensure error logging is enabled for this request
        if (!ini_get('log_errors')) {
            ini_set('log_errors', 1);
        }

        // CRITICAL FIX: Always set log file to WordPress debug.log location
        $wp_debug_log = WP_CONTENT_DIR . '/debug.log';
        ini_set('error_log', $wp_debug_log);

        // Ensure the debug.log file exists and is writable
        if (!file_exists($wp_debug_log)) {
            // Create the file if it doesn't exist
            touch($wp_debug_log);
        }

        // Log the override activation (once per request)
        error_log('[FleekDash Debug Override] Debug logging enabled via FleekDash Force Debug - logs will be saved to wp-content/debug.log');
    }

    /**
     * Disable debug logging (called when Force Debug is OFF)
     */
    private static function disableDebugLogging(): void
    {
        // Log the override deactivation (before disabling)
        error_log('[FleekDash Debug Override] Debug logging disabled via FleekDash Force Debug OFF');

        // CRITICAL: Redirect error_log to a writable location instead of /dev/null
        // This avoids open_basedir restrictions while effectively disabling logging
        if (PHP_OS_FAMILY === 'Windows') {
            ini_set('error_log', 'NUL');
        } else {
            // Use a writable location within WordPress content directory
            $null_log = WP_CONTENT_DIR . '/fleekdash-null.log';
            ini_set('error_log', $null_log);

            // Ensure the file exists but is empty
            if (!file_exists($null_log)) {
                touch($null_log);
            }
            // Clear the file content to ensure it's empty
            file_put_contents($null_log, '');
        }

        // Also disable error logging
        ini_set('log_errors', 0);
    }

    /**
     * Check if debug logging is active (cached)
     * ZERO performance impact when debug is OFF
     */
    public static function isDebugLoggingActive(): bool
    {
        if (!self::$cacheChecked) {
            self::init();
        }

        return self::$debugStatusCache === true;
    }

    /**
     * Custom log function that respects FleekDash debug settings
     * Only logs when FleekDash debug is active
     */
    public static function log(string $message, string $level = 'INFO'): void
    {
        // Fast exit if debug not active (zero performance impact)
        if (!self::isDebugLoggingActive()) {
            return;
        }

        // Only proceed if debug is actually active
        $timestamp = date('Y-m-d H:i:s');
        $formatted_message = "[{$timestamp}] [FleekDash {$level}] {$message}";

        error_log($formatted_message);
    }

    /**
     * Log info message
     */
    public static function info(string $message): void
    {
        self::log($message, 'INFO');
    }

    /**
     * Log warning message
     */
    public static function warn(string $message): void
    {
        self::log($message, 'WARN');
    }

    /**
     * Log error message
     */
    public static function error(string $message): void
    {
        self::log($message, 'ERROR');
    }

    /**
     * Log debug message
     */
    public static function debug(string $message): void
    {
        self::log($message, 'DEBUG');
    }
}
// Note: Closing PHP tag intentionally omitted to prevent whitespace output issues
