<?php
declare (strict_types=1);

namespace app\command;

use app\common\enum\CommonEnum;
use app\common\enum\store\ProductEnum;
use app\common\repositories\douhuomall\DouhuomallChangeLogRepository;
use app\common\repositories\store\product\ProductRepository;
use app\entity\data\douhuomall\DouhuomallChangeLogEntity;
use app\traits\GongApiRequest;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\db\exception\DbException;
use think\facade\Db;
use think\facade\Log;

class WiwibaoProductSync extends Command
{

    use GongApiRequest;

    // 配置参数
    protected $config = [
        'page_size' => 100,      // 每页拉取数量
        'max_pages' => 0,       // 最大页数限制
        'price_change_rate' => 0.0, // 价格变动比率阈值（10%）
        'mer_id' => CommonEnum::DESIGN_MERCHANT_ID['WonderfulLiving']['code']
    ];

    protected function configure()
    {
        // 指令配置
        $this->setName('wiwibaoproductsync')
            ->setDescription('the wiwibaoproductsync command');
    }

    protected function execute(Input $input, Output $output)
    {
        $output->writeln('定时任务执行中...');

        $this->syncGoodsFromGong();

        $output->writeln('定时任务执行完成');
    }

    /**
     * 同步微唯宝商品数据（主方法）
     */
    public function syncGoodsFromGong()
    {
        try {
            set_time_limit(0);

            // 1. 批量拉取所有商品数据
            $allProducts = $this->fetchAllProducts();

            if (empty($allProducts)) {
                Log::info('未拉取到任何商品数据');
                return 'success';
            }

            // 2. 获取本地所有SPU ID
            $douhuomallDataMap = [];
            $douhuomallDataList = Db::name('douhuomall')
                ->select()
                ->toArray();
            if (!empty($douhuomallDataList)) {
                $douhuomallDataMap = array_column($douhuomallDataList, null, 'spu_id');

            }
            $syncedSpuIds = [];

            // 3. 批量处理商品数据
            foreach ($allProducts as $product) {
                try {
                    $spuId = $this->processSingleProduct($product, $douhuomallDataMap[$product['goods_id']] ?? []);
                    if ($spuId) {
                        $syncedSpuIds[] = $spuId;
                    }
                } catch (\Exception $e) {
                    $this->logError("处理商品 {$product['goods_id']} 失败: ", $e);
                    continue;
                }
            }

            // 4. 处理需要下架的商品（本地有但第三方已下架）
            $this->handleOfflineProducts($syncedSpuIds, $douhuomallDataMap);

            return 'success';

        } catch (\Exception $e) {
            $this->logError('商品同步失败', $e);
            return 'error';
        }
    }

    /**
     * 批量拉取所有商品数据
     */
    protected function fetchAllProducts()
    {
        $allData = [];

        // 第一页
        $firstPageData = GongApiRequest::get_goods_list(1, $this->config['page_size']);
        if (empty($firstPageData['list'])) {
            return [];
        }

        $allData = $firstPageData['list'];
        $totalPages = $firstPageData['pages'] ?? 1;
        if (!empty($this->config['max_pages'])) {
            $totalPages = min($totalPages, $this->config['max_pages']);
        }

        // 并行获取剩余页面
        for ($page = 2; $page <= $totalPages; $page++) {
            $pageData = GongApiRequest::get_goods_list($page, $this->config['page_size']);
            if (!empty($pageData['list'])) {
                $allData = array_merge($allData, $pageData['list']);
            }
        }

        return $allData;
    }

