<?php

declare(strict_types=1);

namespace PpPhp\Core\Analytics;

use PpPhp\Core\PlatformSettings;

/**
 * The reporting side, for a SEPARATE PPPHP property that wants its traffic to
 * appear in another install's Visitor console (the primary). Configure it once
 * with the collector URL + the site id/secret the primary handed you, then call
 * report* from anywhere. Fire-and-forget: a slow or down collector never delays
 * the page — the request is sent after the response where possible.
 *
 * This is the server-side counterpart to the browser beacon (pp-analytics.js);
 * use it for server-rendered pageviews or to forward API-client telemetry.
 */
final class AnalyticsClient
{
    public const SETTING = 'platform.analytics_report';

    /** @return array{url:string,site:string,secret:string,enabled:bool} */
    public static function config(): array
    {
        $c = [];
        try { $c = (array) PlatformSettings::get(self::SETTING); } catch (\Throwable $e) {}
        return [
            'url'     => (string) ($c['url'] ?? ''),
            'site'    => (string) ($c['site'] ?? ''),
            'secret'  => (string) ($c['secret'] ?? ''),
            'enabled' => (bool) ($c['enabled'] ?? false),
        ];
    }

    public static function configure(string $collectorUrl, string $site, string $secret, bool $enabled = true): bool
    {
        try {
            return PlatformSettings::set(self::SETTING, [
                'url'     => rtrim(trim($collectorUrl), '/'),
                'site'    => trim($site),
                'secret'  => trim($secret),
                'enabled' => $enabled,
            ]);
        } catch (\Throwable $e) { return false; }
    }

    public static function isConfigured(): bool
    {
        $c = self::config();
        return $c['enabled'] && $c['url'] !== '' && $c['site'] !== '';
    }

    /**
     * Report a server-rendered pageview. Pass the visitor's real IP (the collector
     * would otherwise see this server's IP). Sends the site SECRET so the
     * on-behalf-of IP is trusted.
     *
     * @param array<string,mixed> $extra optional url/ref/langs/tz/etc.
     */
    public static function reportPageview(string $visitorIp, string $url, string $ref = '', array $extra = []): void
    {
        if (!self::isConfigured()) return;
        self::send(['type' => 'pageview', 'ip' => $visitorIp, 'url' => $url, 'ref' => $ref] + $extra);
    }

    /** Forward one API-client query to the primary's Clients & API view. */
    public static function reportApi(string $action, int $status, string $clientLabel = '', string $clientKey = '', string $clientIp = ''): void
    {
        if (!self::isConfigured()) return;
        self::send(['type' => 'api', 'action' => $action, 'status' => $status,
                    'client' => $clientLabel, 'key' => $clientKey, 'ip' => $clientIp]);
    }

    /** @param array<string,mixed> $payload */
    private static function send(array $payload): void
    {
        $c = self::config();
        $payload['site']  = $c['site'];
        $payload['token'] = $c['secret'];
        $body = (string) json_encode($payload, JSON_UNESCAPED_SLASHES);
        $url = $c['url'];

        $run = static function () use ($url, $body) {
            try {
                if (function_exists('curl_init')) {
                    $ch = curl_init($url);
                    curl_setopt_array($ch, [
                        CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body,
                        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
                        CURLOPT_RETURNTRANSFER => true,
                        CURLOPT_CONNECTTIMEOUT => 2, CURLOPT_TIMEOUT => 4,
                        CURLOPT_USERAGENT => 'PPPHP-Analytics-Report/1',
                    ]);
                    curl_exec($ch);
                    unset($ch);
                } else {
                    $ctx = stream_context_create(['http' => [
                        'method' => 'POST', 'header' => "Content-Type: application/json\r\n",
                        'content' => $body, 'timeout' => 4, 'ignore_errors' => true,
                    ]]);
                    @file_get_contents($url, false, $ctx);
                }
            } catch (\Throwable $e) { /* fire and forget */ }
        };

        // Send after the response is delivered, so reporting never delays the page.
        if (function_exists('fastcgi_finish_request') || function_exists('litespeed_finish_request')) {
            register_shutdown_function(static function () use ($run) {
                if (function_exists('fastcgi_finish_request')) { @fastcgi_finish_request(); }
                elseif (function_exists('litespeed_finish_request')) { @litespeed_finish_request(); }
                $run();
            });
        } else {
            register_shutdown_function($run);
        }
    }
}
