package com.xinelu.manage.service.goodsInfo.impl;

import com.xinelu.common.config.XinELuConfig;
import com.xinelu.common.constant.Constants;
import com.xinelu.common.core.domain.AjaxResult;
import com.xinelu.common.enums.StoreOpenStatusEnum;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.SecurityUtils;
import com.xinelu.common.utils.codes.GenerateSystemCodeUtil;
import com.xinelu.common.utils.file.FileUtils;
import com.xinelu.manage.domain.goodsInfo.GoodsInfo;
import com.xinelu.manage.domain.storeInfo.StoreInfo;
import com.xinelu.manage.dto.goodsInfo.GoodsAttributeDTO;
import com.xinelu.manage.dto.goodsInfo.GoodsInfoDTO;
import com.xinelu.manage.mapper.goodsAttribute.GoodsAttributeMapper;
import com.xinelu.manage.mapper.goodsAttributeDetails.GoodsAttributeDetailsMapper;
import com.xinelu.manage.mapper.goodsInfo.GoodsInfoMapper;
import com.xinelu.manage.service.goodsInfo.GoodsOperateInfoService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description 运营PC端-商品信息管理业务层实现类
 * @Author 纪寒
 * @Date 2022-11-10 16:01:43
 * @Version 1.0
 */
@Service
public class GoodsOperateInfoServiceImpl implements GoodsOperateInfoService {

    @Resource
    private GoodsInfoMapper goodsInfoMapper;
    @Resource
    private GenerateSystemCodeUtil generateSystemCodeUtil;
    @Resource
    private GoodsAttributeMapper goodsAttributeMapper;
    @Resource
    private GoodsAttributeDetailsMapper goodsAttributeDetailsMapper;
    @Resource
    private XinELuConfig xinYiLuConfig;