    /**
     * 处理单个商品
     */
    protected function processSingleProduct($productData, $douhuomallData)
    {
        $goodsId = $productData['goods_id'];

        // 1. 获取商品详情
        $goodsInfo = GongApiRequest::get_goods_info($goodsId);
        if (!$goodsInfo) {
            return null;
        }

        // 2. 处理SKU信息
        if (empty($goodsInfo['sku_list'])) {
            return null;
        }
        $skuInfo = [];
        foreach ($goodsInfo['sku_list'] as $sku) {
            if (empty($sku['plat_price'])) {
                continue;
            }
            $processedSku = [
                'sku_id' => $sku['sku_id'] ?? 0,
                'plat_price' => $sku['plat_price'],
                'img_url' => $sku['main_img'],
                'retail_price' => $sku['retail_price'] ?? 0,
                'cost_price' => $this->calculateCostPrice($sku['plat_price']),
                'market_price' => $this->calculateMarketPrice($sku['plat_price']),
                'profit' => $this->calculateProfit($sku['plat_price']),
                'mer_profit' => $this->calculateMerProfit($sku['plat_price']),
                'yanglaojin' => '0.00',
                'main_img' => $sku['main_img'] ?? '',
                'attribute_json' => !empty($sku['attr']) ? $sku['attr'] : [['val' => '默认', 'name' => '默认']]
            ];
            $skuInfo[] = array_merge($sku, $processedSku);
        }

        // 4. 构建保存数据
        $imageData = [
            'cover_url' => $goodsInfo['main_img'] ?? '',
            'detail_images' => $goodsInfo['detail_img'] ?? [],
            'detail_img_list' => $goodsInfo['detail_img'] ?? [] // 为了兼容以前写的代码，建议保留这个数据项，之前用的是detail_img_list字段，但我感觉他们意义一样
        ];

        // 构建详情HTML
        $detailHtml = $this->buildDetailHtml($imageData['detail_images']);

        $saveData = [
            'spu_id' => $goodsInfo['goods_id'],
            'skuId_info' => $skuInfo,
            'sys_id' => '112',
            'goods_id' => $goodsInfo['goods_id'],
            'spuId_info' => array_merge(
                $goodsInfo,
                [
                    'cover_url' => $imageData['cover_url'],
                    'detail' => $detailHtml,
                    'detail_img_list' => $imageData['detail_img_list']
                ]
            ),
            'sku_id' => $skuInfo[0]['sku_id'] ?? 0,
            'status' => $goodsInfo['status'] ?? 0,
            'cate_ids' => $goodsInfo['cate_ids'] ?? '',
            'title' => $goodsInfo['spu_name'] ?? '',
            'cxb_cate_id' => 0,
            'third_update_time' => $goodsInfo['update_time'] ?? ''
        ];

        // 5. 保存到本地（使用原有的add方法逻辑）
        try {
            $spuId = $this->addToDouhuomall($saveData, $douhuomallData);
        } catch (DbException $e) {
            return 0;
        }

        return $spuId;
    }

    /**
     * 构建详情HTML
     */
    protected function buildDetailHtml($detailImages): string
    {
        if (empty($detailImages)) {
            return '';
        }

        $detailHtml = '';
        foreach ((array)$detailImages as $imgUrl) {
            $detailHtml .= "<img src='{$imgUrl}' referrerpolicy='no-referrer' />";
        }

        return $detailHtml;
    }

