<?php

namespace app\controller\manager\mall;

use app\controller\manager\Base;
use app\controller\manager\Upload;
use app\exception\RepositoryException;
use app\model\mall\SpuLimitTime;
use app\model\sku\SpecParam;
use app\model\sku\SpecValue;
use app\model\sku\SpuType;
use app\model\Spu;
use app\model\Sku as SkuModel;
use Exception;
use think\facade\Db;
use think\response\Json;

class Sku extends Base
{
    protected $noNeedRight = [
        'spuTypeData', 'attrSpecData', 'specValueCreate',
        'specCreate', 'specValueDelete', 'specDelete', 'upload', 'skuData'
    ];

    /**
     * 获取SKU数据
     *
     * @throws Exception
     */
    public function skuData(): Json
    {
        $productId = input('product_id', 0);
        if ($productId == 0) {
            return $this->json(200, 'success', []);
        }

        $spu = Spu::findById($productId, ['id', 'activity_id', 'activity_type', 'multi_spec']);
        $res       = [];

        switch ($spu['activity_type']) {
            case SpuLimitTime::TYPE:
                $where = ['spu_activity_id' => $spu['activity_id'], 'type' => $spu['activity_type']];
                break;
            default:
                $where = ['spu_id' => $productId];
        }

        if ($spu['multi_spec'] > 0) {
            $list = SkuModel::where($where)->whereNull('deleted_at')->whereNotNull('indexes')->select();
            foreach ($list as $item) {
                $key = $item['indexes'];

                $res[sprintf("skus[%s][%s]", $key, 'id')]             = $item['id'];
                $res[sprintf("skus[%s][%s]", $key, 'stock')]          = $item['stock'];
                $res[sprintf("skus[%s][%s]", $key, 'original_price')] = $item['original_price'];
                $res[sprintf("skus[%s][%s]", $key, 'price')]          = $item['price'];
                $res[sprintf("skus[%s][%s]", $key, 'picture')]        = $item['picture'];
                $res[sprintf("skus[%s][%s]", $key, 'is_default')]     = $item['is_default'];
                $res[sprintf("skus[%s][%s]", $key, 'coding')]         = $item['coding'];
                $res[sprintf("skus[%s][%s]", $key, 'status')]         = $item['status'];
            }
        } else {
            $item = SkuModel::where($where)->where('is_default', 1)->find();

            $res['skus[id]']             = $item['id'];
            $res['skus[stock]']          = $item['stock'];
            $res['skus[original_price]'] = $item['original_price'];
            $res['skus[price]']          = $item['price'];
            $res['skus[coding]']         = $item['coding'];
            $res['skus[status]']         = $item['status'];
            $res['skus[is_default]']     = $item['is_default'];
        }

        return $this->json(200, 'success', $res);
    }

    /**
     * 获取商品类型列表
     *
     * @throws Exception
     */
    public function spuTypeData(): Json
    {
        $list = SpuType::where('status', SpuType::COMMON_ON)
            ->order('sort', 'desc')
            ->order('id', 'asc')
            ->field('id,title')
            ->select();

        return $this->json(200, 'success', $list);
    }

    /**
     * 获取商品类型下的规格和属性
     *
     * @throws Exception
     */
    public function attrSpecData(): Json
    {
        $spuTypeId  = input('product_type_id/d');
        $productId  = input('product_id/d', 0);//商品ID

        $spuInfo = Spu::findById($productId, ['id', 'activity_id', 'activity_type', 'multi_spec', 'spec']);

        $selectSpec = [];
        if ($spuInfo) {
            switch ($spuInfo['activity_type']) {
                case SpuLimitTime::TYPE:
                    $selectSpec = SpuLimitTime::where('id', $spuInfo['activity_id'])->value('spec');
                    break;
                default:
                    $selectSpec = $spuInfo['spec'];
            }
            $selectSpec = json_decode($selectSpec, true);
        }

        $specIds    = SpuType::where('id', $spuTypeId)->value('spec_ids');
        $specIdArr  = explode(',', $specIds);
        $list       = SpecParam::whereIn('id', $specIdArr)
            ->where('status', SpecParam::COMMON_ON)
            ->with([
                'specValue' => function ($q) {
                    $q->where('status', SpecValue::COMMON_ON)->order('sort', 'desc')->order('id', 'asc');
                }
            ])
            ->order('sort', 'desc')
            ->order('id', 'asc')
            ->field('id,title')
            ->select();
        $spec       = [];//规格
        $attr       = [];//属性
        $list->each(function ($item) use (&$spec, $selectSpec) {
            $arr            = [];
            $arr['id']      = (string) $item->id;
            $arr['title']   = $item->title;
            $arr['options'] = $item->specValue->each(function ($spec) {
                $spec->id = (string) $spec->id;
                unset($spec->sort);
                unset($spec->spec_id);
                unset($spec->status);
                unset($spec->created_at);
                unset($spec->updated_at);
            });
            $arr['value']   = $selectSpec[$item->id] ?? [];
            $spec[]         = $arr;
        });

        return $this->json(200, 'success', ['spec' => $spec, 'attribute' => $attr]);
    }

