<?php

namespace App\Services;

use App\Models\Setting;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class MetaConversionsService
{
    private string $pixelId;
    private string $accessToken;
    private string $testEventCode;
    private string $apiVersion = 'v19.0';

    public function __construct()
    {
        $this->pixelId       = (string) Setting::get('facebook_pixel_id', '');
        $this->accessToken   = (string) Setting::get('conversions_api_token', '');
        $this->testEventCode = (string) Setting::get('conversions_api_test_code', '');
    }

    public function isEnabled(): bool
    {
        return !empty($this->pixelId) && !empty($this->accessToken);
    }

    /**
     * Send event to Meta Conversions API
     * Returns the event_id so browser pixel can use same ID (deduplication)
     */
    public function send(
        string $eventName,
        array  $customData    = [],
        array  $extraUserData = [],
        string $eventId       = null
    ): string {
        $eventId = $eventId ?? $this->generateUuid();

        if (!$this->isEnabled()) {
            return $eventId;
        }

        $req = request();

        $userData = array_filter([
            'client_ip_address' => $req->ip(),
            'client_user_agent' => $req->userAgent(),
            'fbp'               => $req->cookie('_fbp'),
            'fbc'               => $this->getFbc($req),
        ]);

        $userData = array_merge($userData, $extraUserData);

        $payload = [
            'data' => [[
                'event_name'       => $eventName,
                'event_time'       => time(),
                'event_id'         => $eventId,
                'event_source_url' => $req->fullUrl(),
                'action_source'    => 'website',
                'user_data'        => $userData,
                'custom_data'      => array_filter($customData),
            ]],
            'access_token' => $this->accessToken,
        ];

        if (!empty($this->testEventCode)) {
            $payload['test_event_code'] = $this->testEventCode;
        }

        try {
            Http::timeout(3)->post(
                "https://graph.facebook.com/{$this->apiVersion}/{$this->pixelId}/events",
                $payload
            );
        } catch (\Exception $e) {
            Log::warning('[Meta CAPI] ' . $eventName . ' failed: ' . $e->getMessage());
        }

        return $eventId;
    }

    /**
     * Send Purchase event with customer data (most important event)
     */
    public function sendPurchase(
        float  $value,
        string $phone,
        array  $contentIds  = [],
        int    $numItems    = 1,
        string $orderId     = '',
        string $eventId     = null
    ): string {
        $userData = [];
        if (!empty($phone)) {
            $userData['ph'] = $this->hashPhone($phone);
        }

        return $this->send(
            'Purchase',
            [
                'value'        => round($value, 2),
                'currency'     => 'BDT',
                'content_ids'  => $contentIds,
                'content_type' => 'product',
                'num_items'    => $numItems,
                'order_id'     => $orderId,
            ],
            $userData,
            $eventId
        );
    }

    /**
     * Send ViewContent (product page)
     */
    public function sendViewContent(int $productId, string $productName, float $price, string $eventId = null): string
    {
        return $this->send(
            'ViewContent',
            [
                'content_ids'  => [(string) $productId],
                'content_name' => $productName,
                'content_type' => 'product',
                'value'        => round($price, 2),
                'currency'     => 'BDT',
            ],
            [],
            $eventId
        );
    }

    /**
     * Send AddToCart
     */
    public function sendAddToCart(int $productId, string $productName, float $price, int $qty, string $eventId = null): string
    {
        return $this->send(
            'AddToCart',
            [
                'content_ids'  => [(string) $productId],
                'content_name' => $productName,
                'content_type' => 'product',
                'value'        => round($price * $qty, 2),
                'currency'     => 'BDT',
            ],
            [],
            $eventId
        );
    }

    /**
     * Send InitiateCheckout
     */
    public function sendInitiateCheckout(float $value, int $numItems, string $eventId = null): string
    {
        return $this->send(
            'InitiateCheckout',
            [
                'value'     => round($value, 2),
                'currency'  => 'BDT',
                'num_items' => $numItems,
            ],
            [],
            $eventId
        );
    }

    // ── Helpers ────────────────────────────────────────────────────────────────

    private function hashPhone(string $phone): string
    {
        $phone = preg_replace('/[\s\-\(\)]/', '', $phone);
        // Bangladesh: 01XXXXXXXXX → +8801XXXXXXXXX
        if (preg_match('/^01[3-9]\d{8}$/', $phone)) {
            $phone = '+880' . $phone;
        } elseif (preg_match('/^8801[3-9]\d{8}$/', $phone)) {
            $phone = '+' . $phone;
        }
        return hash('sha256', $phone);
    }

    private function getFbc($req): ?string
    {
        if ($req->cookie('_fbc')) {
            return $req->cookie('_fbc');
        }
        if ($fbclid = $req->query('fbclid')) {
            return 'fb.1.' . (time() * 1000) . '.' . $fbclid;
        }
        return null;
    }

    private function generateUuid(): string
    {
        return sprintf(
            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x0fff) | 0x4000,
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
        );
    }
}