    /**
     * @param $data
     * @param $findData
     * @return mixed
     * @throws DbException
     */
    protected function addToDouhuomall($data, $findData)
    {
        try {
            // 对SKU按成本价排序，获取最低成本价的SKU
            $skuInfo = $this->arrSort($data['skuId_info'], 'cost_price', SORT_ASC);

            // 计算价格字段
            $data['cost_price'] = $skuInfo[0]['cost_price'] ?? 0;
            $data['market_price'] = $skuInfo[0]['market_price'] ?? 0;
            $data['ot_price'] = $skuInfo[0]['retail_price'] ?? 0;
            $data['mer_profit'] = $skuInfo[0]['mer_profit'] ?? 0;
            $data['pension'] = $skuInfo[0]['yanglaojin'] ?? 0;
            $data['profit'] = (empty($data['cost_price']) || empty($data['market_price']))
                ? 0
                : bcdiv((string)$data['market_price'], (string)$data['cost_price'], 2);

            $now = date('Y-m-d H:i:s');

            if (empty($findData)) {
                // 新增
                $insertData = [
                    'spu_id' => $data['spu_id'],
                    'skuId_info' => json_encode($data['skuId_info'], JSON_UNESCAPED_UNICODE),
                    'sys_id' => $data['sys_id'],
                    'goods_id' => $data['goods_id'],
                    'spuId_info' => json_encode($data['spuId_info'], JSON_UNESCAPED_UNICODE),
                    'create_time' => $now,
                    'update_time' => $now,
                    'sku_id' => $data['sku_id'],
                    'status' => $data['status'],
                    'cate_ids' => $data['cate_ids'],
                    'title' => $data['title'],
                    'cost_price' => $data['cost_price'],
                    'market_price' => $data['market_price'],
                    'ot_price' => $data['ot_price'],
                    'profit' => $data['profit'],
                    'mer_profit' => $data['mer_profit'],
                    'pension' => $data['pension'],
                    'cxb_cate_id' => $data['cxb_cate_id'],
                    'third_update_time' => $data['third_update_time']
                ];
                Db::name('douhuomall')->insert($insertData);

                // 创建完商品后立马上架
                $this->insert_product($data['spu_id'], $this->config['mer_id']);

            } else {
                // 更新
                if (empty($findData['third_update_time']) || strtotime($data['third_update_time']) > strtotime($findData['third_update_time'])) {
                    $updateData = [
                        'status' => $data['status'],
                        'update_time' => $now,
                        'cost_price' => $data['cost_price'],
                        'market_price' => $data['market_price'],
                        'ot_price' => $data['ot_price'],
                        'mer_profit' => $data['mer_profit'],
                        'pension' => $data['pension'],
                        'profit' => $data['profit'],
                        'skuId_info' => json_encode($data['skuId_info'], JSON_UNESCAPED_UNICODE),
                        'spuId_info' => json_encode($data['spuId_info'], JSON_UNESCAPED_UNICODE),
                        'title' => $data['title'],
                        'cate_ids' => $data['cate_ids'],
                        'cxb_cate_id' => $data['cxb_cate_id'],
                        'third_update_time' => $data['third_update_time']
                    ];
                    Db::name('douhuomall')
                        ->where('spu_id', $findData['spu_id'])
                        ->update($updateData);

                    $productList = Db::name('store_product')
                        ->where('spu_id', $findData['spu_id'])
                        // ->where('is_show', ProductEnum::IS_SHOW['Yes']['code'])
                        ->where('is_del', ProductEnum::IS_DEL['No']['code'])
                        // ->where('status', '<>', ProductEnum::STATUS['Withdrawn']['code'])
                        ->select()
                        ->toArray();
                    $productIdList = array_column($productList, 'product_id');

                    // 将绑定的商品进行下架
                    Db::name('store_product')
                        ->whereIn('product_id', $productIdList)
                        ->update([
                            // 'is_show' => ProductEnum::IS_SHOW['No']['code'],
                            'is_del' => ProductEnum::IS_DEL['Yes']['code'],
                            // 'status' => ProductEnum::STATUS['Withdrawn']['code'],
                            // 'is_status' => ProductEnum::IS_STATUS['Automatic']['code']
                        ]);

                    /** @var DouhuomallChangeLogEntity $douhuomallChangeLogEntity */
                    $douhuomallChangeLogEntity = DouhuomallChangeLogEntity::newInstance();
                    $douhuomallChangeLogEntity->setSpuId($findData['spu_id'])
                        ->setDataJson($findData)
                        ->setEffectProductJson($productIdList)
                        ->setCreateTime(date('Y-m-d H:i:s'));
                    /** @var DouhuomallChangeLogRepository $douhuomallChangeLogRepository */
                    $douhuomallChangeLogRepository = app()->make(DouhuomallChangeLogRepository::class);
                    $douhuomallChangeLogRepository->createByEntity($douhuomallChangeLogEntity);

                    // 将商品重新上架
                    // 创建完商品后立马上架
                    $this->insert_product($data['spu_id'], $this->config['mer_id']);
                }
            }

            return $data['spu_id'];

        } catch (\Exception $e) {
            $this->logError('保存商品到douhuomall失败: ', $e);
            throw $e;
        }
    }

