<?php
// addons/shopro/job/TrackProcessJob.php

namespace addons\shopro\job;

use think\queue\Job;
use think\Db;
use think\Queue;

/**
 * 埋点数据处理任务 
 * PV UV 等统计
 */
class TrackProcessJob
{
    /**
     * 执行队列任务
     */
    public function fire(Job $job, $data) {
        try {
            $trackData = $data['data'] ?? [];
            $clientIp = $data['ip'] ?? '';
            $jobTimestamp = isset($data['timestamp']) ? (int)$data['timestamp'] : time();

            if (empty($trackData)) {
                $job->delete();
                return;
            }

            // 批量插入埋点数据
            $this->insertTracks($trackData, $clientIp, $jobTimestamp);

            //  删除任务
            $job->delete();

        } catch (\Exception $e) {
            // 重试机制
            if ($job->attempts() < 3) {
                $job->release(60); // 60秒后重试
            } else {
                // 记录失败数据
                $this->saveFailed($data, $e->getMessage());
                $job->delete();
            }
        }
    }

    /**
     * 批量插入埋点数据
     */
    protected function insertTracks($trackData, $clientIp, $jobTimestamp) {
        $insertData = [];
        $seen = [];

        foreach ($trackData as $item) {
            $trackRow = [
                'user_id' => $item['user_id'] ?? 0,
                'openid' => $item['openid'] ?? '',
                'session_id' => $item['session_id'] ?? '',
                'event_type' => $item['event_type'] ?? '',
                'event_code' => $item['event_code'] ?? '',
                'page_path' => $item['page_path'] ?? '',
                'page_title' => $item['page_title'] ?? '',
                'params' => !empty($item['params']) ? json_encode($item['params']) : '',
                'ip' => $clientIp,
                'create_time' => isset($item['create_time']) ? (int)($item['create_time'] / 1000) : $jobTimestamp
            ];

            $dedupKey = $this->buildTrackDedupKey($trackRow);
            if (isset($seen[$dedupKey])) {
                continue;
            }
            $seen[$dedupKey] = true;

            if ($this->trackExists($trackRow)) {
                continue;
            }

            $insertData[] = $trackRow;
        }

        if (empty($insertData)) {
            return;
        }

        // 分批插入（每批500条）
        $batches = array_chunk($insertData, 500);
        foreach ($batches as $batch) {
            Db::name('shopro_miniprogram_track')->insertAll($batch);
        }
    }

    /**
     * 构建埋点判重键
     */
    protected function buildTrackDedupKey($trackRow)
    {
        return md5(implode('|', [
            (string)$trackRow['user_id'],
            (string)$trackRow['openid'],
            (string)$trackRow['session_id'],
            (string)$trackRow['event_type'],
            (string)$trackRow['event_code'],
            (string)$trackRow['page_path'],
            (string)$trackRow['page_title'],
            (string)$trackRow['params'],
            (string)$trackRow['ip'],
            (string)$trackRow['create_time'],
        ]));
    }

    /**
     * 判断埋点是否已存在
     */
    protected function trackExists($trackRow)
    {
        return Db::name('shopro_miniprogram_track')
            ->where('user_id', $trackRow['user_id'])
            ->where('openid', $trackRow['openid'])
            ->where('session_id', $trackRow['session_id'])
            ->where('event_type', $trackRow['event_type'])
            ->where('event_code', $trackRow['event_code'])
            ->where('page_path', $trackRow['page_path'])
            ->where('page_title', $trackRow['page_title'])
            ->where('params', $trackRow['params'])
            ->where('ip', $trackRow['ip'])
            ->where('create_time', $trackRow['create_time'])
            ->find() ? true : false;
    }

    /**
     * 保存失败数据
     */
    protected function saveFailed($data, $error) {
        Db::name('shopro_miniprogram_track_failed')->insert([
            'data' => json_encode($data),
            'error' => $error,
            'attempts' => 3,
            'create_time' => time()
        ]);
    }


}
