<?php

namespace App\Services\Tracking\Providers;

use App\Services\Tracking\Contracts\TrackingProvider;
use App\Services\Tracking\TrackingEvent;
use Illuminate\Support\Facades\Log;
use Segment\Client;

class SegmentProvider implements TrackingProvider
{
    /**
     * Optional injected SDK client (tests provide a mock here).
     * When null, a real Client is built on demand via resolveClient().
     */
    public function __construct(private readonly ?Client $client = null)
    {
    }

    public function isEnabled(): bool
    {
        return !empty(setting('segment_write_key'));
    }

    public function send(TrackingEvent $event): void
    {
        $client = $this->resolveClient();

        $userId = $event->user?->emailSha256;
        $anonymousId = $userId ? null : 'anon-' . ($event->eventId ?? bin2hex(random_bytes(6)));

        $properties = array_filter([
            'value'          => $event->params['value'] ?? null,
            'currency'       => $event->params['currency'] ?? null,
            'transaction_id' => $event->params['transaction_id'] ?? null,
        ], fn ($v) => $v !== null);

        // Build the message — only include keys that have a value.
        // Segment requires userId OR anonymousId but not both.
        $message = ['event' => $event->name];

        if ($userId !== null) {
            $message['userId'] = $userId;
        } else {
            $message['anonymousId'] = $anonymousId;
        }

        $message['messageId'] = $event->eventId;
        $message['timestamp'] = $event->timestamp;

        if ($properties) {
            $message['properties'] = $properties;
        }

        if ($event->sourceUrl) {
            $message['context'] = ['page' => ['url' => $event->sourceUrl]];
        }

        try {
            $client->track($message);
            $client->flush();
        } catch (\Throwable $e) {
            Log::channel('tracking')->error('Segment send failed', [
                'event'    => $event->name,
                'event_id' => $event->eventId,
                'error'    => $e->getMessage(),
            ]);
            throw new \RuntimeException('Segment SDK dispatch failed: ' . $e->getMessage(), previous: $e);
        }

        Log::channel('tracking')->info('Segment sent', [
            'event'    => $event->name,
            'event_id' => $event->eventId,
        ]);
    }

    private function resolveClient(): Client
    {
        if ($this->client !== null) {
            return $this->client;
        }

        return new Client(setting('segment_write_key'));
    }
}