    /**
     * 恢复商品上架状态
     */
    protected function restoreProduct($spuId)
    {
        Db::name('store_product')
            ->where('spu_id', $spuId)
            ->update([
                'is_show' => ProductEnum::IS_SHOW['Yes']['code'],
                'status' => ProductEnum::STATUS['Approved']['code']
            ]);

        Log::info("恢复商品上架（恢复到仓库中）状态: spu_id={$spuId}");
    }

    /**
     * 处理需要下架的商品（第三方已下架）
     */
    protected function handleOfflineProducts($syncedSpuIds, $douhuomallDataMap)
    {
        $localSpuIds = array_keys($douhuomallDataMap);
        $offlineSpuIds = array_diff($localSpuIds, $syncedSpuIds);

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

        $productList = Db::name('store_product')
            ->whereIn('spu_id', $offlineSpuIds)
            // ->where('is_show', ProductEnum::IS_SHOW['Yes']['code'])
            ->where('is_del', ProductEnum::IS_DEL['No']['code'])
            // ->where('status', '<>', ProductEnum::STATUS['Withdrawn']['code'])
            ->field('product_id, spu_id, is_show, is_del, status')
            ->select()
            ->toArray();
        if (empty($productList)) {
            return;
        }
        $productIdList = [];
        $spuIdMap = [];
        foreach ($productList as $item) {
            $productIdList[] = $item['product_id'];
            $spuIdMap[$item['spu_id']][] = $item['product_id'];
        }

        // 将绑定的商品进行下架
        Db::name('store_product')
            ->whereIn('product_id', $productIdList)
            ->update([
                // 'is_show' => ProductEnum::IS_SHOW['No']['code'],
                'is_del' => ProductEnum::IS_DEL['Yes']['code'],
                // 'status' => ProductEnum::STATUS['Withdrawn']['code'],
                // 'is_status' => ProductEnum::IS_STATUS['Automatic']['code']
            ]);
        foreach ($spuIdMap as $spuId => $productIdListGroupBySpuId) {
            /** @var DouhuomallChangeLogEntity $douhuomallChangeLogEntity */
            $douhuomallChangeLogEntity = DouhuomallChangeLogEntity::newInstance();
            $douhuomallChangeLogEntity->setSpuId($spuId)
                ->setDataJson($douhuomallDataMap[$spuId])
                ->setEffectProductJson($productIdListGroupBySpuId)
                ->setCreateTime(date('Y-m-d H:i:s'));
            /** @var DouhuomallChangeLogRepository $douhuomallChangeLogRepository */
            $douhuomallChangeLogRepository = app()->make(DouhuomallChangeLogRepository::class);
            $douhuomallChangeLogRepository->createByEntity($douhuomallChangeLogEntity);
        }

        // foreach ($offlineSpuIds as $spuId) {
        //     $this->offlineProductBySpuId($spuId, 'third_party_offline');
        // }

        Log::info("下架第三方已下架商品" . json_encode(['count' => count($offlineSpuIds), 'spu_ids' => $offlineSpuIds]));
    }

    /**
     * 数组排序（从原有add方法中提取）
     */
    protected function arrSort($array, $keys, $sort = SORT_DESC)
    {
        $keysValue = [];
        foreach ($array as $k => $v) {
            $keysValue[$k] = $v[$keys] ?? 0;
        }
        array_multisort($keysValue, $sort, $array);
        return $array;
    }