    /**
     * 运营PC端-新增商品基本信息
     *
     * @param goodsInfo 商品基本信息
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult insertGoodsOperateInfo(GoodsInfoDTO goodsInfo) {
        //检验商品价格负数问题和库存数量负数问题
        AjaxResult ajaxResult = judgeGoodsPriceAndStock(goodsInfo);
        if (Objects.nonNull(ajaxResult)) {
            return ajaxResult;
        }
        StoreInfo storeInfo = new StoreInfo();
        //根据护理站的id查询店铺信息
        StoreInfo storeInfos = goodsInfoMapper.getStoreInfoByName(xinYiLuConfig.getYiLuYouPinStoreName());
        //如果没有就新增
        if (Objects.isNull(storeInfos)) {
            storeInfo.setStoreName(xinYiLuConfig.getYiLuYouPinStoreName());
            storeInfo.setStoreCode(Constants.STORE_KEY + generateSystemCodeUtil.generateSystemCode(Constants.STORE_KEY));
            storeInfo.setOpeningStatus(StoreOpenStatusEnum.OPENED.getInfo());
            storeInfo.setOpeningTime(LocalDateTime.now());
            storeInfo.setOccupationStartTime(LocalDateTime.now());
            storeInfo.setCreateTime(LocalDateTime.now());
            storeInfo.setNurseStationId(goodsInfo.getNurseStationId());
            storeInfo.setSort(Objects.isNull(goodsInfo.getSort()) ? 1 : goodsInfo.getSort());
            goodsInfoMapper.insertStoreInfo(storeInfo);
        }
        if (Objects.nonNull(storeInfos)) {
            goodsInfo.setStoreInfoId(storeInfos.getId());
        } else {
            goodsInfo.setStoreInfoId(storeInfo.getId());
        }
        //新增商品主表信息
        goodsInfo.setNurseStationId(goodsInfo.getNurseStationId());
        goodsInfo.setWhetherShelf(0);
        goodsInfo.setCreateBy(SecurityUtils.getUsername());
        goodsInfo.setCreateTime(LocalDateTime.now());
        goodsInfo.setGoodsCode(Constants.GOODS_CODE + generateSystemCodeUtil.generateSystemCode(Constants.GOODS_CODE));
        int insertGoodsInfo = goodsInfoMapper.insertGoodsInfo(goodsInfo);
        if (insertGoodsInfo <= 0) {
            throw new ServiceException(goodsInfo.getGoodsName() + "-" + "商品新增失败!");
        }
        //新增商品属性表信息
        if (CollectionUtils.isNotEmpty(goodsInfo.getGoodDetailsLists())) {
            for (GoodsAttributeDTO goodsAttribute : goodsInfo.getGoodDetailsLists()) {
                this.integralExchangeFlagCheck(goodsAttribute);
                goodsAttribute.setGoodsId(goodsInfo.getId());
                goodsAttribute.setAttributeDetailsSort(Objects.isNull(goodsAttribute.getAttributeDetailsSort()) ? 1 : goodsAttribute.getAttributeDetailsSort());
                goodsAttribute.setCreateBy(goodsInfo.getCreateBy());
                goodsAttribute.setCreateTime(LocalDateTime.now());
                goodsAttribute.setAttributeCode(Constants.ATTRIBUTE_CODE + generateSystemCodeUtil.generateSystemCode(Constants.ATTRIBUTE_CODE));
                int goodsAttributes = goodsAttributeMapper.insertGoodsAttributes(goodsAttribute);
                if (goodsAttributes <= 0) {
                    throw new ServiceException("新增商品属性表信息失败！");
                }
                goodsAttribute.setGoodsAttributeId(goodsAttribute.getGoodsAttributeId());
                goodsAttribute.setAttributeDetailsName(goodsAttribute.getAttributeName());
                int addGoodsAttributeDetails = goodsAttributeDetailsMapper.addGoodsAttributeDetails(goodsAttribute);
                if (addGoodsAttributeDetails <= 0) {
                    throw new ServiceException("新增商品属性明细表信息失败！");
                }
            }
        }
        return AjaxResult.success();
    }

    /**
     * 运营PC端-修改商品基本信息
     *
     * @param goodsInfo 商品基本信息
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateGoodsOperateInfo(GoodsInfoDTO goodsInfo) {
        //检验商品价格负数问题和库存数量负数问题
        AjaxResult ajaxResult = judgeGoodsPriceAndStock(goodsInfo);
        if (Objects.nonNull(ajaxResult)) {
            return ajaxResult;
        }
        if (CollectionUtils.isEmpty(goodsInfo.getGoodDetailsLists())) {
            return AjaxResult.error("请添加商品属性信息！");
        }
        //查询原有商品信息
        GoodsInfo existGoodsPicture = goodsInfoMapper.selectGoodsInfoById(goodsInfo.getId());
        if (Objects.isNull(existGoodsPicture)) {
            return AjaxResult.error("当前商品信息不存在！");
        }
        //查寻数据库已存在的商品属性信息
        List<GoodsAttributeDTO> goodsByIdList = goodsInfoMapper.getGoodsByIdList(goodsInfo.getId());
        //修改商品主表信息
        goodsInfo.setUpdateBy(SecurityUtils.getUsername());
        goodsInfo.setUpdateTime(LocalDateTime.now());
        int insertGoodsInfo = goodsInfoMapper.updateGoodsInfo(goodsInfo);
        if (insertGoodsInfo <= 0) {
            throw new ServiceException(goodsInfo.getGoodsName() + "-" + "商品修改失败!");
        }
        List<GoodsAttributeDTO> goodDetailsLists = goodsInfo.getGoodDetailsLists();
        //获取前端传过来的商品属性表id集合
        List<Long> attributeIdList = goodDetailsLists.stream().filter(Objects::nonNull).map(GoodsAttributeDTO::getGoodsAttributeId).distinct().collect(Collectors.toList());
        List<Long> attributedDetailIdList = goodDetailsLists.stream().filter(Objects::nonNull).map(GoodsAttributeDTO::getAttributeDetailsId).distinct().collect(Collectors.toList());
        //获取当前数据库中原有的商品属性id集合
        List<Long> attributeIdListExist = goodsByIdList.stream().filter(Objects::nonNull).map(GoodsAttributeDTO::getGoodsAttributeId).distinct().collect(Collectors.toList());
        List<Long> attributedDetailIdListExist = goodsByIdList.stream().filter(Objects::nonNull).map(GoodsAttributeDTO::getGoodAttributeDetailsId).distinct().collect(Collectors.toList());
        //求差值，找出需要删除的商品属性id集合
        List<Long> subtractAttributeIdList = new ArrayList<>(CollectionUtils.subtract(attributeIdListExist, attributeIdList));
        List<Long> subtractAttributeDetailIdList = new ArrayList<>(CollectionUtils.subtract(attributedDetailIdListExist, attributedDetailIdList));
        if (CollectionUtils.isNotEmpty(subtractAttributeIdList)) {
            int insertCount = goodsAttributeMapper.deleteGoodsAttributeByIds(subtractAttributeIdList.toArray(new Long[0]));
            if (insertCount <= 0) {
                throw new ServiceException("删除商品属性表失败!");
            }
        }
        if (CollectionUtils.isNotEmpty(subtractAttributeDetailIdList)) {
            int insertCount = goodsAttributeDetailsMapper.deleteGoodsAttributeDetailsByIds(subtractAttributeDetailIdList.toArray(new Long[subtractAttributeIdList.size()]));
            if (insertCount <= 0) {
                throw new ServiceException("删除商品属性明细表失败!");
            }
        }
        //新增和修改商品属性信息
        this.updateGoodsAttributeInfo(goodsInfo, goodDetailsLists, goodsByIdList);
        //删除商品主表图片以及商品富文本图片
        this.deleteGoodPictureUrl(goodsInfo, existGoodsPicture);
        return AjaxResult.success();
    }

    /**
     * 修改商品属性信息
     *
     * @param goodsInfo        商品信息
     * @param goodDetailsLists 商品属性信息
     * @param goodsByIdList    商品id列表信息
     */
    private void updateGoodsAttributeInfo(GoodsInfoDTO goodsInfo, List<GoodsAttributeDTO> goodDetailsLists, List<GoodsAttributeDTO> goodsByIdList) {
        //新增和修改
        List<String> deletePictureList = Lists.newArrayList();
        for (GoodsAttributeDTO dto : goodDetailsLists) {
            //新增和修改goods_attribute表信息
            if (Objects.isNull(dto.getGoodsAttributeId())) {
                dto.setGoodsId(goodsInfo.getId());
                dto.setCreateBy(goodsInfo.getCreateBy());
                dto.setCreateTime(LocalDateTime.now());
                dto.setAttributeDetailsSort(Objects.isNull(dto.getAttributeDetailsSort()) ? 1 : dto.getAttributeDetailsSort());
                dto.setAttributeCode(Constants.ATTRIBUTE_CODE + generateSystemCodeUtil.generateSystemCode(Constants.ATTRIBUTE_CODE));
                int goodsAttributese = goodsAttributeMapper.insertGoodsAttributes(dto);
                if (goodsAttributese <= 0) {
                    throw new ServiceException("新增商品属性表信息失败！");
                }
            } else {
                dto.setUpdateBy(goodsInfo.getCreateBy());
                dto.setUpdateTime(LocalDateTime.now());
                dto.setAttributeDetailsSort(Objects.isNull(dto.getAttributeDetailsSort()) ? 1 : dto.getAttributeDetailsSort());
                int updateGoodsAttributes = goodsAttributeMapper.updateGoodsAttributes(dto);
                if (updateGoodsAttributes <= 0) {
                    throw new ServiceException("修改商品属性表信息失败！");
                }
            }
            //新增和修改goods_attribute_Details表信息
            if (Objects.isNull(dto.getAttributeDetailsId())) {
                this.integralExchangeFlagCheck(dto);
                dto.setGoodsAttributeId(dto.getGoodsAttributeId());
                dto.setAttributeDetailsName(dto.getAttributeName());
                dto.setCreateBy(goodsInfo.getCreateBy());
                dto.setCreateTime(LocalDateTime.now());
                dto.setAttributeDetailsSort(Objects.isNull(dto.getAttributeDetailsSort()) ? 1 : dto.getAttributeDetailsSort());
                int addGoodsAttributeDetails = goodsAttributeDetailsMapper.addGoodsAttributeDetails(dto);
                if (addGoodsAttributeDetails <= 0) {
                    throw new ServiceException("新增商品属性明细表信息失败！");
                }
            } else {
                this.integralExchangeFlagCheck(dto);
                dto.setGoodsAttributeId(dto.getGoodsAttributeId());
                dto.setAttributeDetailsName(dto.getAttributeName());
                dto.setAttributeDetailsSort(Objects.isNull(dto.getAttributeDetailsSort()) ? 1 : dto.getAttributeDetailsSort());
                dto.setUpdateBy(goodsInfo.getCreateBy());
                dto.setUpdateTime(LocalDateTime.now());
                int updateGoodsAttributeDetailss = goodsAttributeDetailsMapper.updateGoodsAttributeDetailss(dto);
                if (updateGoodsAttributeDetailss <= 0) {
                    throw new ServiceException("修改商品属性明细表信息失败！");
                }
                //删除原有图片信息
                GoodsAttributeDTO goodsAttributeDTO = goodsByIdList.stream()
                        .filter(item -> Objects.nonNull(item.getGoodAttributeDetailsId()))
                        .filter(item -> dto.getAttributeDetailsId().equals(item.getGoodAttributeDetailsId()))
                        .findFirst().orElse(new GoodsAttributeDTO());
                if (StringUtils.isNotBlank(goodsAttributeDTO.getAttributePitureUrl())
                        && !goodsAttributeDTO.getAttributePitureUrl().equals(dto.getAttributePitureUrl())) {
                    deletePictureList.add(goodsAttributeDTO.getAttributePitureUrl());
                }
            }
        }
        //批量删除商品属性原有图片
        deletePictureList.forEach(this::deletePictureUrl);
    }

