<?php

namespace addons\shopro\service\xhs;

use app\admin\model\shopro\xhs\ConversionLog as ConversionLogModel;

/**
 * 小红书聚光「种草直达」转化回传服务
 *
 * 负责调用小红书转化回传 API 上报转化事件
 *
 * ⚠️ 凭证说明：
 *   app_id + access_token 由小红书运营/销售侧提供（静态凭证），非 OAuth 动态获取。
 *   配置方式：
 *     - 环境变量: PHP_XHS_APP_ID / PHP_XHS_ACCESS_TOKEN
 *     - 或 shopro 配置表 code=xhs_ad 组中配置 APP_ID / ACCESS_TOKEN
 *
 *   注意：OAuth 接口（app_key + app_secret → /oauth/token）用于管理类 API，
 *   转化回传 API 不使用 OAuth token，此处保留 getAccessToken() 仅供其他场景参考。
 */
class ConversionService
{
    // API 基础地址（以小红书开放平台官方文档为准）
    const API_BASE = 'https://ad-market.xiaohongshu.com/open/api';
    // const API_BASE = 'https://adapi.xiaohongshu.com';

    // Token 接口
    const TOKEN_URL = '/oauth/token';

    // 转化回传接口（具体路径以开放平台文档为准）
    const CONVERSION_URL = '/conversion/upload';
    // const CONVERSION_URL = '/api/open/conversion';

    // Token 缓存 key 前缀
    const TOKEN_CACHE_KEY = 'shopro:xhs:access_token';

    // Token 提前刷新时间（秒），在过期前 5 分钟刷新
    const TOKEN_REFRESH_AHEAD = 300;

    /**
     * 获取 Access Token（带缓存）
     *
     * @return string|null
     * @throws \Exception
     */
    // public function getAccessToken()
    // {
    //     // 检查缓存
    //     $cached = redis_cache('?' . self::TOKEN_CACHE_KEY);
    //     if ($cached) {
    //         $tokenData = json_decode($cached, true);
    //         if ($tokenData && isset($tokenData['token'])) {
    //             $now = time();
    //             if ($tokenData['expires_at'] > ($now + self::TOKEN_REFRESH_AHEAD)) {
    //                 return $tokenData['token'];
    //             }
    //         }
    //     }

    //     // 获取新 Token
    //     return $this->refreshAccessToken();
    // }

    /**
     * 强制刷新 Access Token
     *
     * @return string|null
     * @throws \Exception
     */
    // private function refreshAccessToken()
    // {
    //     $appKey = $this->getConfig('APP_KEY', '');
    //     $appSecret = $this->getConfig('APP_SECRET', '');

    //     if (empty($appKey) || empty($appSecret)) {
    //         throw new \Exception('小红书聚光 API 凭证未配置（PHP_XHS_APP_KEY / PHP_XHS_APP_SECRET）');
    //     }

    //     $url = self::API_BASE . self::TOKEN_URL;
    //     $params = [
    //         'app_key'    => $appKey,
    //         'app_secret' => $appSecret,
    //         'grant_type' => 'client_credentials',
    //     ];

    //     $response = $this->httpPost($url, $params);

    //     if (empty($response['access_token'])) {
    //         throw new \Exception('获取 access_token 失败: ' . json_encode($response));
    //     }

    //     $token = $response['access_token'];
    //     $expiresIn = intval($response['expires_in'] ?? 7200);

    //     // 缓存 Token
    //     $tokenData = [
    //         'token'      => $token,
    //         'expires_at' => time() + $expiresIn,
    //     ];
    //     redis_cache(self::TOKEN_CACHE_KEY, json_encode($tokenData), $expiresIn);

    //     return $token;
    // }