    /**
     * 计算成本价
     */
    protected function calculateCostPrice($platPrice)
    {
        return bcadd((string)$platPrice, bcmul((string)$platPrice, '0.03', 4), 2);
    }

    /**
     * 计算市场价
     */
    protected function calculateMarketPrice($platPrice)
    {
        $costPrice = $this->calculateCostPrice($platPrice);
        return bcadd($costPrice, bcmul($costPrice, '0.2', 4), 2);
    }

    /**
     * 计算利润率
     */
    protected function calculateProfit($platPrice)
    {
        $costPrice = $this->calculateCostPrice($platPrice);
        $marketPrice = $this->calculateMarketPrice($platPrice);
        return bcdiv($marketPrice, $costPrice, 2);
    }

    /**
     * 计算毛利
     */
    protected function calculateMerProfit($platPrice)
    {
        $costPrice = $this->calculateCostPrice($platPrice);
        $marketPrice = $this->calculateMarketPrice($platPrice);
        return bcsub($marketPrice, $costPrice, 2);
    }

    /**
     * 记录错误
     */
    protected function logError($message, \Exception $e)
    {
        $errorInfo = [
            'message' => $message,
            'error_message' => $e->getMessage(),
            'error_file' => $e->getFile(),
            'error_line' => $e->getLine(),
            'error_code' => $e->getCode(),
            'exception_class' => get_class($e),
            'trace' => $e->getTraceAsString()
        ];
        Log::error($message);

        Log::error($message . json_encode($errorInfo, JSON_UNESCAPED_UNICODE));

        Db::name('log')->insert([
            'data' => json_encode($errorInfo, JSON_UNESCAPED_UNICODE),
            'time' => date('Y-m-d H:i:s')
        ]);
    }

    // 借用 app\controller\merchant\gong\Goods.php 控制器内方法

    /**
     * 将 微唯宝商品 选品（加入） 到系统内部商户商品表
     * @param $spu_id
     * @param $mer_id
     * @return bool
     */
    public function insert_product($spu_id, $mer_id)
    {
        try {
            // 1、获取商品信息
            $data = Db::name('douhuomall')->where('spu_id', $spu_id)->find();

            // 2、是否为多规格
            $sku_data = json_decode($data['skuId_info'], true);
            $spec_type = count($sku_data);
            if ($spec_type > 1) {
                $spec_type = 1;
            } else {
                $spec_type = 0;
            }

            // 3、商品主图
            $spuId_info = json_decode($data['spuId_info'], true);
            $slider_image = $spuId_info['detail_img_list'] ?? '';
            $image = $spuId_info['cover_url'] ?? '';
            if (empty($slider_image)) {
                $slider_image = $image;
            } else if (is_string($slider_image)) {
                $slider_image = implode(',', json_decode($slider_image, true));
            } else if (is_array($slider_image)) {
                $slider_image = implode(',', $slider_image);
            }
            $yanglaojin_scale = (!empty($data['pension']) && !empty($data['market_price'])) ? bcdiv($data['pension'], $data['market_price'], 2) : 0;

            // 4、商品入库数据
            $product_insert_data = [
                'mer_id' => $mer_id,
                'image' => $image,
                'slider_image' => $slider_image,
                'store_name' => $data['title'],
                'store_info' => 1,
                'keyword' => mb_substr($data['title'], 0, 3),
                'is_show' => 1,
                'status' => 1,
                'cate_id' => $data['cate_ids'],
                'unit_name' => '个',
                'price' => $data['market_price'],
                'cost' => $data['cost_price'],
                'ot_price' => $data['ot_price'],
                'stock' => '1000',
                'spec_type' => $spec_type,
                'extension_type' => 1,
                'mer_status' => 1,
                'is_used' => 1,
                'old_product_id' => $data['id'],
                'volunteer' => 0,
                'type' => 1,
                'pension' => '0.00',
                'commission' => 5,
                'spu_id' => $data['spu_id'],
                'temp_id' => 105,
                'plate_mer_profit' => $data['mer_profit'],
                'concession_pri' => $data['mer_profit'],
                'yanglaojin_scale' => $yanglaojin_scale
            ];
            $insert_id = Db::name('store_product')->insertGetId($product_insert_data);

            // 5、更新商品详情表
            $detail = $spuId_info['detail'];
            if (!is_null(json_decode($detail))) {
                $detail_list = json_decode($detail);
                $detail = '';
                foreach ($detail_list as $value) {
                    $detail .= '<img src="' . $value . '"></img>';
                }
            }
            Db::name('store_product_content')->insert(['content' => $detail, 'product_id' => $insert_id]);

            // 6、
            $this->insert_sku($insert_id, $sku_data);
            return true;
        } catch (\Exception $e) {
            $this->logError($spu_id . "加入选品失败：", $e);
            return false;
        }
    }

