<?php
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Service for catching fatal errors, logging system events, and managing the log UI.
 */
class EEP_Runtime_Log_Service {

    /**
     * Appends a new entry to the platform's internal runtime log.
     * Keeps the log trimmed to the most recent 250 entries to prevent database bloat.
     *
     * @param string $level   Log level (e.g., 'info', 'warning', 'error', 'fatal').
     * @param string $message A brief description of the event.
     * @param array  $context Additional context/data to store with the log.
     */
    public function append_runtime_log($level, $message, array $context = []) {
        $message = trim((string) $message);
        if ($message === '') {
            return;
        }

        $level = sanitize_key((string) $level);
        if ($level === '') {
            $level = 'error';
        }

        $context_payload = [];
        foreach ($context as $key => $value) {
            $key = sanitize_key((string) $key);
            if ($key === '') {
                continue;
            }
            if (is_scalar($value)) {
                $context_payload[$key] = sanitize_text_field((string) $value);
            } else {
                $context_payload[$key] = sanitize_text_field((string) wp_json_encode($value));
            }
        }

        $entry = [
            'time'    => current_time('mysql'),
            'level'   => $level,
            'message' => eep_sanitize_text($message),
            'context' => $context_payload,
        ];

        $logs = get_option('eep_runtime_logs', []);
        if (!is_array($logs)) {
            $logs = [];
        }

        array_unshift($logs, $entry);
        
        if (count($logs) > 250) {
            $logs = array_slice($logs, 0, 250);
        }
        
        update_option('eep_runtime_logs', $logs, false);
    }

    /**
     * Retrieves the most recent log entries.
     *
     * @param int $limit Maximum number of logs to retrieve.
     * @return array
     */
    public function get_runtime_logs($limit = 80) {
        $limit = max(1, min(250, (int) $limit));
        $logs = get_option('eep_runtime_logs', []);
        
        if (!is_array($logs)) {
            return [];
        }
        
        return array_slice($logs, 0, $limit);
    }

    /**
     * Form handler for the admin area to clear all runtime logs.
     * Hook this to `admin_post_eep_clear_logs`.
     */
    public function handle_clear_logs() {
        if (!current_user_can('manage_options')) {
            wp_die(esc_html__('Not allowed.', 'nexdirectory'));
        }

        if (
            !isset($_POST['eep_clear_logs_nonce']) || 
            !wp_verify_nonce(eep_sanitize_text(wp_unslash($_POST['eep_clear_logs_nonce'])), 'eep_clear_logs')
        ) {
            wp_die(esc_html__('Invalid request.', 'nexdirectory'));
        }

        delete_option('eep_runtime_logs');

        $redirect_base = wp_get_referer() ?: admin_url('admin.php?page=eep-settings#eep-tab-logs');
        $redirect_url = eep_add_query_arg([
            'eep_notice'      => rawurlencode(__('Logs cleared.', 'nexdirectory')),
            'eep_notice_type' => 'success'
        ], $redirect_base);

        wp_safe_redirect($redirect_url);
        exit;
    }

    /**
     * Catches and logs PHP fatal errors. 
     * Hook this using `register_shutdown_function()`.
     */
    public function capture_fatal_error() {
        $error = error_get_last();
        if (!is_array($error)) {
            return;
        }

        $fatal_types = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
        if (!in_array((int) ($error['type'] ?? 0), $fatal_types, true)) {
            return;
        }

        $this->append_runtime_log('fatal', (string) ($error['message'] ?? 'Fatal error'), [
            'file' => (string) ($error['file'] ?? ''),
            'line' => (string) ($error['line'] ?? ''),
        ]);
    }
}
