<?php

namespace App\Services\Tracking\Providers;

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

class TiktokEventsApiProvider implements TrackingProvider
{
    private const ENDPOINT = 'https://business-api.tiktok.com/open_api/v1.3/event/track/';

    private const NAME_MAP = [
        'Purchase' => 'CompletePayment',
        'AddToCart' => 'AddToCart',
        'InitiateCheckout' => 'InitiateCheckout',
        'CompleteRegistration' => 'CompleteRegistration',
        'ViewContent' => 'ViewContent',
        'Lead' => 'SubmitForm',
    ];

    public function isEnabled(): bool
    {
        return !empty(setting('tiktok_pixel_id'))
            && !empty(setting('tiktok_events_api_token'));
    }

    public function send(TrackingEvent $event): void
    {
        if (!isset(self::NAME_MAP[$event->name])) return;

        $pixelId = setting('tiktok_pixel_id');
        $token = setting('tiktok_events_api_token');
        $testCode = setting('tiktok_events_test_event_code');

        $payload = [
            'event_source' => 'web',
            'event_source_id' => $pixelId,
            'data' => [$this->buildEventData($event)],
        ];

        if (!empty($testCode)) {
            $payload['test_event_code'] = $testCode;
        }

        $response = Http::timeout(5)
            ->withHeaders(['Access-Token' => $token])
            ->post(self::ENDPOINT, $payload);

        if ($response->failed() || ($response->json('code') !== 0 && $response->json('code') !== null)) {
            Log::channel('tracking')->error('TikTok Events API send failed', [
                'status' => $response->status(),
                'body' => $response->body(),
                'event' => $event->name,
                'event_id' => $event->eventId,
            ]);
            throw new \RuntimeException("TikTok Events API failed with status {$response->status()}");
        }

        Log::channel('tracking')->info('TikTok Events API sent', [
            'event' => $event->name,
            'event_id' => $event->eventId,
            'status' => $response->status(),
        ]);
    }

    private function buildEventData(TrackingEvent $event): array
    {
        $data = [
            'event' => self::NAME_MAP[$event->name],
            'event_time' => $event->timestamp,
            'user' => $this->buildUser($event),
            'properties' => $this->buildProperties($event),
        ];

        if ($event->eventId) $data['event_id'] = $event->eventId;
        if ($event->sourceUrl) {
            $data['page'] = ['url' => $event->sourceUrl];
        }

        return $data;
    }

    private function buildUser(TrackingEvent $event): array
    {
        $u = [];
        $user = $event->user;
        if (!$user) return $u;

        if ($user->emailSha256) $u['email'] = $user->emailSha256;
        if ($user->phoneSha256) $u['phone'] = $user->phoneSha256;
        if ($user->ipAddress) $u['ip'] = $user->ipAddress;
        if ($user->userAgent) $u['user_agent'] = $user->userAgent;
        if ($user->ttclid) $u['ttclid'] = $user->ttclid;
        return $u;
    }

    private function buildProperties(TrackingEvent $event): array
    {
        $p = [];
        if (isset($event->params['value'])) $p['value'] = (float) $event->params['value'];
        if (isset($event->params['currency'])) $p['currency'] = $event->params['currency'];
        if (isset($event->params['transaction_id'])) $p['order_id'] = $event->params['transaction_id'];

        if (isset($event->params['contents']) && is_array($event->params['contents'])) {
            $p['contents'] = array_map(fn ($c) => [
                'content_id' => (string) ($c['id'] ?? ''),
                'quantity' => (int) ($c['quantity'] ?? 1),
                'price' => (float) ($c['item_price'] ?? 0),
            ], $event->params['contents']);
        }

        return $p;
    }
}
