<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace app\store\model\goods;

use think\Paginator;
use think\db\exception\DbException;
use app\job\controller\goods\Collector as GoodsCollectorJob;
use app\common\model\goods\Collector as CollectorModel;
use app\common\enum\goods\CollectorStatus as GoodsCollectorStatusEnum;
use cores\exception\BaseException;

/**
 * 商品采集记录模型
 * Class Collector
 * @package app\store\model\goods
 */
class Collector extends CollectorModel
{
    /**
     * 获取采集记录
     * @param array $param
     * @return Paginator
     * @throws DbException
     */
    public function getList(array $param = []): \think\Paginator
    {
        return $this->where($this->getFilter($param))
            ->where('is_delete', '=', 0)
            ->order(['create_time' => 'desc', $this->getPk()])
            ->paginate(10);
    }

    /**
     * 获取查询条件
     * @param array $param
     * @return array
     */
    private function getFilter(array $param = []): array
    {
        // 默认查询参数
        $params = $this->setQueryDefaultValue($param, ['goods_type' => -1, 'status' => -1]);
        // 检索查询条件
        $filter = [];
        $params['status'] > -1 && $filter[] = ['status', '=', (int)$params['status']];
        return $filter;
    }

    /**
     * 执行采集任务`
     * @param array $form
     * @return bool
     * @throws BaseException
     */
    public function batch(array $form): bool
    {
        $urls = $this->getUrls($form);
        // 验证采集的商品数量是否合法
        $this->checkLimit($urls);
        // 新增商品采集记录
        $recordId = $this->addRecord(\count($urls));
        // 调度计划任务
        $this->dispatchJob($urls, $recordId, $form);
        return true;
    }

    /**
     * 获取采集商品url列表
     * @param array $form
     * @return false|string[]
     */
    private function getUrls(array $form)
    {
        return array_filter(explode("\n", $form['urls']));
    }

    /**
     * 调度队列服务执行商品采集
     * @param array $urls 商品url列表
     * @param int $recordId 商品采集记录ID
     * @return void
     */
    private function dispatchJob(array $urls, int $recordId, array $form)
    {
        // 分批每次采集1条
        $limit = 1;
        // 根据商品总数量计算需要的队列任务数量
        $jobCount = \count($urls) / $limit;
        // 逐次发布队列任务
        for ($i = 0; $i < $jobCount; $i++) {
            $data = array_slice($urls, $i * $limit, $limit);
            GoodsCollectorJob::dispatch([
                'urls' => $data,
                'form' => $form,
                'recordId' => $recordId,
                'storeId' => self::$storeId,
            ]);
        }
    }

    /**
     * 新增商品采集记录
     * @param int $totalCount 商品总数量
     * @return int
     */
    private function addRecord(int $totalCount): int
    {
        $this->save([
            'total_count' => $totalCount,
            'start_time' => \time(),
            'fail_log' => [],
            'status' => GoodsCollectorStatusEnum::NORMAL,
            'store_id' => self::$storeId
        ]);
        return (int)$this['id'];
    }

    /**
     * 验证采集的商品数量是否合法
     * @param array $urls
     * @return void
     * @throws BaseException
     */
    private function checkLimit(array $urls): void
    {
        // 判断商品数据是否为空
        if (empty($urls)) {
            throwError('很抱歉,采集的商品数量不能为空');
        }
        // 判断商品数量是否超出100条
        if (\count($urls) > 100) {
            throwError('很抱歉,一次性采集最多不能超过100个商品');
        }
    }

    /**
     * 删除记录
     * @return bool
     */
    public function setDelete(): bool
    {
//        if ($this['status'] == GoodsCollectorStatusEnum::NORMAL) {
//            $this->error = '很抱歉,当前任务没有结束不能删除';
//            return false;
//        }
        return $this->save(['is_delete' => 1]);
    }
}