    /**
     * 回传转化事件到小红书（对齐官方「种草直达」API 文档）
     * 官方文档: https://adapi.xiaohongshu.com/api/open/conversion
     *
     * @param array $data 转化数据
     *  - click_id        string  广告点击 ID（必填）
     *  - conversion_type string  转化类型（必填）
     *  - value           float   转化金额
     *  - order_id        string  订单号（用于查询商品上下文）
     *  - conversion_time int     转化发生时间（秒级时间戳）
     *  - platform        string  平台来源，默认 WechatMiniProgram
     * @return array ['success' => bool, 'response' => mixed]
     */
    public function reportConversion($data)
    {
        $clickId = $data['click_id'] ?? '';
        $conversionType = $data['conversion_type'] ?? '';

        if (empty($clickId)) {
            return ['success' => false, 'response' => 'click_id 为空'];
        }

        // 获取 app_id 和 access_token
        // 注意：转化回传 API 的 access_token 不同于管理 API 的 OAuth token
        // 官方文档说明："app_id和access_token需要联系您的产品获取"，即由小红书运营/销售侧提供的静态凭证
        $appId = config('shopro.xhs_app_id');
        $accessToken = config('shopro.xhs_access_token');

        custom_log('[xhs.context] 配置调试:app_id:'.$appId.'accessToken:'.$accessToken, 0, 'xhs_ad', 'info');

        if (empty($appId)) {
            return ['success' => false, 'response' => 'app_id 未配置（需联系小红书运营获取）'];
        }

        if (empty($accessToken)) {
            return ['success' => false, 'response' => 'access_token 未配置（需联系小红书运营获取）'];
        }

        // 转换事件类型为小红书平台编码
        // 1=商品成交, 122=微信加好友, 123=注册, 124=微信小程序访问
        $eventType = $this->mapEventType($conversionType);

        // 构建 context.product 商品上下文（仅商品成交事件需要）
        $context = $this->buildContext($data, $eventType);

        $url = self::API_BASE . self::CONVERSION_URL;

        // 对齐官方 API 请求体格式: app_id、access_token 放在 body 中，不放在 Header
        $body = [
            'app_id'       => $appId,
            'access_token' => $accessToken,
            'event_type'   => strval($eventType),
            'timestamp'    => intval(microtime(true) * 1000), // 毫秒级时间戳
            'click_id'     => $clickId,
            'platform'     => $data['platform'] ?? '爱岛珠宝微信小程序',
        ];

        if (!empty($context)) {
            $body['context'] = $context;
        }

        $headers = [
            'Content-Type: application/json',
        ];

        $result = $this->httpPostJson($url, $body, $headers);

        // 判断回传是否成功（根据小红书返回结构判断）
        if (isset($result['code']) && $result['code'] === 0) {
            return ['success' => true, 'response' => json_encode($result)];
        }

        return [
            'success'  => false,
            'response' => json_encode($result),
            'err_msg'  => $result['msg'] ?? ($result['message'] ?? '未知错误'),
        ];
    }

    /**
     * 构建转化上下文（context.product）
     * 对于商品成交（event_type=1），自动查询订单获取商品信息
     *
     * @param array $data 转化数据
     * @param int   $eventType 小红书事件类型编码
     * @return array
     */
    private function buildContext($data, $eventType)
    {
        $context = [];

        // 只有商品成交事件（event_type=1）需要商品上下文
        if ($eventType != 1) {
            return $context;
        }

        $orderId = $data['order_id'] ?? '';
        if (empty($orderId)) {
            return $context;
        }

        try {
            $orderModel = \app\admin\model\shopro\order\Order::where('order_sn', $orderId)->find();
            if (!$orderModel) {
                custom_log('[xhs.context] 未找到订单, order_sn=' . $orderId, 0, 'xhs_ad', 'warning');
                return $context;
            }

            $items = \app\admin\model\shopro\order\OrderItem::where('order_id', $orderModel->id)->select();

            $orderCount = 0;
            $productId = '';
            $productName = '';
            $productPrice = 0;
            $productImg = '';

            foreach ($items as $item) {
                $orderCount += intval($item->goods_num ?? 1);
                if (empty($productId)) {
                    $productId = strval($item->goods_id ?? '');
                    $productName = $item->goods_title ?? '';
                    $productPrice = floatval($item->goods_price ?? 0);
                    $productImg = $item->goods_image ?? '';
                }
            }

            $context['product'] = [
                'product_id'       => $productId,
                'product_name'     => $productName,
                'product_price'    => $productPrice,
                'product_category' => $this->getCategoryName($orderModel),
                'img_url'          => $productImg,
                'shop_name'        => 'BEEVERA',
                'order_id'         => $orderId,
                'order_count'      => $orderCount,
                'pay_amount'       => floatval($data['value'] ?? ($orderModel->pay_fee ?? 0)),
            ];

            custom_log('[xhs.context] 商品上下文构建成功, order_sn=' . $orderId, 0, 'xhs_ad');
        } catch (\Exception $e) {
            custom_log('[xhs.context] 获取商品上下文异常: ' . $e->getMessage(), 0, 'xhs_ad', 'error');
        }

        return $context;
    }

