package com.liquidnet.service.goblin.controller.manage;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtGoodsSqbAddParam;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSpecVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfGoodsVo;
import com.liquidnet.service.goblin.entity.GoblinSqbGoodsExt;
import com.liquidnet.service.goblin.mapper.GoblinSqbGoodsExtMapper;
import com.liquidnet.service.goblin.param.shouqianba.response.data.MallProductsQueryData;
import com.liquidnet.service.goblin.service.IGoblinShouQianBaService;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtSqbGoodsService;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.ObjectUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 收钱吧商品管理
 */
@Api(tags = "收钱吧商品管理")
@Slf4j
@Validated
@RestController
@RequestMapping("store/mgt/sqb/goods")
public class GoblinStoreMgtSqbGoodsController {

    @Autowired
    private IGoblinStoreMgtSqbGoodsService goblinstoreMgtSqbGoodsService;
    @Autowired
    private GoblinRedisUtils goblinRedisUtils;
    @Autowired
    private GoblinSqbGoodsExtMapper goblinSqbGoodsExtMapper;
    @Autowired
    private IGoblinShouQianBaService goblinShouQianBaService;

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "SPU添加-收钱吧商品(批量)")
    @PostMapping("add")
    public ResponseDto<Object> add(@RequestParam("storeId") String storeId,
            @RequestBody @Validated List<GoblinSqbPerfGoodsVo> items) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        if (CollectionUtils.isEmpty(items)) {
            return ResponseDto.success(buildAddResult(0, 0, 0));
        }
        if (log.isDebugEnabled()) {
            log.debug("收钱吧商品管理:批量添加:[items={}]", JsonUtils.toJson(items));
        }

        int addSuccess = 0, alreadyExists = 0, addFail = 0;
        for (GoblinSqbPerfGoodsVo sqbGoods : items) {
            if (sqbGoods == null || StringUtils.isBlank(sqbGoods.getSpuId()) || StringUtils.isBlank(sqbGoods.getMallSn())) {
                addFail++;
                continue;
            }
            if (existsSqbSpu(sqbGoods.getMallSn(), sqbGoods.getSpuId())) {
                alreadyExists++;
                continue;
            }
            try {
                GoblinStoreMgtGoodsSqbAddParam initParam = new GoblinStoreMgtGoodsSqbAddParam();
                GoblinGoodsInfoVo goodsInfoVo = initParam.initGoodsInfoVo(storeId, sqbGoods, currentUid, LocalDateTime.now());

                ArrayList<GoblinGoodsSpecVo> goodsSpecVoList = ObjectUtil.getGoblinGoodsSpecVoArrayList();
                List<GoblinGoodsSkuInfoVo> goodsSkuInfoVoList = ObjectUtil.getGoblinGoodsSkuInfoVoArrayList();
                initParam.initGoodsSkuInfoVo(goodsInfoVo, goodsSkuInfoVoList, goodsSpecVoList, sqbGoods);

                goodsInfoVo.setTagVoList(new ArrayList<>());
                goodsInfoVo.setExtagVoList(new ArrayList<>());
                goodsInfoVo.setArtagVoList(new ArrayList<>());
                goodsInfoVo.setServiceSupportVoList(new ArrayList<>());
                goblinstoreMgtSqbGoodsService.sqbGoodsAdd(goodsInfoVo, goodsSkuInfoVoList);
                saveSqbExtRelations(goodsInfoVo, sqbGoods);
                addSuccess++;
            } catch (Exception e) {
                addFail++;
                log.error("收钱吧商品管理:批量添加失败, storeId={}, sqbSpuId={}", storeId, sqbGoods.getSpuId(), e);
            }
        }
        return ResponseDto.success(buildAddResult(addSuccess, alreadyExists, addFail));
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "商品编辑:SPU编辑-收钱吧商品(批量，传系统spuId)")
    @PutMapping("edit_spu")
    public ResponseDto<Object> editSpu(@RequestParam("storeId") String storeId,
            @RequestBody @Validated List<String> localSpuIds) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        if (CollectionUtils.isEmpty(localSpuIds)) {
            return ResponseDto.success(buildEditResult(0, 0, 0, 0));
        }

        int editSuccess = 0, notAdded = 0, sqbNotFound = 0, editFail = 0;
        for (String localSpuId : localSpuIds) {
            if (StringUtils.isBlank(localSpuId)) {
                editFail++;
                continue;
            }
            List<GoblinSqbGoodsExt> extList = goblinSqbGoodsExtMapper.selectList(new LambdaQueryWrapper<GoblinSqbGoodsExt>()
                    .eq(GoblinSqbGoodsExt::getSpuId, localSpuId)
                    .eq(GoblinSqbGoodsExt::getDelFlg, "0"));
            if (CollectionUtils.isEmpty(extList)) {
                notAdded++;
                continue;
            }

            GoblinGoodsInfoVo localGoodsInfoVo = goblinRedisUtils.getGoodsInfoVo(localSpuId);
            if (localGoodsInfoVo == null) {
                notAdded++;
                continue;
            }

            GoblinSqbGoodsExt ext = extList.get(0);
            String mallSn = ext.getMallSn();
            String sqbSpuId = ext.getSqbSpuId();
            String signature = ext.getSignature();
            GoblinSqbPerfGoodsVo sqbGoods = fetchSqbGoodsByMallAndSpu(mallSn, sqbSpuId, signature);
            if (sqbGoods == null) {
                sqbNotFound++;
                continue;
            }

            try {
                if (goblinstoreMgtSqbGoodsService.sqbGoodsEditSpu(currentUid, sqbGoods, localGoodsInfoVo)) {
                    editSuccess++;
                } else {
                    editFail++;
                }
            } catch (Exception e) {
                editFail++;
                log.error("收钱吧商品管理:批量编辑失败, storeId={}, localSpuId={}, sqbSpuId={}",
                        storeId, localSpuId, sqbSpuId, e);
            }
        }
        return ResponseDto.success(buildEditResult(editSuccess, notAdded, sqbNotFound, editFail));
    }

    private boolean existsSqbSpu(String mallSn, String sqbSpuId) {
        return goblinSqbGoodsExtMapper.selectCount(new LambdaQueryWrapper<GoblinSqbGoodsExt>()
                .eq(GoblinSqbGoodsExt::getMallSn, mallSn)
                .eq(GoblinSqbGoodsExt::getSqbSpuId, sqbSpuId)
                .eq(GoblinSqbGoodsExt::getDelFlg, "0")) > 0;
    }

    private void saveSqbExtRelations(GoblinGoodsInfoVo goodsInfoVo, GoblinSqbPerfGoodsVo sqbGoods) {
        LocalDateTime now = LocalDateTime.now();
        List<String> localSkuIds = goodsInfoVo.getSkuIdList() == null ? Collections.emptyList() : goodsInfoVo.getSkuIdList();
        List<MallProductsQueryData.Sku> sqbSkus = sqbGoods.getSkuResults() == null ? Collections.emptyList() : sqbGoods.getSkuResults();

        int relationSize = Math.max(localSkuIds.size(), sqbSkus.size());
        if (relationSize == 0) {
            relationSize = 1;
        }
        for (int i = 0; i < relationSize; i++) {
            GoblinSqbGoodsExt ext = new GoblinSqbGoodsExt();
            ext.setSpuId(goodsInfoVo.getSpuId());
            ext.setSkuId(i < localSkuIds.size() ? localSkuIds.get(i) : null);
            ext.setMallSn(sqbGoods.getMallSn());
            ext.setSignature(sqbGoods.getSignature());
            ext.setSqbSpuId(sqbGoods.getSpuId());
            ext.setSqbSkuId(i < sqbSkus.size() ? sqbSkus.get(i).getSkuId() : null);
            ext.setDelFlg("0");
            ext.setCreatedAt(now);
            ext.setUpdatedAt(now);
            goblinSqbGoodsExtMapper.insert(ext);
        }
    }

    private GoblinSqbPerfGoodsVo fetchSqbGoodsByMallAndSpu(String mallSn, String sqbSpuId, String signature) {
        if (StringUtils.isBlank(mallSn) || StringUtils.isBlank(sqbSpuId) || StringUtils.isBlank(signature)) {
            return null;
        }
        List<MallProductsQueryData> products = goblinShouQianBaService.queryMallProducts(mallSn, signature);
        if (CollectionUtils.isEmpty(products)) {
            return null;
        }
        for (MallProductsQueryData product : products) {
            if (sqbSpuId.equals(product.getSpuId())) {
                GoblinSqbPerfGoodsVo vo = new GoblinSqbPerfGoodsVo();
                vo.setMallSn(mallSn);
                vo.setSignature(signature);
                vo.setSpuId(product.getSpuId());
                vo.setConverImages(product.getConverImages());
                vo.setProductIntroduction(product.getProductIntroduction());
                vo.setTitle(product.getTitle());
                vo.setSkuResults(product.getSkuResults());
                return vo;
            }
        }
        return null;
    }

    private Map<String, Integer> buildAddResult(int addSuccess, int alreadyExists, int addFail) {
        Map<String, Integer> result = new HashMap<>();
        result.put("addSuccess", addSuccess);
        result.put("alreadyExists", alreadyExists);
        result.put("addFail", addFail);
        return result;
    }

    private Map<String, Integer> buildEditResult(int editSuccess, int notAdded, int sqbNotFound, int editFail) {
        Map<String, Integer> result = new HashMap<>();
        result.put("editSuccess", editSuccess);
        result.put("notAdded", notAdded);
        result.put("sqbNotFound", sqbNotFound);
        result.put("editFail", editFail);
        return result;
    }
}