    // 借用 app\controller\merchant\gong\Goods.php 控制器内方法
    public function insert_sku($id, $data)
    {
        // 1、获取 所有SKU的 规格属性值
        $sku_attr_data = array_column($data, 'attribute_json');
        $name = '';

        // 2、写入 商品属性表
        /** @var ProductRepository $ProductRepository */
        $ProductRepository = app()->make(ProductRepository::class);
        if (empty($sku_attr_data[0][0])) {
            // 写入商品属性表
            Db::name('store_product_attr')->insert(['product_id' => $id, 'attr_name' => '规格', 'attr_values' => $name]);
            $key = '';
            $num = 1;
            // 写入 SKU 商品属性值表
            foreach ($data as $k => $v) {
                Db::name('store_product_attr_value')->insert([
                    'product_id' => $id,
                    'detail' => json_encode(['规格' => $key]),
                    'sku' => $key,
                    'image' => $v['img_url'],
                    'cost' => $v['cost_price'],
                    'ot_price' => $v['retail_price'],
                    'price' => $v['market_price'],
                    'unique' => $ProductRepository->setUnique($id, $v['sku_id'], 0),
                    'stock' => 100,
                    'cost_price' => $v['cost_price'],
                    'extension_one' => 5,
                    'gong_sku_id' => $v['sku_id'],
                    'gong_mer_profit' => $v['mer_profit'],
                    'gong_pension' => $v['yanglaojin'],
                    'gong_market_price' => $v['market_price'],
                    'plate_mer_profit' => $v['mer_profit']
                ]);
                $key = '';
                $num++;
            }
        } else {
            foreach ($sku_attr_data as $kk => $vv) {
                foreach ($vv as $k1 => $v1) {
                    $name .= $v1['val'];
                }
                $name .= '-!-';
            }
            $name = rtrim($name, '-!-');
            Db::name('store_product_attr')->insert(['product_id' => $id, 'attr_name' => '规格', 'attr_values' => $name]);
            $key = '';
            $num = 1;
            foreach ($data as $k => $v) {
                foreach ($v['attribute_json'] as $k2 => $v2) {
                    $key .= $v2['val'];
                }

                Db::name('store_product_attr_value')->insert([
                    'product_id' => $id,
                    'detail' => json_encode(['规格' => $key]),
                    'sku' => $key,
                    'image' => $v['img_url'],
                    'cost' => $v['cost_price'],
                    'ot_price' => $v['retail_price'],
                    'price' => $v['market_price'],
                    'unique' => $ProductRepository->setUnique((int)$id, $v['sku_id'], 0),
                    'stock' => 100,
                    'cost_price' => $v['cost_price'],
                    'extension_one' => 5,
                    'gong_sku_id' => $v['sku_id'],
                    'gong_mer_profit' => $v['mer_profit'],
                    'gong_pension' => $v['yanglaojin'],
                    'gong_market_price' => $v['market_price'],
                    'plate_mer_profit' => $v['mer_profit']
                ]);
                $key = '';
                $num++;
            }
        }
    }
}