    /**
     * 创建规格值
     *
     * @throws Exception
     */
    public function specValueCreate(): Json
    {
        $params = input('post.');
        $rules  = [
            'spec_id|规格ID' => 'require|number',
            'title|规格值'    => 'require',
        ];

        $validate = $this->validateByApi($params, $rules);

        if ($validate !== true) {
            return $validate;
        }

        $count = SpecValue::where('spec_id', $params['spec_id'])
            ->where('title', $params['title'])
            ->where('status', SpecValue::COMMON_ON)
            ->count();
        if ($count > 0) {
            return $this->json(4000, '规格值已存在');
        }

        $value = SpecValue::create([
            'spec_id' => $params['spec_id'],
            'title'   => $params['title'],
        ]);

        return $this->json(200, 'success', ['id' => $value->id]);
    }

    /**
     * 创建规格
     *
     * @return bool|Json
     * @throws Exception
     */
    public function specCreate()
    {
        $params = input('post.');
        $rules  = [
            'product_type_id|商品类型' => 'require|number',
            'title|规格名称'           => 'require',
        ];

        $validate = $this->validateByApi($params, $rules);

        if ($validate !== true) {
            return $validate;
        }

        $count = SpecParam::where('spu_type_id', $params['product_type_id'])
            ->where('title', $params['title'])
            ->where('status', SpecParam::COMMON_ON)
            ->count();
        if ($count > 0) {
            return $this->json(4000, '规格名称已存在');
        }

        $param = SpecParam::create([
            'spu_type_id' => $params['product_type_id'],
            'title'       => $params['title'],
        ]);

        $specIds = SpecParam::where('spu_type_id', $params['product_type_id'])->column('id');
        // 更新商品类型
        SpuType::where('id', $params['product_type_id'])->save(['spec_ids' => implode(',', $specIds)]);

        return $this->json(200, 'success', ['id' => $param->id]);
    }

    /**
     * 规格删除
     *
     * @return Json
     * @throws Exception
     */
    public function specDelete(): Json
    {
        $id = input('post.id/d', 0);
        if ($id <= 0) {
            return $this->json(4000, '参数错误');
        }

        SpecParam::where('id', $id)->save(['status' => -1]);
        SpecValue::where('spec_id', $id)->save(['status' => -1]);

        return $this->json(200, 'success');
    }

    /**
     * 规格值删除
     *
     * @return Json
     * @throws Exception
     */
    public function specValueDelete(): Json
    {
        $id = input('post.id/d', 0);
        if ($id <= 0) {
            return $this->json(4000, '参数错误');
        }

        SpecValue::where('id', $id)->save(['status' => -1]);

        return $this->json(200, 'success');
    }

    /**
     * 上传图片
     *
     * @return Json
     */
    public function upload(): Json
    {
        // 字段名 image-image避免冲突 layui组件自动生成的隐藏file input框中name容易重名冲突
        $image = request()->file('file');
        try {
            $res        = (new Upload())->uploadImage($image);
            $res['url'] = $res['src'];
            return $this->json(200, '上传成功', $res);
        } catch (RepositoryException $e) {
            return $this->json(1, $e->getMessage());
        }
    }
}