<?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 MetaConversionsApiProvider implements TrackingProvider
{
    private const API_VERSION = 'v18.0';

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

    public function send(TrackingEvent $event): void
    {
        $pixelId = setting('meta_pixel_id');
        $accessToken = setting('meta_capi_access_token');
        $testCode = setting('meta_capi_test_event_code');
        $endpoint = "https://graph.facebook.com/" . self::API_VERSION . "/{$pixelId}/events";

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

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

        $response = Http::timeout(5)
            ->withQueryParameters(['access_token' => $accessToken])
            ->post($endpoint, $payload);

        if ($response->failed()) {
            Log::channel('tracking')->error('Meta CAPI send failed', [
                'status' => $response->status(),
                'body' => $response->body(),
                'event' => $event->name,
                'event_id' => $event->eventId,
            ]);
            throw new \RuntimeException("Meta CAPI responded {$response->status()}");
        }

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

    private function buildEventData(TrackingEvent $event): array
    {
        $data = [
            'event_name' => $event->name,
            'event_time' => $event->timestamp,
            'action_source' => 'website',
            'user_data' => $this->buildUserData($event),
            'custom_data' => $this->buildCustomData($event),
        ];

        if ($event->eventId) $data['event_id'] = $event->eventId;
        if ($event->sourceUrl) $data['event_source_url'] = $event->sourceUrl;

        return $data;
    }

    private function buildUserData(TrackingEvent $event): array
    {
        $user = $event->user;
        $ud = [];

        if (!$user) return $ud;

        if ($user->emailSha256) $ud['em'] = [$user->emailSha256];
        if ($user->phoneSha256) $ud['ph'] = [$user->phoneSha256];
        if ($user->firstNameSha256) $ud['fn'] = [$user->firstNameSha256];
        if ($user->lastNameSha256) $ud['ln'] = [$user->lastNameSha256];
        if ($user->countrySha256) $ud['country'] = [$user->countrySha256];
        if ($user->ipAddress) $ud['client_ip_address'] = $user->ipAddress;
        if ($user->userAgent) $ud['client_user_agent'] = $user->userAgent;
        if ($user->fbc) $ud['fbc'] = $user->fbc;
        if ($user->fbp) $ud['fbp'] = $user->fbp;

        return $ud;
    }

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

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

        return $cd;
    }
}
