<?php
/**
 * Debug Logger for Chat Pipeline.
 *
 * Logs detailed debug information for each chat request to a JSON file.
 * Activated by defining INQYRA_DEBUG_LOG as true in wp-config.php.
 *
 * @package Inqyra
 */

// If this file is called directly, abort.
if (!defined('WPINC')) {
    die;
}

/**
 * Debug Logger class (singleton).
 */
class Inqyra_Debug_Logger {

    /**
     * Singleton instance.
     *
     * @var self|null
     */
    private static $instance = null;

    /**
     * Collected debug sections.
     *
     * @var array
     */
    private $sections = [];

    /**
     * Request start time.
     *
     * @var float
     */
    private $start_time;

    /**
     * Get singleton instance.
     *
     * @return self
     */
    public static function instance(): self {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Check if debug logging is enabled.
     *
     * @return bool
     */
    public static function is_enabled(): bool {
        return defined('INQYRA_DEBUG_LOG') && INQYRA_DEBUG_LOG;
    }

    /**
     * Private constructor.
     */
    private function __construct() {
        $this->start_time = microtime(true);
    }

    /**
     * Reset for a new request.
     */
    public function reset(): void {
        $this->sections = [];
        $this->start_time = microtime(true);
    }

    /**
     * Add a debug section.
     *
     * @param string $name Section name.
     * @param array  $data Section data.
     */
    public function log(string $name, array $data): void {
        if (!self::is_enabled()) {
            return;
        }

        $this->sections[] = [
            'step' => $name,
            'time_ms' => round((microtime(true) - $this->start_time) * 1000, 1),
            'data' => $data,
        ];
    }

    /**
     * Write all collected debug data to a JSON file.
     *
     * @return string|false File path on success, false on failure.
     */
    public function flush() {
        if (!self::is_enabled() || empty($this->sections)) {
            return false;
        }

        $upload_dir = wp_upload_dir();
        $debug_dir = $upload_dir['basedir'] . '/inqyra/debug';

        if (!file_exists($debug_dir)) {
            wp_mkdir_p($debug_dir);
            // Protect directory from web access.
            file_put_contents($debug_dir . '/.htaccess', "Deny from all\n");
            file_put_contents($debug_dir . '/index.php', "<?php // Silence is golden.\n");
        }

        $filename = gmdate('Y-m-d_H-i-s') . '_' . bin2hex(random_bytes(6)) . '.json';
        $filepath = $debug_dir . '/' . $filename;

        $output = [
            'timestamp' => gmdate('c'),
            'total_time_ms' => round((microtime(true) - $this->start_time) * 1000, 1),
            'steps' => $this->sections,
        ];

        $written = file_put_contents(
            $filepath,
            wp_json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
        );

        if ($written !== false) {
            // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_chmod -- Setting secure permissions on debug log.
            chmod($filepath, 0600);
        }

        // Clean up old files (keep last 50).
        $this->cleanup_old_files($debug_dir, 50);

        return $written !== false ? $filepath : false;
    }

    /**
     * Clean up old debug files, keeping only the most recent ones.
     *
     * @param string $dir   Directory path.
     * @param int    $keep  Number of files to keep.
     */
    private function cleanup_old_files(string $dir, int $keep): void {
        $files = glob($dir . '/*.json');
        if ($files === false || count($files) <= $keep) {
            return;
        }

        // Sort by modification time (oldest first).
        usort($files, fn($a, $b) => filemtime($a) - filemtime($b));

        $to_delete = count($files) - $keep;
        for ($i = 0; $i < $to_delete; $i++) {
            wp_delete_file($files[$i]);
        }
    }
}
