<?php

namespace app\admin\controller\shopro\traits;

use app\admin\model\shopro\goods\Goods as GoodsModel;
use app\admin\model\shopro\goods\Sku as SkuModel;
use app\admin\model\shopro\goods\SkuPrice as SkuPriceModel;
use addons\shopro\traits\StockWarning as StockWarningTrait;

trait SkuPrice
{
    use StockWarningTrait;

    /**
     * 编辑规格
     *
     * @param GoodsModel $goods
     * @param array $sku
     * @param string $type
     * @return void
     */
    private function editSku($goods, $type = 'add')
    {
        if ($goods['is_sku']) {
            // 多规格
            $this->editMultiSku($goods, $type);
        } else {
            $this->editSimSku($goods, $type);
        }
    }


    /**
     * 添加编辑单规格
     *
     * @param GoodsModel $goods
     * @param string $type
     * @return void
     */
    protected function editSimSku($goods, $type = 'add')
    {
        $params = $this->request->only([
            'stock',
            'stock_warning',
            'sn',
            'weight',
            'cost_price',
            'original_price',
            'price'
        ]);

        $data = [
            "goods_sku_ids" => null,
            "goods_sku_text" => null,
            "image" => null,
            "goods_id" => $goods->id,
            "stock" => $params['stock'] ?? 0,
            "stock_warning" => isset($params['stock_warning']) && is_numeric($params['stock_warning'])
                ? $params['stock_warning'] : null,
            "sn" => $params['sn'] ?? "",
            "weight" => isset($params['weight']) ? floatval($params['weight']) : 0,
            "cost_price" => $params['cost_price'] ?? 0,
            "original_price" => $params['original_price'] ?? 0,
            "price" => $params['price'] ?? 0,
            "status" => 'up'
        ];

        if ($type == 'edit') {
            // 查询
            $skuPrice = SkuPriceModel::where('goods_id', $goods->id)->order('id', 'asc')->find();
            if ($skuPrice) {
                // 删除多余的这个商品的其他规格以及规格项(防止多规格改为了单规格，遗留一批多余的 sku_price)
                SkuPriceModel::where('goods_id', $goods->id)->where('id', '<>', $skuPrice->id)->delete();
                SkuModel::where('goods_id', $goods->id)->delete();
            }

            unset($data['stock']);      // 移除库存(库存只能通过补货增加)
        }

        if (!isset($skuPrice) || !$skuPrice) {
            $skuPrice = new SkuPriceModel();
        }

        $skuPrice->save($data);
        if ($type == 'add') {
            // 增加补货记录
            $this->addStockLog($skuPrice, 0, $data['stock'], $type);

            // 检测库存预警
            $this->checkStockWarning($skuPrice, $type);
        }
    }


    /**
     * 添加编辑多规格
     * 
     * @param GoodsModel $goods
     * @param string $type
     * @return void
     */
    protected function editMultiSku($goods, $type = 'add')
    {
        $params = $this->request->only([
            'skus',
            'sku_prices'
        ]);
        $skus = $params['skus'] ?? [];
        $skuPrices = $params['sku_prices'] ?? [];

        $this->checkMultiSku($skus, $skuPrices);

        // 编辑保存规格项
        $optionsMap = $this->saveSkus($goods, $skus);

        if ($type == 'edit') {
            // 编辑旧商品，先删除老的不用的 skuPrice
            $oldSkuPriceIds = array_column($skuPrices, 'id');
            // 删除当前商品老的除了在基础上修改的skuPrice
            SkuPriceModel::where('goods_id', $goods->id)
                ->whereNotIn('id', $oldSkuPriceIds)->delete();

            // 删除失效的库存预警记录
            $this->delNotStockWarning($oldSkuPriceIds, $goods->id);
        }

        $min_price = min(array_column($skuPrices, 'price'));        // 规格最小价格
        $originPrices = array_filter(array_column($skuPrices, 'original_price'));
        $min_original_price = $originPrices ? min($originPrices) : 0;        // 规格最小划线价格
        foreach ($skuPrices as $key => &$skuPrice) {
            $skuPrice['goods_sku_ids'] = $this->getRealOptionIds($skuPrice['optionTempIds'], $optionsMap);
            $skuPrice['goods_id'] = $goods->id;
            $skuPrice['goods_sku_text'] = is_array($skuPrice['goods_sku_text']) ? join(',', $skuPrice['goods_sku_text']) : $skuPrice['goods_sku_text'];
            $skuPrice['stock_warning'] = isset($skuPrice['stock_warning']) && is_numeric($skuPrice['stock_warning'])
                ? $skuPrice['stock_warning'] : null;        // null 为关闭商品库存预警， 采用默认库存预警

            // 移除无用 属性
            if ($type == 'add') {
                // 添加直接移除 id
                unset($skuPrice['id']);
            }
            unset($skuPrice['optionTempIds']);       // 前端临时规格 id,查找真实 id 用
            unset($skuPrice['temp_id']);                  // 前端临时 id
            unset($skuPrice['createtime'], $skuPrice['updatetime']);      // 删除时间戳

            $skuPriceModel = new SkuPriceModel();
            if (isset($skuPrice['id']) && $skuPrice['id']) {
                // type == 'edit' 
                unset($skuPrice['stock']);      // 编辑商品 不能编辑库存，只能通过补货
                $skuPriceModel = $skuPriceModel->find($skuPrice['id']);
            }

            if ($skuPriceModel) {
                $skuPriceModel->allowField(true)->save($skuPrice);

                if ($type == 'add') {
                    // 增加补货记录
                    $this->addStockLog($skuPriceModel, 0, $skuPrice['stock'], 'add');      // 记录库存记录

                    // 检测库存预警
                    $this->checkStockWarning($skuPriceModel, $type);
                }
            }

        }

        // 重新赋值最小价格和原价
        $goods->original_price =  $min_original_price;  // 最小价格规格对应的原价
        $goods->price = $min_price;
        $goods->save();
    }