    /**
     * 删除商品主表图片以及商品富文本图片
     *
     * @param goodsInfo         前端传过来的商品信息
     * @param existGoodsPicture 数据库中的商品信息
     **/
    private void deleteGoodPictureUrl(GoodsInfoDTO goodsInfo, GoodsInfo existGoodsPicture) {
        if (StringUtils.isNotBlank(goodsInfo.getGoodsPictureUrl()) && StringUtils.isNotBlank(existGoodsPicture.getGoodsPictureUrl())
                && !goodsInfo.getGoodsPictureUrl().equals(existGoodsPicture.getGoodsPictureUrl())) {
            //删除商品图片主表地址
            this.deletePictureUrl(existGoodsPicture.getGoodsPictureUrl());
        }
        if (StringUtils.isNotBlank(goodsInfo.getGoodsRemark()) && StringUtils.isNotBlank(existGoodsPicture.getGoodsRemark())
                && !goodsInfo.getGoodsRemark().equals(existGoodsPicture.getGoodsRemark())) {
            //数据库中原来有的
            List<String> existGoodsImgSrc = FileUtils.getImgSrc(existGoodsPicture.getGoodsRemark());
            //前端传的
            List<String> goodsImgSrc = FileUtils.getImgSrc(goodsInfo.getGoodsRemark());
            //求图片的差集
            List<String> subtractGoodsImgSrc = new ArrayList<>(CollectionUtils.subtract(existGoodsImgSrc, goodsImgSrc));
            //删除商品图片主表地址GoodsRemark中的图片
            for (String pictureUrl : subtractGoodsImgSrc) {
                if (StringUtils.isBlank(pictureUrl)) {
                    continue;
                }
                //修改路径
                String substring = pictureUrl.substring(pictureUrl.indexOf("/profile"));
                //删除商品富文本图片
                deletePictureUrl(substring);
            }
        }
    }

