package com.cyksj.web.controller.manage.goods;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.annotation.Log;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.Jsons;
import com.cyksj.dto.Result;
import com.cyksj.enums.BusinessType;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.model.entity.*;
import com.cyksj.model.manage.request.ReqGoodsSkuInsert;
import com.cyksj.model.request.CombinationSkuReq;
import com.cyksj.model.views.DistributeSearchView;
import com.cyksj.service.mange.CmsGoodsDonService;
import com.cyksj.service.mange.CmsGoodsDonSkuService;
import com.cyksj.service.mange.CmsGoodsDonSpecService;
import com.cyksj.service.mange.RefreshCacheService;
import com.cyksj.service.translations.BackInfoTranslationsFrontService;
import com.cyksj.service.translations.BackInfoTranslationsService;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.SearchResult;
import com.ejlchina.searcher.param.Operator;
import com.ejlchina.searcher.util.MapBuilder;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;

/**
 * @author chan
 * @date 2022/9/27 5:25 PM
 */
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/manage/goods/sku")
@RestController
public class CmsGoodsDonSkuController {


    private final CmsGoodsDonService goodsDonService;

    private final CmsGoodsDonSpecService goodsDonSpecService;

    private final CmsGoodsDonSkuService goodsDonSkuService;

    private final BeanSearcher beanSearcher;

    private final HttpServletRequest request;

    private final RefreshCacheService refreshCacheService;

    private final BackInfoTranslationsService backInfoTranslationsService;

    private final BackInfoTranslationsFrontService backInfoTranslationsFrontService;