    /**
     * 校验多规格是否填写完整
     * 
     * @param array $skus
     * @param array $skuPrices
     * @return void
     */
    private function checkMultiSku($skus, $skuPrices)
    {
        if (count($skus) < 1) {
            error_stop('请填写规格列表');
        }
        foreach ($skus as $key => $sku) {
            if (count($sku['children']) <= 0) {
                error_stop('主规格至少要有一个子规格');
            }
            if (!isset($sku['name']) || empty(trim($sku['name']))) {
                error_stop('主规格名称不能为空');
            }

            // 验证子规格不能为空
            foreach ($sku['children'] as $k => $child) {
                if (!isset($child['name']) || empty(trim($child['name']))) {
                    error_stop('子规格名称不能为空');
                }
            }
        }

        if (count($skuPrices) < 1) {
            error_stop('请填写规格价格');
        }

        foreach ($skuPrices as &$price) {
            // 校验多规格属性
            $this->svalidate($price, '.sku_params');
        }
    }



    /**
     * 根据前端临时 temp_id 获取真实的数据库 id
     *
     * @param string $newGoodsSkuIds
     * @param array $optionsMap
     * @return string
     */
    private function getRealOptionIds($optionTempIds, $optionsMap)
    {
        $newIds = [];
        $ids = explode(',', $optionTempIds);
        foreach ($ids as $id) {
            $newIds[] = $optionsMap[$id];
        }
        return join(',', $newIds);
    }


    /**
     * 差异更新 规格规格项（多的删除，少的添加）
     *
     * @param array $skus
     * @return array
     */
    private function saveSkus($goods, $skus)
    {
        $optionsMap = [];
        $saveSkuIds = [];
        // 添加主规格
        foreach ($skus as &$sku) {
            $skuId = isset($sku['id']) ? (int)$sku['id'] : 0;
            if ($skuId > 0) {
                // 更新
                SkuModel::where('id', $skuId)->update([
                    'name' => $sku['name'],
                    'image' => $sku['image'] ?? null,
                    'parent_id' => 0,
                    'goods_id' => $goods->id,
                    'weigh' => $sku['weigh'],
                ]);
            } else {
                // 新增
                $skuModel = new SkuModel();
                $skuModel->save([
                    'name' => $sku['name'],
                    'image' => $sku['image'] ?? null,
                    'parent_id' => 0,
                    'goods_id' => $goods->id,
                    'weigh' => $sku['weigh'],
                ]);
                $skuId = $skuModel->id;
            }
            $saveSkuIds[] = $skuId;

            foreach ($sku['children'] as &$option) {
                $optionId = isset($option['id']) ? (int)$option['id'] : 0;
                if ($optionId > 0) {
                    // 更新
                    SkuModel::where('id', $optionId)->update([
                        'name' => $option['name'],
                        'image' => $option['image'] ?? null,
                        'weigh' => $option['weigh'],
                        'parent_id' => $skuId,
                        'goods_id' => $goods->id,
                    ]);
                } else {
                    // 新增
                    $skuModel = new SkuModel();
                    $skuModel->save([
                        'name' => $option['name'],
                        'image' => $option['image'] ?? null,
                        'weigh' => $option['weigh'],
                        'parent_id' => $skuId,
                        'goods_id' => $goods->id
                    ]);
                    $optionId = $skuModel->id;
                }

                $optionsMap[$option['temp_id']] = $optionId;
                $saveSkuIds[] = $optionId;
            }
        }
        // 差异删除不需要的主规格
        SkuModel::where('goods_id', $goods->id)->whereNotIn('id', $saveSkuIds)->delete();

        return $optionsMap;
    }
}
