package com.fs.oms.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.core.domain.R;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.DateUtils;
import com.fs.oms.domain.OmsProduct;
import com.fs.oms.domain.OmsProductAttr;
import com.fs.oms.domain.OmsProductAttrValue;
import com.fs.oms.dto.OmsProductArrtDTO;
import com.fs.oms.dto.OmsProductAttrCountDTO;
import com.fs.oms.mapper.OmsProductAttrMapper;
import com.fs.oms.mapper.OmsProductAttrValueMapper;
import com.fs.oms.mapper.OmsProductMapper;
import com.fs.oms.param.OmsProductAddEditParam;
import com.fs.oms.service.IOmsProductService;
import com.fs.oms.vo.OmsProductExportVO;
import com.fs.oms.vo.OmsProductListVO;
import com.fs.oms.vo.OmsDetailVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


/**
 * 商品Service业务层处理
 *
 * @author fs
 * @date 2023-06-07
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class OmsProductServiceImpl implements IOmsProductService
{
    @Autowired
    private OmsProductMapper omsProductMapper;

    @Autowired
    private OmsProductAttrMapper omsProductAttrMapper;

    @Autowired
    private OmsProductAttrValueMapper omsProductAttrValueMapper;

    /**
     * 查询商品
     *
     * @param productId 商品ID
     * @return 商品
     */
    @Override
    public OmsProduct selectOmsProductById(Long productId)
    {
        return omsProductMapper.selectOmsProductById(productId);
    }

    /**
     * 查询商品列表
     *
     * @param omsProduct 商品
     * @return 商品
     */
    @Override
    public List<OmsProduct> selectOmsProductList(OmsProduct omsProduct)
    {
        return omsProductMapper.selectOmsProductList(omsProduct);
    }

    /**
     * 新增商品
     *
     * @param omsProduct 商品
     * @return 结果
     */
    @Override
    public int insertOmsProduct(OmsProduct omsProduct)
    {
        omsProduct.setCreateTime(DateUtils.getNowDate());
        return omsProductMapper.insertOmsProduct(omsProduct);
    }

    /**
     * 修改商品
     *
     * @param omsProduct 商品
     * @return 结果
     */
    @Override
    public int updateOmsProduct(OmsProduct omsProduct)
    {
        omsProduct.setUpdateTime(DateUtils.getNowDate());
        return omsProductMapper.updateOmsProduct(omsProduct);
    }

    /**
     * 批量删除商品
     *
     * @param productIds 需要删除的商品ID
     * @return 结果
     */
    @Override
    public int deleteOmsProductByIds(Long[] productIds)
    {
        return omsProductMapper.deleteOmsProductByIds(productIds);
    }

    /**
     * 删除商品信息
     *
     * @param productId 商品ID
     * @return 结果
     */
    @Override
    public int deleteOmsProductById(Long productId)
    {
        return omsProductMapper.deleteOmsProductById(productId);
    }

    @Override
    public List<OmsProductListVO> selectOmsProductListVO(OmsProduct omsProduct) {
        return omsProductMapper.selectOmsProductListVO(omsProduct);
    }

    @Override
    public List<OmsProductListVO> selectOmsProductBarCodeListVO(OmsProduct omsProduct) {
        return omsProductMapper.selectFsStoreProductBarCodeListVO(omsProduct);
    }

    @Override
    public List<OmsProductExportVO> selectOmsProductExportList(OmsProduct omsProduct) {
        return omsProductMapper.selectOmsProductExportList(omsProduct);
    }

    @Override
    public Map<String, Object> getFormatAttr(Long productId, String jsonStr) {
        JSONObject jsonObject = JSON.parseObject(jsonStr);
        Map<String, Object> resultMap = new LinkedHashMap<>(3);
        if (jsonObject == null || jsonObject.get("attrs") == null || jsonObject.getJSONArray("attrs").isEmpty()) {
            resultMap.put("attr", new ArrayList<>());
            resultMap.put("value", new ArrayList<>());
            resultMap.put("header", new ArrayList<>());
            return resultMap;
        }
        List<OmsProductArrtDTO> formatDetailDTOList = JSON.parseArray(jsonObject.get("attrs").toString(),
                OmsProductArrtDTO.class);
        OmsDetailVO detailDto = this.attrFormat(formatDetailDTOList);
        List<Map<String, Object>> headerMapList = null;
        List<Map<String, Object>> valueMapList = new ArrayList<>();
        String align = "center";
        Map<String, Object> headerMap = new LinkedHashMap<>();
        for (Map<String, Map<String, String>> map : detailDto.getRes()) {
            Map<String, String> detail = map.get("detail");
            String[] detailArr = detail.values().toArray(new String[]{});
            Arrays.sort(detailArr);

            String sku = String.join(",", detailArr);

            Map<String, Object> valueMap = new LinkedHashMap<>();

            List<String> detailKeys =
                    detail.entrySet()
                            .stream()
                            .map(Map.Entry::getKey)
                            .collect(Collectors.toList());

            int i = 0;
            headerMapList = new ArrayList<>();
            for (String title : detailKeys) {
                headerMap.put("title", title);
                headerMap.put("minWidth", "130");
                headerMap.put("align", align);
                headerMap.put("key", "value" + (i + 1));
                headerMap.put("slot", "value" + (i + 1));
                headerMapList.add(ObjectUtil.clone(headerMap));
                i++;
            }

            String[] detailValues = detail.values().toArray(new String[]{});
            for (int j = 0; j < detailValues.length; j++) {
                String key = "value" + (j + 1);
                valueMap.put(key, detailValues[j]);
            }

            valueMap.put("detail", detail);
            valueMap.put("sku", "");
            valueMap.put("image", "");
            valueMap.put("price", 0);
            valueMap.put("cost", 0);
            valueMap.put("otPrice", 0);
            valueMap.put("barCode", "");
            valueMap.put("activityPrice", 0);
            valueMap.put("marketPrice", 0);
            valueMap.put("clearingPrice", 0);
            valueMap.put("innerPrice", 0);
            valueMap.put("weight", 0);
            valueMap.put("volume", 0);
            if (productId > 0) {
                OmsProductAttrValue attrValueMap=new OmsProductAttrValue();
                attrValueMap.setProductId(productId);
                attrValueMap.setSku(sku);
                List<OmsProductAttrValue> values = omsProductAttrValueMapper.selectOmsProductAttrValueList(attrValueMap);

                if (values != null&&values.size()==1) {
                    valueMap.put("id",values.get(0).getId());
                    valueMap.put("sku",values.get(0).getSku());
                    valueMap.put("image", values.get(0).getImage());
                    valueMap.put("price", values.get(0).getPrice());
                    valueMap.put("cost", values.get(0).getCost());
                    valueMap.put("otPrice", values.get(0).getOtPrice());
                    valueMap.put("barCode", values.get(0).getBarCode());
                    valueMap.put("activityPrice",values.get(0).getActivityPrice());
                    valueMap.put("marketPrice", values.get(0).getMarketPrice());
                    valueMap.put("clearingPrice", values.get(0).getClearingPrice());
                    valueMap.put("innerPrice", values.get(0).getInnerPrice());
                    valueMap.put("weight", values.get(0).getWeight());
                    valueMap.put("volume", values.get(0).getVolume());
                }
            }
            valueMapList.add(ObjectUtil.clone(valueMap));
        }
        this.addHeaderMap(headerMap, headerMapList, align);
        resultMap.put("attr", formatDetailDTOList);
        resultMap.put("value", valueMapList);
        resultMap.put("header", headerMapList);
        return resultMap;
    }

    @Override
    @Transactional
    public R addOrEdit(OmsProductAddEditParam param) {
        OmsProductAttrCountDTO countDto=computedProductCount(param.getValues());

        if(param.getProductId()>0){
            OmsProduct product=new OmsProduct();
            BeanUtils.copyProperties(param,product);
            product.setPrice(countDto.getMinPrice());
            product.setOtPrice(countDto.getMinOtPrice());
            product.setCost(countDto.getMinCost());
            omsProductMapper.updateOmsProduct(product);
            if (param.getSpecType().equals(0)) {
               OmsProductArrtDTO fromatDetailDto = OmsProductArrtDTO.builder()
                        .value("规格")
                        .detail(ListUtil.toList("默认"))
                        .build();
                List<OmsProductArrtDTO> items=new ArrayList<>();
                items.add(fromatDetailDto);
                param.getValues().get(0).setSku("默认");
                addProductAttr(product.getProductId(),items,param.getValues());
            } else {
                addProductAttr(product.getProductId(),param.getItems(),param.getValues());
            }
        }
        else{
            OmsProduct product=new OmsProduct();
            BeanUtils.copyProperties(param,product);
            product.setPrice(countDto.getMinPrice());
            product.setOtPrice(countDto.getMinOtPrice());
            product.setCost(countDto.getMinCost());
            omsProductMapper.insertOmsProduct(product);
            if (param.getSpecType().equals(0)) {
                OmsProductArrtDTO fromatDetailDto = OmsProductArrtDTO.builder()
                        .value("规格")
                        .detail(ListUtil.toList("默认"))
                        .build();
                List<OmsProductArrtDTO> items=new ArrayList<>();
                items.add(fromatDetailDto);
                param.getValues().get(0).setSku("默认");
                addProductAttr(product.getProductId(),items,param.getValues());
            } else {
                addProductAttr(product.getProductId(),param.getItems(),param.getValues());
            }
        }
        return R.ok();
    }

    private void addProductAttr(Long productId, List<OmsProductArrtDTO> items, List<OmsProductAttrValue> values){
        //清空attr
        omsProductAttrMapper.clear(productId);
        //清空values
        //查出商品属性所有ID;
        List<OmsProductAttrValue> attrValues=omsProductAttrValueMapper.selectOmsProductAttrValueByProductId(productId);
        omsProductAttrValueMapper.deleteOmsProductAttrValueByProductId(productId);
        //写入attr
        for(OmsProductArrtDTO vo:items){
            OmsProductAttr attr=new OmsProductAttr();
            attr.setProductId(productId);
            attr.setAttrName(vo.getValue());
            attr.setAttrValues(StringUtils.join(vo.getDetail(), ","));
            omsProductAttrMapper.insertOmsProductAttr(attr);
        }
        Map<String,Object> map = new LinkedHashMap<>();
        map.put("attr",items);
        // map.put("value",values);

        for(OmsProductAttrValue val: values){
            //更新套餐商品属性ID  获取套餐
            Long id=val.getId();
            if(val.getDetail()!=null){
                List<String> stringList = new ArrayList<>(val.getDetail().values());
                Collections.sort(stringList);
                val.setSku(StrUtil.join(",",stringList));
            }
            val.setProductId(productId);
            omsProductAttrValueMapper.insertOmsProductAttrValue(val);
        }
    }

    private OmsProductAttrCountDTO computedProductCount(List<OmsProductAttrValue> values) {
        BigDecimal val=new BigDecimal(0);
        //取最小价格
        BigDecimal minPrice = values
                .stream()
                .map(OmsProductAttrValue::getPrice)
                .min(Comparator.naturalOrder())
                .orElse(val);

        BigDecimal minOtPrice = values
                .stream()
                .map(OmsProductAttrValue::getOtPrice)
                .min(Comparator.naturalOrder())
                .orElse(val);

        BigDecimal minCost = values
                .stream()
                .map(OmsProductAttrValue::getCost)
                .min(Comparator.naturalOrder())
                .orElse(val);

//        if (stock <= 0) {
//            throw new CustomException("库存不能低于0");
//        }

        return OmsProductAttrCountDTO.builder()
                .minPrice(minPrice)
                .minOtPrice(minOtPrice)
                .minCost(minCost)
                .build();
    }

    private OmsDetailVO attrFormat(List<OmsProductArrtDTO> fromatDetailDTOList) {
        List<String> data = new ArrayList<>();
        List<Map<String, Map<String, String>>> res = new ArrayList<>();
        fromatDetailDTOList.stream()
                .map(OmsProductArrtDTO::getDetail)
                .forEach(i -> {
                    if (i == null || i.isEmpty()) {
                        throw new CustomException("请至少添加一个规格值哦");
                    }
                    String str = ArrayUtil.join(i.toArray(), ",");
                    if (str.contains("-")) {
                        throw new CustomException("规格值里包含'-',请重新添加");
                    }
                });

        if (fromatDetailDTOList.size() > 1) {
            for (int i = 0; i < fromatDetailDTOList.size() - 1; i++) {
                if (i == 0) {
                    data = fromatDetailDTOList.get(i).getDetail();
                }
                List<String> tmp = new LinkedList<>();
                for (String v : data) {
                    for (String g : fromatDetailDTOList.get(i + 1).getDetail()) {
                        String rep2 = "";
                        if (i == 0) {
                            rep2 = fromatDetailDTOList.get(i).getValue() + "_" + v + "-"
                                    + fromatDetailDTOList.get(i + 1).getValue() + "_" + g;
                        } else {
                            rep2 = v + "-"
                                    + fromatDetailDTOList.get(i + 1).getValue() + "_" + g;
                        }

                        tmp.add(rep2);

                        if (i == fromatDetailDTOList.size() - 2) {
                            Map<String, Map<String, String>> rep4 = new LinkedHashMap<>();
                            Map<String, String> reptemp = new LinkedHashMap<>();
                            for (String h : Arrays.asList(rep2.split("-"))) {
                                List<String> rep3 = Arrays.asList(h.split("_"));
                                if (rep3.size() > 1) {
                                    reptemp.put(rep3.get(0), rep3.get(1));
                                } else {
                                    reptemp.put(rep3.get(0), "");
                                }
                            }
                            rep4.put("detail", reptemp);
                            res.add(rep4);
                        }
                    }
                }
                if (!tmp.isEmpty()) {
                    data = tmp;
                }
            }
        } else {
            List<String> dataArr = new ArrayList<>();
            for (OmsProductArrtDTO fromatDetailDTO : fromatDetailDTOList) {
                for (String str : fromatDetailDTO.getDetail()) {
                    Map<String, Map<String, String>> map2 = new LinkedHashMap<>();
                    dataArr.add(fromatDetailDTO.getValue() + "_" + str);
                    Map<String, String> map1 = new LinkedHashMap<>();
                    map1.put(fromatDetailDTO.getValue(), str);
                    map2.put("detail", map1);
                    res.add(map2);
                }
            }
            String s = StrUtil.join("-", dataArr);
            data.add(s);
        }
        OmsDetailVO detailDto = new OmsDetailVO();
        detailDto.setData(data);
        detailDto.setRes(res);
        return detailDto;
    }

    /**
     * 增加表头
     */
    private void addHeaderMap(Map<String, Object> headerMap, List<Map<String, Object>> headerMapList, String align) {
        headerMap.put("title", "图片");
        headerMap.put("slot", "image");
        headerMap.put("align", align);
        headerMap.put("minWidth", 80);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "售价");
        headerMap.put("slot", "price");
        headerMap.put("align", align);
        headerMap.put("minWidth", 120);
        headerMapList.add(ObjectUtil.clone(headerMap));


        headerMap.put("title", "成本价");
        headerMap.put("slot", "cost");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "原价");
        headerMap.put("slot", "otPrice");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "营销价");
        headerMap.put("slot", "activityPrice");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "市场价");
        headerMap.put("slot", "marketPrice");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "结算价");
        headerMap.put("slot", "clearingPrice");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "内部分摊价");
        headerMap.put("slot", "innerPrice");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "商品编号");
        headerMap.put("slot", "barCode");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "重量(KG)");
        headerMap.put("slot", "weight");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "体积(m³)");
        headerMap.put("slot", "volume");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "操作");
        headerMap.put("slot", "action");
        headerMap.put("align", align);
        headerMap.put("minWidth", 70);
        headerMapList.add(ObjectUtil.clone(headerMap));
    }
}
