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

namespace app\common\library\collector\provider\driver;

use app\common\enum\goods\SpecType as GoodsSpecTypeEnum;
use app\common\library\helper;
use app\common\library\collector\provider\Driver;
use cores\exception\BaseException;

/**
 * 阿里巴巴商品采集驱动
 * Class Alibaba
 * @package app\common\library\collector\provider\driver
 */
class Alibaba extends Driver
{
    // API地址
    const API_URL = 'https://api09.99api.com/alibaba/detail';

    /**
     * 获取商品详情
     * @param string $itemId
     * @return array
     * @throws BaseException
     */
    public function detail(string $itemId): array
    {
        $result = $this->curlGet(self::API_URL, $itemId);
        return $this->formatGoods($result['data']);
    }

    /**
     * 格式化商品数据
     * @param array $original
     * @return array
     */
    private function formatGoods(array $original): array
    {
        $data = [];
        // 商品规格
        $data['spec_type'] = !empty($original['skuMap']) ? GoodsSpecTypeEnum::MULTI : GoodsSpecTypeEnum::SINGLE;
        $data['goods_name'] = $original['title'];
        $data['goodsImages'] = $this->goodsImages($original['images']);
        $data['content'] = $this->goodsContent($original['descImgs']);
        $price = \current($original['showPriceRanges'])['price'] ?? '0.00';
        // 整理多规格数据
        if ($data['spec_type'] === GoodsSpecTypeEnum::MULTI) {
            $specList = $this->createSpecList($original['skuProps']);
            $data['specData']['specList'] = $specList;
            $data['specData']['skuList'] = $this->createSkuList($original['skuMap'], $specList, $price, $original['skuProps']);
        } elseif ($data['spec_type'] === GoodsSpecTypeEnum::SINGLE) {
            $data['goods_price'] = $price;
            $data['line_price'] = '0.00';
            $data['stock_num'] = 100;   // 库存数量 (单规格商品没有库存数量 默认100)
            $data['goods_weight'] = 1;  // 重量默认1kg
        }
        return $data;
    }

    /**
     * 创建标准的商品SKU数据
     * @param array $originalSkuList 商品SKU列表
     * @param array $specList 商品规格
     * @param string $defaultPrice 默认价格
     * @param array $skuProps 规格信息 (用于获取缩略图)
     * @return array
     */
    private function createSkuList(array $originalSkuList, array $specList, string $defaultPrice, array $skuProps): array
    {
        // 根据规格数据生成完整的SKU数据 (因为originalSkuList会有不存在的sku)
        $cartesian = $this->cartesian($specList);
        // 整理商品SKU列表
        $skuList = [];
        foreach ($cartesian as $spec) {
            // 设置skuKeys数据
            $skuKeys = [];
            foreach ($spec as $specValue) {
                $skuKeys[] = [
                    'groupKey' => $specValue['groupKey'],
                    'valueKey' => $specValue['key']
                ];
            }
            // 查找已存在的SKU
            $originalSku = $this->findOriginalSku($originalSkuList, $spec);
            // 整理SKU数据
            $skuList[] = [
                'image_id' => 0,
                'goods_price' => $originalSku['price'] ?? $defaultPrice,
                'line_price' => '0.00',
                'stock_num' => $originalSku ? $originalSku['canBookCount'] : 0,    // 库存数量
                'goods_weight' => 1,    // 重量默认1kg
                'goods_sku_no' => $originalSku ? $originalSku['skuId'] : '',
                'skuKeys' => $skuKeys,
                'imageUrl' => $this->findClothesColor($skuProps, $spec),
            ];
        }
        return $skuList;
    }

    /**
     * 查找SKU封面图
     * @param array $skuProps 规格信息
     * @param array $spec
     * @return string
     */
    private function findClothesColor(array $skuProps, array $spec): string
    {
        foreach ($spec as $skuValue) {
            if ($skuValue['groupKey'] != 0) {
                continue;
            }
            foreach ($skuProps as $prop) {
                foreach ($prop['value'] as $value) {
                    if ($skuValue['spec_value'] === $value['name'] && !empty($value['imageUrl'])) {
                        return $this->imageUrl($value['imageUrl'], '_800x800.jpg');
                    }
                }
            }
        }
        return '';
    }

    /**
     * 查找已存在的SKU
     * @param array $originalSkuList
     * @param array $spec
     * @return false|mixed
     */
    private function findOriginalSku(array $originalSkuList, array $spec)
    {
        foreach ($originalSkuList as $key => $item) {
            $skuKey = implode('&gt;', helper::getArrayColumn($spec, 'spec_value'));
            if ($skuKey === $key) {
                return $item;
            }
        }
        return false;
    }

    /**
     * 生成完整的SKU列表(笛卡尔积运算)
     * @param array $specList
     * @param array $tmp
     * @param array $nArr
     * @return int
     */
    private function cartesian(array $specList, array $tmp = [], array $nArr = [])
    {
        foreach (array_shift($specList)['valueList'] as $v) {
            $tmp[] = $v;
            if ($specList) {
                $nArr = $this->cartesian($specList, $tmp, $nArr);
            } else {
                $nArr[] = $tmp;
            }
            array_pop($tmp);
        }
        return $nArr;
    }

    /**
     * 创建标准的商品规格数据(树状)
     * @param array $skuProps 规格信息
     * @return array
     */
    private function createSpecList(array $skuProps): array
    {
        $specList = [];
        foreach ($skuProps as $prop) {
            $groupKey = \count($specList);
            $valueList = [];
            foreach ($prop['value'] as $value) {
                $valueList[] = [
                    'key' => \count($valueList),
                    'groupKey' => $groupKey,
                    'spec_value' => $value['name'],
                ];
            }
            $specList[] = [
                'key' => $groupKey,
                'spec_name' => $prop['prop'],
                'valueList' => $valueList,
            ];
        }
        return $specList;
    }

    /**
     * 格式化商品主图
     * @param array $images
     * @return array
     */
    private function goodsImages(array $images): array
    {
        return array_map(function (string $imageUrl) {
            return $this->imageUrl($imageUrl, '_800x800.jpg');
        }, \array_slice($images, 0, 10));
    }

    /**
     * 格式化图片url
     * @param string $url 图片url
     * @param string $suffix 后缀 (目的是格式化图片尺寸和压缩文件体积)
     * @return string
     */
    private function imageUrl(string $url, string $suffix = ''): string
    {
        if (empty($url)) {
            return '';
        }
        // 补全url协议
        if (\substr($url, 0, 2) === '//') {
            return "https:{$url}{$suffix}";
        }
        if (\substr($url, 0, 4) != 'http') {
            return "https://{$url}{$suffix}";
        }
        // http替换为https
        return str_replace('http://', 'https://', $url) . $suffix;
    }

    /**
     * 格式化商品详情
     * @param array $descImgs
     * @return string
     */
    private function goodsContent(array $descImgs): string
    {
        $content = '';
        foreach ($descImgs as $img) {
            $content .= "<p><img src=\"{$img}\"/></p>";
        }
        return $content;
    }
}