    /**
     * 获取订单商品分类名称
     *
     * @param \app\admin\model\shopro\order\Order $order
     * @return string
     */
    private function getCategoryName($order)
    {
        try {
            $items = $order->items;
            if (!empty($items)) {
                $firstItem = $items[0];
                $goodsId = $firstItem->goods_id ?? 0;
                if ($goodsId) {
                    $goods = \app\admin\model\shopro\goods\Goods::find($goodsId);
                    if ($goods && !empty($goods->category_ids)) {
                        $categoryIds = is_string($goods->category_ids)
                            ? json_decode($goods->category_ids, true)
                            : $goods->category_ids;
                        if (!empty($categoryIds) && is_array($categoryIds)) {
                            $categoryId = $categoryIds[0] ?? 0;
                            if ($categoryId) {
                                $category = \app\admin\model\shopro\category\Category::find($categoryId);
                                return $category ? $category->name : '';
                            }
                        }
                    }
                }
            }
        } catch (\Exception $e) {
            // 分类查询失败不影响主流程
        }
        return '';
    }

    /**
     * 处理转化回传（含重试逻辑）
     *
     * @param array $jobData 队列数据
     * @return bool
     */
    public function handleReport($jobData)
    {
        $logId = $jobData['log_id'] ?? 0;
        $userId = $jobData['user_id'] ?? 0;

        custom_log('[xhs.report] 开始处理转化回传, log_id=' . $logId . ', data=' . json_encode($jobData, JSON_UNESCAPED_UNICODE), $userId, 'xhs_ad');

        // 查询日志记录
        $log = ConversionLogModel::find($logId);
        if (!$log) {
            custom_log('[xhs.report] 转化日志不存在, log_id=' . $logId, $userId, 'xhs_ad', 'warning');
            return false;
        }

        // 非待回传状态跳过
        if ($log->status != ConversionLogModel::STATUS_PENDING) {
            custom_log('[xhs.report] 日志状态非待回传，跳过, log_id=' . $logId . ', status=' . $log->status, $userId, 'xhs_ad', 'warning');
            return true;
        }

        // 超过最大重试次数
        if ($log->retry_count >= ConversionLogModel::MAX_RETRY) {
            $log->status = ConversionLogModel::STATUS_FAILED;
            $log->api_err_msg = '超过最大重试次数(' . ConversionLogModel::MAX_RETRY . ')';
            $log->updatetime = time();
            $log->save();

            custom_log('[xhs.report] 超过最大重试次数，标记失败, log_id=' . $logId, $userId, 'xhs_ad', 'error');
            return false;
        }

        // 调用回传
        $result = $this->reportConversion($jobData);

        $now = time();
        $log->retry_count = $log->retry_count + 1;
        $log->report_time = $now;
        $log->updatetime = $now;

        if ($result['success']) {
            $log->status = ConversionLogModel::STATUS_SUCCESS;
            $log->api_response = $result['response'];
            $log->save();

            custom_log('[xhs.report] 转化回传成功, log_id=' . $logId, $userId, 'xhs_ad');
            return true;
        } else {
            $log->status = ($log->retry_count >= ConversionLogModel::MAX_RETRY)
                ? ConversionLogModel::STATUS_FAILED
                : ConversionLogModel::STATUS_PENDING;

            $log->api_response = $result['response'] ?? '';
            $log->api_err_msg = $result['err_msg'] ?? 'API 返回异常';
            $log->save();

            custom_log('[xhs.report] 转化回传失败, log_id=' . $logId . ', retry=' . $log->retry_count . ', err=' . $log->api_err_msg, $userId, 'xhs_ad', 'error');

            return false;
        }
    }