    /**
     * 新增 商品spec & sku
     */
    @PostMapping(value = "/post/spec-sku")
    @Log(module = "平台管理/新增商品sku&spec", businessType = BusinessType.POST, isSaveRequestData = true)
    public Result<String> skuInsert(@Validated @RequestBody ReqGoodsSkuInsert insert) throws Exception{
        goodsDonSpecService.insertOrUpdateSkuSpec(insert, false);
        refreshCacheService.refreshYhHomePageCache();
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 更新 spec
     */
    @PutMapping("/update/spec")
    public Result<String> updateGoodsSpec(@Validated @RequestBody ReqGoodsSkuInsert insert) throws Exception {
        goodsDonSpecService.insertOrUpdateSkuSpec(insert, true);
        refreshCacheService.refreshYhHomePageCache();
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 追加 商品sku
     */
    @Transactional(rollbackFor = Throwable.class)
    @PostMapping(value = "/post")
    @Log(module = "平台管理/新增规格", businessType = BusinessType.POST, isSaveRequestData = true)
    public Result<String> skuAppend(@Validated @RequestBody ReqGoodsSkuInsert insert) throws Exception{

        GoodsDon goods = goodsDonService.getById(insert.getGoodsId());
        if (null == goods) {
            throw new RuntimeException("找不到商品spu.");
        }
        goodsDonSpecService.skuAppend(insert, goods);
        //给平台更新额外属性
        goodsDonService.updateGoodsSkuPrice(goods.getId(), goods);
        refreshCacheService.refreshYhHomePageCache();
       return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 修改 sku
     */
    @Transactional(rollbackFor = Throwable.class)
    @PutMapping(value = "/update")
    @Log(module = "平台管理/编辑规格", businessType = BusinessType.PUT, isSaveRequestData = true)
    public Result<String> skuUpdate(@RequestBody GoodsDonSku sku) throws Exception {
        Long skuId = sku.getId();
        GoodsDonSku dbSku = goodsDonSkuService.getById(skuId);
        Assert.notNull(dbSku, "规格不存在");
        Long goodsId = sku.getGoodsId();
        GoodsDon goods = goodsDonService.getById(goodsId);
        if (goods.getType() == 1) {
            if (sku.getMonths() != null && sku.getMonths() > 0 && sku.getDays() != null && sku.getDays() > 0)
                throw BusinessRuntimeException.getInstance("续费天数和续费月数不能同时存在");
            if (sku.getMonths() == null && sku.getDays() == null)
                throw BusinessRuntimeException.getInstance("请输入对应续费时间");
        }
        if (sku.getMonths() == null) {
            sku.setMonths(null);
        }
        if (sku.getDays() == null) {
            sku.setDays(null);
        }
        if (sku.getMjRelaxNum() == null) {
            sku.setMjRelaxNum(null);
        }
        String specificGoodsIds = sku.getSpecificGoodsIds();
        if (StrUtil.isEmpty(specificGoodsIds)) {
            sku.setSpecificPrice(BigDecimal.ZERO);
        } else {
            Set<Long> specificGids = Jsons.parseSet(specificGoodsIds, Long.class);
            if (specificGids.isEmpty()) {
                sku.setSpecificPrice(BigDecimal.ZERO);
            } else {
                Integer count = goodsDonService.count(Wrappers.lambdaQuery(GoodsDon.class)
                        .in(GoodsDon::getId, specificGids)
                        .eq(GoodsDon::getStatus, true)
                        .eq(GoodsDon::getDeleted, true));
                if (count != specificGids.size()) {
                    throw BusinessRuntimeException.getInstance("存在被删除或已下架的平台");
                }
                BigDecimal specificPrice = sku.getSpecificPrice();
                if (specificPrice == null || specificPrice.compareTo(BigDecimal.ZERO) <= 0) {
                    throw BusinessRuntimeException.getInstance("请输入正确的特定价格");
                }
            }
        }
        if (StrUtil.isNotEmpty(sku.getUserOwns())) {
            List<Long> userOwnsList = Jsons.parseList(sku.getUserOwns(), Long.class);
            if (CollUtil.isEmpty(userOwnsList)) {
                sku.setUserOwns(null);
            }else {
                sku.setUserOwns(userOwnsList.toString());
            }
        }
        //多语言
        String lang = request.getHeader("lang");
        if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
            backInfoTranslationsService.saveOrUpdateBackInfoTranslations(BackInfoTranslations.Type.sku, sku.getId(), sku, lang);
        } else {
            //优惠加购
            goodsDonSkuService.handleDiscountPurchaseGoods(sku, sku.getDpSku());
            String benefitsList = sku.getBenefitsList();
            if (StrUtil.isNotBlank(benefitsList)) {
                Set<GoodsDonSku> benefitsSkuIds = Jsons.parseSet(benefitsList, GoodsDonSku.class);
                sku.setBenefitsList(Jsons.toJson(benefitsSkuIds));
            }
            goodsDonSkuService.updateMirrorCarUserNum(sku);
            goodsDonSkuService.saveOrUpdate(sku);
            //给平台更新额外属性
            goodsDonService.updateGoodsSkuPrice(sku.getGoodsId(), null);
            //前后两次价格不同 下架店铺低于这个折扣最低价格
            BigDecimal oldPrice = dbSku.getPrice();
            BigDecimal newPrice = sku.getPrice();
            //规格新价 变高
            //下架店铺低于这个规格价格的品
            goodsDonSkuService.setBelowPriceShopSkuDown(skuId, newPrice);
            //套餐包关联规格
            goodsDonSkuService.handleGptPackageSku(dbSku, sku);
        }
        refreshCacheService.refreshYhHomePageCache();
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }


    /**
     * 删除 sku
     */
    @Transactional(rollbackFor = Throwable.class)
    @DeleteMapping("/delete/{skuId}")
    @Log(module = "平台管理/删除规格", businessType = BusinessType.DELETE)
    public Result<String> skuDelete(@PathVariable Long skuId) {
        //给平台更新额外属性
        GoodsDonSku sku = goodsDonSkuService.getById(skuId);
        goodsDonSkuService.handleDiscountPurchaseGoods(sku, null);
        goodsDonSkuService.removeById(skuId);
        goodsDonService.updateGoodsSkuPrice(sku.getGoodsId(), null);
        refreshCacheService.refreshYhHomePageCache();
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }

    /**
     * 新 生成排列组合规格
     */
    @PostMapping("/post/combination/{goodsId}")
    @Transactional(rollbackFor = Throwable.class)
    public Result<String> postCombinationSku(@PathVariable Long goodsId, @RequestBody List<CombinationSkuReq> combinations) throws Exception {
        goodsDonSpecService.combinationSku(goodsId, combinations);
        return GatewayResponse.SUCCESS.newBuilder().toResult("新增规格成功");
    }

    /**
     * 获取平台规格列表
     */
    @GetMapping("/get/list")
    public Result<SearchResult<GoodsDonSku>> getGoodsSkuList(@RequestParam(defaultValue = "0") Boolean filterPack, Integer specId) {
        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
        String condition = StrUtil.EMPTY;
        if (filterPack) {
            condition = " spec_json not like '%套餐%'";
        }
        if (specId != null) {
            if (StrUtil.isNotBlank(condition)) {
                condition += " and ";
            }
            condition += String.format("JSON_CONTAINS(spec_ids, '%s')", specId);
        }
        if (StrUtil.isNotBlank(condition)) {
            builder.put("condition", condition);
        }
        SearchResult<GoodsDonSku> skuViewList = beanSearcher.search(GoodsDonSku.class, builder
                .orderBy(GoodsDonSku::getSorted).orderBy(GoodsDonSku::getCreatedTime).desc()
                .build());
        skuViewList.getDataList().forEach(sku -> {
            if (sku.getIsDp()) {
                sku.setDpSku(beanSearcher.searchAll(GoodsDiscountPlusPurchaseRelation.class, MapUtils.builder()
                        .field(GoodsDiscountPlusPurchaseRelation::getSkuId, sku.getId())
                        .build()));
            }

            if (StrUtil.isNotEmpty(sku.getUserOwns())) {
                try {
                    sku.setUserOwnsList(beanSearcher.searchAll(DistributeSearchView.class, MapUtils.builder().field(DistributeSearchView::getUserId, Jsons.parseList(sku.getUserOwns(), Long.class)).op(Operator.InList).build()));
                } catch (Exception e) {
                }
            }
        });
        String lang = request.getHeader("lang");
        if (lang != null && !StrUtil.equals(lang, UserPageLanguage.Language.zh_CN.name())) {
            backInfoTranslationsFrontService.setSkuBackLanguage(skuViewList.getDataList(), lang);
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult(skuViewList);
    }

    /**
     * 批量上架
     */
    @PutMapping("/batch/update/status/{goodsId}")
    public Result<String> batchUpdateStatus(@PathVariable Long goodsId, @RequestBody List<Long> skuIds) {
        GoodsDon goodsDon = goodsDonService.getById(goodsId);
        if (goodsDon == null || !goodsDon.getDeleted()) {
            throw BusinessRuntimeException.getInstance("商品不存在");
        }
        boolean update = goodsDonSkuService.update(null, Wrappers.lambdaUpdate(GoodsDonSku.class)
                .set(GoodsDonSku::getStatus, true)
                .eq(GoodsDonSku::getGoodsId, goodsId)
                .in(GoodsDonSku::getId, skuIds)
                .eq(GoodsDonSku::getStatus, false));
        if (update) {
            goodsDonService.updateGoodsSkuPrice(goodsId, null);
            refreshCacheService.refreshYhHomePageCache();
        }
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }


    /**
     * 规格排序
     */
    @PutMapping("/sorted")
    public Result<String> sorted(@RequestBody GoodsDonSku sku) {
        Long id = sku.getId();
        Integer sorted = sku.getSorted();
        Assert.notNull(id, "请选择指定的规格");
        goodsDonSkuService.update(null, Wrappers.lambdaUpdate(GoodsDonSku.class)
                .eq(GoodsDonSku::getId, id)
                .set(GoodsDonSku::getSorted, sorted));
        refreshCacheService.refreshYhHomePageCache();
        return GatewayResponse.SUCCESS.newBuilder().toResult();
    }
}
