<?php

namespace App\Game\Services;

use App\Game\GlobalUserInfo;
use App\Game\WebChannelConfig;
use App\Http\helper\HttpCurl;
use App\Jobs\FacebookServerEvent;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class FacebookEventService
{
    /**
     * 通过服务端 Facebook Conversions API 上报事件
     *
     * 去重策略（前后端统一）：
     * 仅依赖 Facebook 官方的 event_id 去重：
     * - 前端 fbq 上报时必须使用同一个 event_id
     * - 服务端调用 Conversions API 时也传入同一个 event_id
     * - Facebook 会自动把 Browser + Server 事件按照 event_id 合并
     *
     * @param string $eventName
     * @param string $eventId
     * @param int|string $userId
     * @param float|int|null $value
     * @param string|null $currency
     * @param string $pixelId
     * @param string $accessToken
     * @param array $extraCustomData
     */
    public static function trackEvent(
        string $eventName,
        string $eventId,
        $userId,
        $value = null,
        ?string $currency = null,
        string $pixelId = '',
        string $accessToken = '',
        array $extraCustomData = []
    ): void {
        if (empty($pixelId) || empty($accessToken)) {
            return;
        }

        $eventTime = time();
        $externalId = (string)$userId;

        // Facebook Conversions API 要求 user_data 做哈希，这里只对 external_id 做一次 sha256
        $userData = [
            'external_id' => hash('sha256', $externalId),
        ];

        $customData = array_merge(
            array_filter([
                'currency' => $currency,
                'value'    => $value,
            ], static function ($v) {
                return $v !== null && $v !== '';
            }),
            $extraCustomData
        );

        $payload = [
            'data' => [
                [
                    'event_name'    => $eventName,
                    'event_time'    => $eventTime,
                    'action_source' => 'website',
                    'event_id'      => $eventId,
                    'user_data'     => $userData,
                    'custom_data'   => $customData,
                ],
            ],
        ];

        $url = sprintf(
            'https://graph.facebook.com/v25.0/%s/events?access_token=%s',
            $pixelId,
            $accessToken
        );

        try {
            $http = new HttpCurl();
            $response = $http->curlPost($url, $payload, 'json', true);

            Log::info('FacebookEventService trackEvent success', [
                'event_name' => $eventName,
                'event_id'   => $eventId,
                'user_id'    => $userId,
                'pixel_id'   => $pixelId,
                'payload'    => $payload,
                'response'   => $response,
            ]);
        } catch (\Throwable $e) {
            Log::error('FacebookEventService trackEvent error', [
                'event_name' => $eventName,
                'event_id'   => $eventId,
                'user_id'    => $userId,
                'pixel_id'   => $pixelId,
                'message'    => $e->getMessage(),
            ]);
        }
    }

    /**
     * 注册完成事件（对应前端 CompleteRegistration）
     */
    public static function trackCompleteRegistration(GlobalUserInfo $user, WebChannelConfig $config): void
    {
        if (empty($config->PlatformID) || empty($config->PlatformToken)) {
            return;
        }
        $pixelId = $config->PlatformID;
        $accessToken = $config->PlatformToken;

        // 建议前端也使用相同的 event_id：reg_{UserID}
        $eventId = 'reg_' . $user->UserID;

        FacebookServerEvent::dispatch(
            'CompleteRegistration',
            $eventId,
            $user->UserID,
            null,
            null,
            $pixelId,
            $accessToken
        );
    }

    /**
     * 支付事件（对应前端 pay + firstpayD0/firstpayD1/payagain/Purchase）
     *
     * @param int|string $userId
     * @param string $orderSn
     * @param float|int $amount
     * @param string $currency
     * @param bool $isFirst
     * @param bool $isD0
     * @param int $channel
     */
    public static function trackPayEvent(
        $userId,
        string $orderSn,
        $amount,
        string $currency,
        bool $isFirst,
        bool $isD0,
        int $channel
    ): void {
        $config = WebChannelConfig::getByChannel($channel);
        if (!$config || empty($config->PlatformID) || empty($config->PlatformToken)) {
            return;
        }
        $pixelId = $config->PlatformID;
        $accessToken = $config->PlatformToken;

        // 统一使用同一个 event_id（与前端保持一致）
        // 前端所有支付相关事件共用：purchase_{order_sn}
        $eventId = 'purchase_' . $orderSn;

        // 标准 Purchase 事件（所有支付都会上报）
        FacebookServerEvent::dispatch(
            'Purchase',
            $eventId,
            $userId,
            $amount,
            $currency,
            $pixelId,
            $accessToken
        );

        // 首次支付
        if ($isFirst) {
            FacebookServerEvent::dispatch(
                'firstpayD1',
                $eventId,
                $userId,
                $amount,
                $currency,
                $pixelId,
                $accessToken
            );

            if ($isD0) {
                // D0 首充自定义事件
                FacebookServerEvent::dispatch(
                    'firstpayD0',
                    $eventId,
                    $userId,
                    $amount,
                    $currency,
                    $pixelId,
                    $accessToken
                );

                // D0 首充标准事件：AddToWishlist（与前端保持一致）
                FacebookServerEvent::dispatch(
                    'AddToWishlist',
                    $eventId,
                    $userId,
                    $amount,
                    $currency,
                    $pixelId,
                    $accessToken
                );
            }
        } elseif (!$isD0) {
            // 复充（非首次且非 D0）
            FacebookServerEvent::dispatch(
                'payagain',
                $eventId,
                $userId,
                $amount,
                $currency,
                $pixelId,
                $accessToken
            );
        }
    }
}

