<?php
namespace SS\Core;

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

class Telemetry
{
    private static $buffer = array();

    /** Small debug logger (file + PHP error_log) */
    private static function dbg($msg){
        if (!defined('SS_TEL_DEBUG') || !SS_TEL_DEBUG) return;
        $line = '[SS_TEL] ' . $msg;
        error_log($line);
        if (defined('SS_TEL_DEBUG_FILE') && SS_TEL_DEBUG_FILE) {
            @file_put_contents(SS_TEL_DEBUG_FILE, $line . "\n", FILE_APPEND);
        }
    }

    public static function isEnabled() {
        return (bool) get_option('ss_telemetry_opt_in', false);
    }
    public static function installationId() {
        $id = (string) get_option('ss_installation_id');
        if (!$id) { $id = function_exists('wp_generate_uuid4') ? wp_generate_uuid4() : uniqid('ss_', true); update_option('ss_installation_id', $id); }
        return $id;
    }
    public static function domainHash() {
        $host = parse_url(home_url(), PHP_URL_HOST);
        $host = is_string($host) ? strtolower($host) : '';
        return hash('sha256', $host);
    }
    private static function featureFlags() {
        $flags = (array) (class_exists('\\SS_Settings') ? get_option(\SS_Settings::OPT_FEATURE_FLAGS, []) : []);
        return array(
            'qa'     => in_array('qa', $flags, true),
            'llms'   => in_array('llms', $flags, true),
            'schema' => in_array('schema', $flags, true),
        );
    }
    private static function base() {
        return array(
            'installation_id' => self::installationId(),
            'domain_hash'     => self::domainHash(),
            'plugin_version'  => defined('SEARCHSHIFTER_VERSION') ? SEARCHSHIFTER_VERSION : 'unknown',
            'php_version'     => PHP_VERSION,
            'wp_version'      => function_exists('get_bloginfo') ? get_bloginfo('version') : 'unknown',
            'site_locale'     => function_exists('get_locale') ? get_locale() : 'en_US',
            'platform'        => 'wordpress',
        );
    }
    private static function stripToDomainOrKey($value) {
        $value = (string) $value;
        $host = parse_url($value, PHP_URL_HOST);
        if ($host) return $host;
        return preg_replace('#^https?://#', '', $value);
    }
    private static function sanitize($data) {
        $data = is_array($data) ? $data : array();
        $allowed = array('endpoint','http_status','error_signature','retry_count','duration_ms','cache_hit','screen');
        $out = array();
        foreach ($allowed as $k) {
            if (array_key_exists($k, $data)) {
                $out[$k] = ($k === 'endpoint') ? self::stripToDomainOrKey((string)$data[$k]) : $data[$k];
            }
        }
        return $out;
    }

    public static function bufferSize() { return count(self::$buffer); }

    public static function queue($event, $data = array()) {
        if (!self::isEnabled()) return;

        $payload = array_merge(
            self::base(),
            array(
                'event'         => sanitize_key($event),
                'timestamp'     => gmdate('c'),
                'feature_flags' => self::featureFlags(),
                'data'          => self::sanitize($data),
            )
        );

        if (function_exists('apply_filters')) {
            $payload = apply_filters('ss_telemetry_payload', $payload);
        }

        self::$buffer[] = $payload;
        if (count(self::$buffer) > 100) array_shift(self::$buffer);

        self::dbg(sprintf('queued event=%s buffer=%d', $event, count(self::$buffer)));
    }

    public static function onShutdown() {
        $err = function_exists('error_get_last') ? error_get_last() : null;
        if ($err && isset($err['type']) && in_array($err['type'], array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR), true)) {
            self::queue('crash', array(
                'error_signature' => hash('sha256', ($err['message'] ?? '') . '|' . ($err['file'] ?? '') . '|' . ($err['line'] ?? '')),
            ));
            self::dbg('captured crash at shutdown');
        }
        self::flush();
    }

    /** Returns WP_Http response array in debug mode, or true/false otherwise */
    public static function flush() {
        if (!self::isEnabled() || empty(self::$buffer)) { self::dbg('flush skipped (disabled or empty)'); return false; }

        $apiBase = class_exists('\\SS_Settings')
            ? (string) get_option(\SS_Settings::OPT_API_BASE, defined('SEARCHSHIFTER_API_BASE') ? SEARCHSHIFTER_API_BASE : '')
            : (defined('SEARCHSHIFTER_API_BASE') ? SEARCHSHIFTER_API_BASE : '');

        $endpoint = rtrim($apiBase, '/') . '/telemetry/ingest';
        if (!$apiBase) { self::dbg('flush aborted: empty apiBase'); self::$buffer = array(); return false; }

        // Headers: API key + domain
        $headers = array('Content-Type' => 'application/json');
        $apiKey  = class_exists('\\SS_Settings') ? (string) get_option(\SS_Settings::OPT_API_KEY, '') : '';
        $domain  = class_exists('\\SS_Settings')
            ? (string) get_option(\SS_Settings::OPT_DOMAIN, parse_url(get_site_url(), PHP_URL_HOST))
            : (string) parse_url(get_site_url(), PHP_URL_HOST);

        if ($apiKey) {
            $headers['Authorization'] = 'Bearer ' . $apiKey;
            $headers['X-Api-Key']     = $apiKey;
        }
        if ($domain) {
            $headers['X-Domain']     = $domain;
            $headers['X-SS-Domain']  = $domain;
        }
        $headers['X-SS-Client'] = 'wordpress';
        $headers['User-Agent']  = 'SearchShifter/' . (defined('SEARCHSHIFTER_VERSION') ? SEARCHSHIFTER_VERSION : 'unknown');

        $args = array(
            'timeout'  => (defined('SS_TEL_DEBUG') && SS_TEL_DEBUG) ? 10 : 4,
            'blocking' => (defined('SS_TEL_DEBUG') && SS_TEL_DEBUG) ? true : false,
            'headers'  => $headers,
            'body'     => wp_json_encode(array('events' => self::$buffer)),
        );

        self::dbg(sprintf('flush sending %d event(s) -> %s', count(self::$buffer), $endpoint));

        $res = null;
        if (function_exists('wp_remote_post')) {
            $res = wp_remote_post($endpoint, $args);
            if (is_wp_error($res)) {
                self::dbg('flush result: WP_Error ' . $res->get_error_message());
            } else {
                $c = (int) wp_remote_retrieve_response_code($res);
                $b = wp_remote_retrieve_body($res);
                self::dbg(sprintf('flush result: code=%d body[0..160]=%s', $c, substr((string)$b,0,160)));
            }
        }
        self::$buffer = array();
        return $res ? $res : true;
    }
}
