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.common.third.sqb.biz.SqbBiz;
import com.liquidnet.common.third.sqb.param.response.data.MallProductsQueryData;
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.*;
import com.liquidnet.service.goblin.entity.GoblinSqbGoodsExt;
import com.liquidnet.service.goblin.mapper.GoblinSqbGoodsExtMapper;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtSqbGoodsService;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.GoblinSqbRedisUtils;
import com.liquidnet.service.goblin.util.ObjectUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
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.*;

import java.time.LocalDateTime;
import java.util.*;

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

    @Autowired
    private IGoblinStoreMgtSqbGoodsService goblinstoreMgtSqbGoodsService;
    @Autowired
    private GoblinRedisUtils goblinRedisUtils;
    @Autowired
    private GoblinSqbRedisUtils goblinSqbRedisUtils;
    @Autowired
    private GoblinSqbGoodsExtMapper goblinSqbGoodsExtMapper;
    @Autowired
    private SqbBiz goblinShouQianBaService;

    /**
     * 查询所有商城及商品列表
     * 后端自动拉取所有商城，循环获取每个商城的商品列表，聚合返回前端
     */
    @GetMapping("/list")
    @ApiOperation("查询收钱吧所有商城及商品列表")
    public ResponseDto<List<GoblinSqbPerfGoodsVo>> list() {
        return goblinstoreMgtSqbGoodsService.getProductList();
    }

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "SPU添加-收钱吧商品(批量)")
    @PostMapping("add")
    public ResponseDto<Object> add(
            @ApiParam(value = "门店ID", required = true) @RequestParam("storeId") String storeId,
            @ApiParam(value = "待同步的收钱吧商品列表", required = true) @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, Collections.emptyList()));
        }
        if (log.isDebugEnabled()) {
            log.debug("收钱吧商品管理:批量添加:[items={}]", JsonUtils.toJson(items));
        }

        int addSuccess = 0, alreadyExists = 0, addFail = 0;
        List<String> invalidReasons = new ArrayList<>();
        for (GoblinSqbPerfGoodsVo sqbGoods : items) {
            // TODO 测试用
//            int i = 1;
//            for (MallProductsQueryData.Sku skuResult : sqbGoods.getSkuResults()) {
//                if (StringUtils.isBlank(skuResult.getSkuName())) {
//                    skuResult.setSkuName("未知SkuName-" + i);
//                }
//            }

            String invalidReason = validateSqbGoodsForSync(sqbGoods);
            if (StringUtils.isNotBlank(invalidReason)) {
                addFail++;
                invalidReasons.add(invalidReason);
                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, invalidReasons));
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "商品编辑:SPU编辑-收钱吧商品(批量，传系统spuId)")
    @PutMapping("edit_spu")
    public ResponseDto<Object> editSpu(
            @ApiParam(value = "门店ID", required = true) @RequestParam("storeId") String storeId,
            @ApiParam(value = "本地系统SPU ID列表", required = true) @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, Collections.emptyList()));
        }

        int editSuccess = 0, notAdded = 0, sqbNotFound = 0, editFail = 0;
        List<String> invalidReasons = new ArrayList<>();
        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;
            }
            String invalidReason = validateSqbGoodsForSync(sqbGoods);
            if (StringUtils.isNotBlank(invalidReason)) {
                editFail++;
                invalidReasons.add("localSpuId=" + localSpuId + ", " + invalidReason);
                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, invalidReasons));
    }

    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);
            // 设置正在商品获取收钱吧相关信息缓存
            goblinSqbRedisUtils.setSqbGoodsExt(ext.getSpuId(), ext.getSkuId(),
                    GoblinSqbGoodsExtVo.of(ext.getSpuId(), ext.getSkuId(), ext.getMallSn(), ext.getSignature(), ext.getSqbSpuId(), ext.getSqbSkuId()));
        }
    }

    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 String validateSqbGoodsForSync(GoblinSqbPerfGoodsVo sqbGoods) {
        if (sqbGoods == null) {
            return "收钱吧商品为空";
        }
        if (StringUtils.isBlank(sqbGoods.getMallSn())) {
            return "收钱吧商品校验失败: mallSn为空, spuId=" + StringUtils.defaultString(sqbGoods.getSpuId());
        }
        if (StringUtils.isBlank(sqbGoods.getSignature())) {
            return "收钱吧商品校验失败: signature为空, mallSn=" + sqbGoods.getMallSn() + ", spuId=" + StringUtils.defaultString(sqbGoods.getSpuId());
        }
        if (StringUtils.isBlank(sqbGoods.getSpuId())) {
            return "收钱吧商品校验失败: spuId为空, mallSn=" + sqbGoods.getMallSn();
        }
        if (StringUtils.isBlank(sqbGoods.getTitle())) {
            return "收钱吧商品校验失败: title为空, mallSn=" + sqbGoods.getMallSn() + ", spuId=" + sqbGoods.getSpuId();
        }
        if (CollectionUtils.isEmpty(sqbGoods.getSkuResults())) {
            return "收钱吧商品校验失败: skuResults为空, mallSn=" + sqbGoods.getMallSn() + ", spuId=" + sqbGoods.getSpuId();
        }
        for (int i = 0; i < sqbGoods.getSkuResults().size(); i++) {
            MallProductsQueryData.Sku sku = sqbGoods.getSkuResults().get(i);
            if (sku == null) {
                return "收钱吧商品校验失败: skuResults[" + i + "]为空, mallSn=" + sqbGoods.getMallSn() + ", spuId=" + sqbGoods.getSpuId();
            }
            if (StringUtils.isBlank(sku.getSkuId())) {
                return "收钱吧商品校验失败: skuId为空, mallSn=" + sqbGoods.getMallSn() + ", spuId=" + sqbGoods.getSpuId() + ", index=" + i;
            }
            if (StringUtils.isBlank(sku.getSkuName())) {
                return "收钱吧商品校验失败: skuName为空, mallSn=" + sqbGoods.getMallSn() + ", spuId=" + sqbGoods.getSpuId() + ", skuId=" + sku.getSkuId();
            }
            if (sku.getPrice() == null) {
                return "收钱吧商品校验失败: price为空, mallSn=" + sqbGoods.getMallSn() + ", spuId=" + sqbGoods.getSpuId() + ", skuId=" + sku.getSkuId();
            }
        }
        return null;
    }

    private Map<String, Object> buildAddResult(int addSuccess, int alreadyExists, int addFail, List<String> invalidReasons) {
        Map<String, Object> result = new HashMap<>();
        result.put("addSuccess", addSuccess);
        result.put("alreadyExists", alreadyExists);
        result.put("addFail", addFail);
        result.put("invalidCount", CollectionUtils.isEmpty(invalidReasons) ? 0 : invalidReasons.size());
        result.put("invalidReasons", invalidReasons);
        return result;
    }

    private Map<String, Object> buildEditResult(int editSuccess, int notAdded, int sqbNotFound, int editFail,
                                                List<String> invalidReasons) {
        Map<String, Object> result = new HashMap<>();
        result.put("editSuccess", editSuccess);
        result.put("notAdded", notAdded);
        result.put("sqbNotFound", sqbNotFound);
        result.put("editFail", editFail);
        result.put("invalidCount", CollectionUtils.isEmpty(invalidReasons) ? 0 : invalidReasons.size());
        result.put("invalidReasons", invalidReasons);
        return result;
    }
}