    /**
     * 删除商品图片地址
     *
     * @param pictureUrl 商品图片地址
     **/
    private void deletePictureUrl(String pictureUrl) {
        if (StringUtils.isBlank(pictureUrl)) {
            return;
        }
        String picture = XinELuConfig.getProfile() + pictureUrl.replaceAll("/profile", "");
        File checkReportNameFile = new File(picture);
        if (checkReportNameFile.exists()) {
            boolean delete = checkReportNameFile.delete();
            if (BooleanUtils.isFalse(delete)) {
                throw new ServiceException("商品图片地址删除失败！");
            }
        }
    }

    /**
     * 校验商品单价和库存数量是否为负数
     *
     * @param goodsInfo 输入参数
     * @return 返回结果
     */
    private AjaxResult judgeGoodsPriceAndStock(GoodsInfoDTO goodsInfo) {
        if (CollectionUtils.isNotEmpty(goodsInfo.getGoodDetailsLists())) {
            GoodsAttributeDTO goodsAttributeDTO = goodsInfo.getGoodDetailsLists().stream().filter(item -> Objects.nonNull(item.getGoodsPrice()) && item.getGoodsPrice().compareTo(BigDecimal.ZERO) < 0).findFirst().orElse(null);
            if (Objects.nonNull(goodsAttributeDTO)) {
                return AjaxResult.error("商品单价不能为负数，请重新输入！");
            }
            GoodsAttributeDTO goodStockInfo = goodsInfo.getGoodDetailsLists().stream().filter(item -> Objects.nonNull(item.getGoodsStock()) && item.getGoodsStock() < 0).findFirst().orElse(null);
            if (Objects.nonNull(goodStockInfo)) {
                return AjaxResult.error("商品库存数量不能为负数，请重新输入！");
            }
        }
        return null;
    }

    /**
     * 校验积分兑换信息
     */
    @Override
    public void integralExchangeFlagCheck(GoodsAttributeDTO dto) {
        if (Objects.nonNull(dto.getIntegralExchangeCount()) && Objects.nonNull(dto.getGoodsStock()) && dto.getGoodsStock() < dto.getIntegralExchangeCount()) {
            throw new ServiceException("'库存数量'不能少于'积分兑换数量'!");
        }
        //如果积分兑换标识为'是'，则'积分兑换门槛'或'积分兑换商品数量'不能为空
        boolean flagBool = Objects.nonNull(dto.getIntegralExchangeFlag()) && dto.getIntegralExchangeFlag() == 1;
        boolean countBool = Objects.isNull(dto.getIntegralExchangeCount()) || Objects.isNull(dto.getIntegralExchangeSill());
        if (BooleanUtils.isTrue(flagBool) && BooleanUtils.isTrue(countBool)) {
            throw new ServiceException(dto.getAttributeName() + "的'积分兑换门槛'或'积分兑换商品数量'不能为空!");
        }
    }
}