    /**
     * 转化类型映射：内部类型 → 小红书事件编码
     * 官方事件枚举:
     *   1   = 商品成交（支持联调/报表展示/优化）
     *   122 = 微信加好友（支持联调/报表展示，不支持优化）
     *   123 = 注册（支持联调/报表展示，不支持优化）
     *   124 = 微信小程序访问（支持联调/报表展示，不支持优化）
     *
     * @param string $type
     * @return int
     */
    private function mapEventType($type)
    {
        $map = [
            'register'    => 123, // 注册
            'order'       => 1,   // 商品成交（下单）
            // 'payment'     => 1,   // 商品成交（付款）
            // 'add_wechat'  => 122, // 微信加好友
            'visit'       => 124, // 微信小程序访问
        ];

        return $map[$type] ?? 0;
    }

    // /**
    //  * 获取配置（优先环境变量，其次 shopro 配置组）
    //  *
    //  * @param string $key
    //  * @param mixed  $default
    //  * @return mixed
    //  */
    // private function getConfig($key, $default = null)
    // {
        // 1. 优先环境变量（如 PHP_XHS_APP_ID / PHP_XHS_ACCESS_TOKEN）
        // $envKey = 'PHP_XHS_' . strtoupper($key);
        // $envValue = getenv($envKey);
        // if ($envValue !== false && $envValue !== '') {
        //     return $envValue;
        // }

        // // 2. 从 shopro 配置组中获取（需先在 fa_shopro_config 表添加 code=xhs_ad 的配置组）
        // $config = sheep_config('xhs_ad');
        // if ($config && isset($config[$key])) {
        //     return $config[$key];
        // }

    //     return $default;
    // }

    /**
     * HTTP POST (form-urlencoded)
     */
    private function httpPost($url, $data)
    {
        try {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_TIMEOUT, 10);

            $result = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);

            if ($error) {
                custom_log('[xhs.api] curl error: ' . $error, 0, 'xhs_ad', 'error');
                return null;
            }

            if ($httpCode != 200) {
                custom_log('[xhs.api] http error: ' . $httpCode . ', body=' . substr($result, 0, 500), 0, 'xhs_ad', 'error');
                return null;
            }

            return json_decode($result, true) ?: null;
        } catch (\Exception $e) {
            custom_log('[xhs.api] POST 请求异常: ' . $e->getMessage(), 0, 'xhs_ad', 'error');
            return null;
        }
    }

    /**
     * HTTP POST (JSON body)
     */
    private function httpPostJson($url, $data, $headers = [])
    {
        try {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_TIMEOUT, 15);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

            $result = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);

            if ($error) {
                custom_log('[xhs.api] curl error: ' . $error, 0, 'xhs_ad', 'error');
                return null;
            }

            if ($httpCode != 200) {
                custom_log('[xhs.api] http error: ' . $httpCode . ', body=' . substr($result, 0, 500), 0, 'xhs_ad', 'error');
            }

            return json_decode($result, true) ?: null;
        } catch (\Exception $e) {
            custom_log('[xhs.api] POST JSON 请求异常: ' . $e->getMessage(), 0, 'xhs_ad', 'error');
            return null;
        }
    }
}
