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

class Aysa_Error_Center {
    const DEFAULT_ENDPOINT = '';

    public static function report($event) {
        $event = is_array($event) ? $event : array();
        $endpoint = self::get_endpoint();
        $secret = self::get_secret();
        if ($endpoint === '' || $secret === '') {
            return false;
        }

        $payload = self::normalize_event($event);
        $body = wp_json_encode($payload);
        if (!is_string($body) || $body === '') {
            return false;
        }

        $timestamp = (string) time();
        $signature = hash_hmac('sha256', $body . "\n" . $timestamp, $secret);
        wp_remote_post($endpoint, array(
            'timeout' => 3,
            'blocking' => false,
            'headers' => array(
                'Accept' => 'application/json',
                'Content-Type' => 'application/json',
                'X-AYSA-TIMESTAMP' => $timestamp,
                'X-AYSA-SIGNATURE' => $signature,
            ),
            'body' => $body,
        ));

        return true;
    }

    private static function get_endpoint() {
        if (defined('AYSA_ERROR_CENTER_INGEST_ENDPOINT')) {
            $endpoint = trim((string) AYSA_ERROR_CENTER_INGEST_ENDPOINT);
            if ($endpoint !== '') {
                return esc_url_raw($endpoint);
            }
        }
        $option = trim((string) get_option('aysa_error_center_ingest_endpoint', ''));
        if ($option !== '') {
            return esc_url_raw($option);
        }
        return self::DEFAULT_ENDPOINT;
    }

    private static function get_secret() {
        if (defined('AYSA_ERROR_CENTER_INGEST_SECRET')) {
            $secret = trim((string) AYSA_ERROR_CENTER_INGEST_SECRET);
            if ($secret !== '') {
                return $secret;
            }
        }
        $option = trim((string) get_option('aysa_error_center_ingest_secret', ''));
        if ($option !== '') {
            return $option;
        }
        return '';
    }

    private static function normalize_event(array $event) {
        $website = isset($event['website']) ? (string) $event['website'] : '';
        if ($website === '') {
            $website = (string) wp_parse_url(home_url('/'), PHP_URL_HOST);
        }

        $payload = array(
            'source' => self::safe_key($event['source'] ?? 'plugin', 'plugin'),
            'module' => self::safe_key($event['module'] ?? 'plugin', 'plugin'),
            'severity' => self::safe_severity($event['severity'] ?? 'error'),
            'error_code' => self::safe_key($event['error_code'] ?? 'plugin_error', 'plugin_error'),
            'message_safe' => self::safe_message($event['message_safe'] ?? 'Plugin operational error.'),
            'technical_context' => self::sanitize_context($event['technical_context'] ?? array()),
            'project_id' => intval($event['project_id'] ?? get_option('aysa_project_id', 0)),
            'website' => self::safe_message($website, 190),
            'run_id' => self::safe_message($event['run_id'] ?? '', 120),
            'action_key' => self::safe_key($event['action_key'] ?? '', ''),
            'request_id' => self::safe_message($event['request_id'] ?? (isset($_SERVER['HTTP_X_REQUEST_ID']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_X_REQUEST_ID'])) : ''), 120),
        );

        $payload['fingerprint'] = isset($event['fingerprint'])
            ? self::safe_message($event['fingerprint'], 190)
            : self::fingerprint($payload);

        return $payload;
    }

    private static function fingerprint(array $payload) {
        $parts = array(
            $payload['source'] ?? '',
            $payload['module'] ?? '',
            $payload['error_code'] ?? '',
            $payload['project_id'] ?? '',
            $payload['website'] ?? '',
            $payload['run_id'] ?? '',
            $payload['action_key'] ?? '',
            $payload['message_safe'] ?? '',
        );
        return hash('sha256', implode('|', array_map('strval', $parts)));
    }

    private static function safe_severity($value) {
        $severity = sanitize_key((string) $value);
        return in_array($severity, array('info', 'warning', 'error', 'critical'), true) ? $severity : 'error';
    }

    private static function safe_key($value, $fallback) {
        $value = sanitize_key((string) $value);
        return $value !== '' ? $value : $fallback;
    }

    private static function safe_message($value, $limit = 500) {
        $text = is_scalar($value) ? (string) $value : wp_json_encode($value);
        $text = is_string($text) ? $text : '';
        $text = wp_strip_all_tags($text);
        $text = preg_replace('/\s+/', ' ', $text);
        $text = self::redact_string(trim((string) $text));
        return substr($text, 0, max(1, intval($limit)));
    }

    private static function sanitize_context($value, $depth = 0) {
        if ($depth > 4) {
            return '[truncated]';
        }
        if (is_array($value)) {
            $out = array();
            $count = 0;
            foreach ($value as $key => $item) {
                $key_string = is_scalar($key) ? (string) $key : 'key';
                $safe_key = self::safe_context_key($key_string);
                if (self::is_sensitive_key($key_string)) {
                    $out[$safe_key] = '[redacted]';
                } else {
                    $out[$safe_key] = self::sanitize_context($item, $depth + 1);
                }
                $count++;
                if ($count >= 40) {
                    $out['truncated'] = true;
                    break;
                }
            }
            return $out;
        }
        if (is_bool($value) || is_int($value) || is_float($value) || $value === null) {
            return $value;
        }
        return self::safe_message($value, 500);
    }

    private static function safe_context_key($key) {
        $key = preg_replace('/[^a-zA-Z0-9_\-:.]/', '_', (string) $key);
        $key = trim((string) $key, '_');
        return $key !== '' ? substr($key, 0, 120) : 'key';
    }

    private static function is_sensitive_key($key) {
        return preg_match('/(secret|token|key|password|authorization|signature|cookie|nonce|credential|bearer)/i', (string) $key) === 1;
    }

    private static function redact_string($text) {
        $text = preg_replace('/Bearer\s+[A-Za-z0-9._\-~+\/]+=*/i', 'Bearer [redacted]', (string) $text);
        $text = preg_replace('/(key|secret|token|signature|password|authorization)(["\\\']?\s*[:=]\s*["\\\']?)[^\s"\\\']+/i', '$1$2[redacted]', $text);
        $text = preg_replace('/[A-Za-z0-9+\/]{32,}={0,2}/', '[redacted]', $text);
        return $text;
    }
}

if (!function_exists('aysa_report_operational_error')) {
    function aysa_report_operational_error($event) {
        if (!class_exists('Aysa_Error_Center')) {
            return false;
        }
        return Aysa_Error_Center::report($event);
    }
}
