<?php

namespace Openguru\OpenCartFramework\TeleCartPulse;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Openguru\OpenCartFramework\Support\Arr;
use Psr\Log\LoggerInterface;

class TeleCartPulseEventsSender
{
    private PayloadSigner $payloadSigner;
    private LoggerInterface $logger;
    private ?string $apiKey;

    public function __construct(
        PayloadSigner $payloadSigner,
        LoggerInterface $logger,
        ?string $apiKey = null
    ) {
        $this->payloadSigner = $payloadSigner;
        $this->logger = $logger;
        $this->apiKey = $apiKey;
    }

    /**
     * Универсальный метод для отправки события из БД
     * Payload уже готов в БД в формате для отправки в SaaS
     *
     * @param array $eventData Данные события из БД (содержит event, payload, и т.д.)
     * @return bool true если SaaS принял событие (ответ содержит {"ok": true}), false в противном случае
     * @throws GuzzleException
     * @throws PayloadSignException
     */
    public function sendEvent(array $eventData): bool
    {
        $payloadJson = $eventData['payload'] ?? '{}';
        $payload = json_decode($payloadJson, true);
        if (! is_array($payload)) {
            throw new \InvalidArgumentException('Invalid payload format');
        }

        // Проверяем обязательные поля
        if (
            ! isset(
                $payload['event'],
                $payload['campaign_id'],
                $payload['tracking_id'],
                $payload['meta'],
                $payload['timestamp'],
            )
        ) {
            throw new \InvalidArgumentException(
                'Payload must contain event, campaign_id, tracking_id, meta, and timestamp'
            );
        }

        // Payload уже готов, просто добавляем signature и отправляем
        $dataToSend = [
            'payload' => $payload,
            'signature' => $this->payloadSigner->sign($payload),
        ];

        return $this->executeHttpRequest($dataToSend);
    }

    /**
     * Выполняет HTTP запрос к SaaS-приложению для отправки события
     *
     * @param array $json Данные для отправки (payload и signature)
     * @return bool true если SaaS принял событие (ответ содержит {"ok": true}), false в противном случае
     * @throws GuzzleException
     */
    private function executeHttpRequest(array $json): bool
    {
        $this->logger->debug('Pushing event: ' . Arr::get($json, 'payload.event'), [
            'data' => $json,
        ]);

        $baseUri = rtrim(env('PULSE_API_HOST', 'http://localhost'), '/') . '/';

        $client = new Client([
            'base_uri' => $baseUri,
            'timeout' => env('PULSE_TIMEOUT', 5.0),
            'headers' => [
                'Authorization' => 'Bearer ' . $this->apiKey,
                'X-TELECART-VERSION' => module_version(),
            ],
        ]);

        $response = $client->post('events', compact('json'));
        $body = $response->getBody()->getContents();
        $responseData = json_decode($body, true) ?? [];

        // Проверяем, что SaaS принял событие
        return isset($responseData['ok']) && $responseData['ok'] === true;
    }
}
