<?php
namespace WalletUpPro\Core\Debug;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Diagnostic tracer for Content-Security-Policy headers.
 *
 * Activated by `?walletup_csp_debug=1` query param OR `WALLETUP_CSP_DEBUG` constant.
 * Snapshots `headers_list()` at every major WP lifecycle hook so we can pinpoint
 * the exact moment a CSP header enters the response — and whether it ever does
 * via PHP at all (if not, the header is added by the web server or CDN downstream).
 *
 * Output: `wp-content/walletup-csp-trace.log` plus an HTML comment in the page footer.
 */
class CSPTracer
{
    private static array $snapshots = [];
    private static bool $active = false;

    public static function maybeBoot(): void
    {
        $param = '';
        if (isset($_GET['walletup_csp_debug'])) {
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only diagnostic toggle
            $param = sanitize_text_field(wp_unslash($_GET['walletup_csp_debug']));
        }
        if ($param === '' && !defined('WALLETUP_CSP_DEBUG')) {
            return;
        }
        self::$active = true;
        self::snapshot('boot');

        $hooks = [
            'plugins_loaded',
            'setup_theme',
            'after_setup_theme',
            'init',
            'wp_loaded',
            'parse_request',
            'wp',
            'send_headers',
            'template_redirect',
        ];
        foreach ($hooks as $hook) {
            add_action($hook, function () use ($hook) {
                self::snapshot($hook . ':early');
            }, -99999);
            add_action($hook, function () use ($hook) {
                self::snapshot($hook . ':late');
            }, 99999);
        }

        add_action('wp_head', function () { self::snapshot('wp_head:early'); }, -99999);
        add_action('wp_head', function () { self::snapshot('wp_head:late'); }, 99999);
        add_action('wp_footer', function () {
            self::snapshot('wp_footer:late');
            self::emitHtml();
        }, 99999);

        if (function_exists('header_register_callback')) {
            @header_register_callback(function () {
                self::snapshot('header_register_callback');
                self::flush();
            });
        }
        register_shutdown_function([self::class, 'shutdownHandler']);
    }

    public static function shutdownHandler(): void
    {
        self::snapshot('shutdown');
        self::flush();
    }

    private static function snapshot(string $stage): void
    {
        $cspLines = [];
        $allHeaders = function_exists('headers_list') ? headers_list() : [];
        foreach ($allHeaders as $h) {
            if (stripos($h, 'Content-Security-Policy') === 0) {
                $cspLines[] = $h;
            }
        }
        $reqStart = $_SERVER['REQUEST_TIME_FLOAT'] ?? microtime(true);
        self::$snapshots[] = [
            'stage'   => $stage,
            'time_us' => (int) round((microtime(true) - $reqStart) * 1e6),
            'csp'     => $cspLines,
            'hdrs'    => count($allHeaders),
        ];
    }

    public static function flush(): void
    {
        if (!self::$active) {
            return;
        }
        static $done = false;
        if ($done) {
            return;
        }
        $done = true;

        $lines = self::buildLines();
        $logFile = (defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR : ABSPATH . 'wp-content') . '/walletup-csp-trace.log';
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents -- diagnostic log
        @file_put_contents($logFile, implode(PHP_EOL, $lines) . PHP_EOL, FILE_APPEND | LOCK_EX);
    }

    public static function emitHtml(): void
    {
        if (!self::$active) {
            return;
        }
        echo "\n<!-- WalletUp CSP Trace\n";
        foreach (self::buildLines() as $l) {
            echo '  ' . esc_html($l) . "\n";
        }
        echo "-->\n";
    }

    private static function buildLines(): array
    {
        $url = '?';
        if (isset($_SERVER['REQUEST_URI'])) {
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- diagnostic read-only
            $url = sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI']));
        }
        $out = ['===== WalletUp CSP Trace ' . gmdate('c') . ' | ' . $url . ' ====='];
        $first = null;
        foreach (self::$snapshots as $s) {
            $out[] = sprintf(
                '[+%7dus] %-38s csp=%d hdrs=%d',
                $s['time_us'],
                $s['stage'],
                count($s['csp']),
                $s['hdrs']
            );
            foreach ($s['csp'] as $c) {
                $out[] = '              ' . $c;
            }
            if (!empty($s['csp']) && $first === null) {
                $first = $s['stage'];
            }
        }
        $out[] = 'CSP first appeared at: ' . ($first ?? '(NEVER in PHP — header is added by web server or CDN downstream)');
        $out[] = '';
        return $out;
    }
}
