package cn.newfeifan.mall.module.product.service.spuapply;

import cn.newfeifan.mall.framework.common.exception.ErrorCode;
import cn.newfeifan.mall.module.product.controller.admin.skuapply.vo.SkuApplySaveReqVO;
import cn.newfeifan.mall.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO;
import cn.newfeifan.mall.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO;
import cn.newfeifan.mall.module.product.convert.spuapply.SpuApplyConvert;
import cn.newfeifan.mall.module.product.dal.dataobject.skuapply.SkuApplyDO;
import cn.newfeifan.mall.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.newfeifan.mall.module.product.enums.spu.ProductSpuStatusEnum;
import cn.newfeifan.mall.module.product.enums.spu.SpuApplyCheckStatusEnum;
import cn.newfeifan.mall.module.product.service.category.ProductCategoryService;
import cn.newfeifan.mall.module.product.service.skuapply.SkuApplyService;
import cn.newfeifan.mall.module.product.service.spu.ProductSpuService;
import cn.newfeifan.mall.module.promotion.controller.admin.diy.vo.page.DiyPageUpdateReqVO;
import cn.newfeifan.mall.module.promotion.dal.dataobject.diy.DiyPageDO;
import cn.newfeifan.mall.module.promotion.service.diy.DiyPageService;
import cn.newfeifan.mall.module.system.api.sms.SmsCodeApi;
import cn.newfeifan.mall.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
import cn.newfeifan.mall.module.system.controller.admin.user.vo.user.UserShopDetailsVO;
import cn.newfeifan.mall.module.system.dal.dataobject.user.AdminUserDO;
import cn.newfeifan.mall.module.system.enums.sms.SmsSceneEnum;
import cn.newfeifan.mall.module.system.service.permission.PermissionService;
import cn.newfeifan.mall.module.system.service.permission.RoleService;
import cn.newfeifan.mall.module.system.service.user.AdminUserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;

import cn.newfeifan.mall.module.product.controller.admin.spuapply.vo.*;
import cn.newfeifan.mall.module.product.dal.dataobject.spuapply.SpuApplyDO;
import cn.newfeifan.mall.framework.common.pojo.PageResult;
import cn.newfeifan.mall.framework.common.util.object.BeanUtils;

import cn.newfeifan.mall.module.product.dal.mysql.spuapply.SpuApplyMapper;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.framework.common.util.collection.CollectionUtils.*;
import static cn.newfeifan.mall.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.newfeifan.mall.module.product.dal.dataobject.category.ProductCategoryDO.CATEGORY_LEVEL;
import static cn.newfeifan.mall.module.product.enums.ErrorCodeConstants.*;

/**
 * 商品spu申请 Service 实现类
 *
 * @author 非繁人
 */
@Service
@Validated
public class SpuApplyServiceImpl implements SpuApplyService {

    @Resource
    private SpuApplyMapper spuApplyMapper;
    @Resource
    private SkuApplyService skuApplyService;
    @Resource
    private AdminUserService adminUserService;
    @Resource
    private ProductCategoryService categoryService;
    @Resource
    private AdminUserService userService;
    @Resource
    private ProductSpuService spuService;
    @Resource
    private RoleService roleService;
    @Resource
    private PermissionService permissionService;
    @Resource
    private SmsCodeApi smsCodeApi;
    @Resource
    private DiyPageService diyPageService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createSpuApply(SpuApplySaveReqVO createReqVO) {
// 校验分类、品牌
        validateCategory(createReqVO.getCategoryId());
//        brandService.validateProductBrand(createReqVO.getBrandId());

        // 根据商户ID查询对应的店铺ID
        // todo 后续如果存在多店铺的情况


        // 校验 SKU
        List<SkuApplySaveReqVO> skuSaveReqList = createReqVO.getSkus();
        skuApplyService.validateSkuList(skuSaveReqList, createReqVO.getSpecType());

        SpuApplyDO spuApply = BeanUtils.toBean(createReqVO, SpuApplyDO.class);
        // 初始化 SPU 中 SKU 相关属性
        initSpuFromSkus(spuApply, skuSaveReqList, true);

        //加入商户、店铺信息
        UserShopDetailsVO userShopDetails = userService.getUserShopDetails();

        spuApply.setShopId(userShopDetails.getShopId());
        spuApply.setMerchantId(userShopDetails.getMerId());

        //最大推广费, 单位: 分
        Integer maxPromotionFee = 0;
        for (SkuApplySaveReqVO productSkuSaveReqVO : skuSaveReqList) {
            productSkuSaveReqVO.setShopId(userShopDetails.getShopId());
            productSkuSaveReqVO.setMerchantId(userShopDetails.getMerId());

            Integer skuPromotionFee = productSkuSaveReqVO.getPromotionFee();
            if (skuPromotionFee > maxPromotionFee)
                maxPromotionFee = skuPromotionFee;
        }

        spuApply.setApplyMemberUserId(getLoginUserId());
        spuApply.setPromotionFee(maxPromotionFee);
        // 插入 SPU
        spuApplyMapper.insert(spuApply);
        // 插入 SKU
        skuApplyService.createSkuList(spuApply.getId(), skuSaveReqList);

        // 发送短信
        sendSms(createReqVO.getName());

        // 返回
        return spuApply.getId();
    }

    /**
     * 基于 SKU 的信息，初始化 SPU 的信息
     * 主要是计数相关的字段，例如说市场价、最大最小价、库存等等
     *
     * @param spu   商品 SPU
     * @param skus  商品 SKU 数组
     * @param isAdd 是否为新增
     */
    private void initSpuFromSkus(SpuApplyDO spu, List<SkuApplySaveReqVO> skus, Boolean isAdd) {
        //是否是高精度商品
        // sku 单价最低的商品的价格
        spu.setPrice(getMinValue(skus, SkuApplySaveReqVO::getPrice));
        // sku 单价最低的商品的市场价格
        spu.setMarketPrice(getMinValue(skus, SkuApplySaveReqVO::getMarketPrice));
        // sku 单价最低的商品的成本价格
        spu.setCostPrice(getMinValue(skus, SkuApplySaveReqVO::getCostPrice));

        // skus 库存总数
        spu.setStock(getSumValue(skus, SkuApplySaveReqVO::getStock, Integer::sum));
        // 若是 spu 已有状态则不处理
        if (spu.getStatus() == null) {
            if (isAdd) {
                spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); // 默认状态为上架
            }
            spu.setSalesCount(0); // 默认商品销量
            spu.setBrowseCount(0); // 默认商品浏览量
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSpuApply(SpuApplySaveReqVO updateReqVO) {
        // 校验存在
        validateSpuApplyExists(updateReqVO.getId());

        // 校验分类、品牌
        validateCategory(updateReqVO.getCategoryId());

        // 获取原来的SPU对比
        SpuApplyRespVO spuApplyDetail = getSpuApplyDetail(updateReqVO.getId());


//        brandService.validateProductBrand(updateReqVO.getBrandId());
        // 校验SKU
        List<SkuApplySaveReqVO> skuSaveReqList = updateReqVO.getSkus();
        skuApplyService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType());

        // 更新 SPU
        SpuApplyDO updateObj = BeanUtils.toBean(updateReqVO, SpuApplyDO.class);
        SpuApplyDO spuApplyDO = spuApplyMapper.selectById(updateReqVO.getId());
        updateObj.setStatus(spuApplyDO.getStatus());
        initSpuFromSkus(updateObj, skuSaveReqList, false);

        //最大推广费, 单位: 分  add by Ben
        Integer maxPromotionFee = 0;

        for (SkuApplySaveReqVO productSkuSaveReqVO : skuSaveReqList) {
            productSkuSaveReqVO.setShopId(updateReqVO.getShopId());
            productSkuSaveReqVO.setMerchantId(updateReqVO.getMerchantId());

            Integer skuPromotionFee = productSkuSaveReqVO.getPromotionFee();
            if (skuPromotionFee > maxPromotionFee)
                maxPromotionFee = skuPromotionFee;
        }

        updateObj.setPromotionFee(maxPromotionFee);
        updateObj.setCheckStatus(SpuApplyCheckStatusEnum.WAIT_CHECK.getStatus());

        // 有部分字段更新了才需要审核，否则不需要审核
        if (spuApplyDetail.getName().equals(updateReqVO.getName()) &&
                spuApplyDetail.getProducerArea().equals(updateReqVO.getProducerArea()) &&
                spuApplyDetail.getKeyword().equals(updateReqVO.getKeyword()) &&
                spuApplyDetail.getIntroduction().equals(updateReqVO.getIntroduction()) &&
                spuApplyDetail.getSliderPicUrls().equals(updateReqVO.getSliderPicUrls()) &&
                spuApplyDetail.getDescription().equals(updateReqVO.getDescription()) &&
                spuApplyDetail.getSkus().size() == updateReqVO.getSkus().size()
        ) {
            boolean flag = isFlag(updateReqVO, spuApplyDetail);

            // 如果关键消息没有变动那就不用审核，直接更新到商品中，并且不用发送审核短信
            if (flag) {
                updateObj.setCheckStatus(SpuApplyCheckStatusEnum.CHECK_PASS.getStatus());

                // 更新商品
                ProductSpuSaveReqVO bean = BeanUtils.toBean(updateReqVO, ProductSpuSaveReqVO.class);

                ProductSpuDO spu = spuService.getSpuByApplyId(updateReqVO.getId());
                bean.setId(spu.getId());
                spuService.updateSpu(bean);
            }
        }

        spuApplyMapper.updateById(updateObj);
        // 批量更新 SKU
        skuApplyService.updateSkuList(updateObj.getId(), updateReqVO.getSkus());

//        // 发送审核短信
//        if (updateObj.getCheckStatus().equals(SpuApplyCheckStatusEnum.WAIT_CHECK.getStatus())) {
//            // 发送短信
//            sendSms(updateReqVO.getName());
//        }

    }

    /**
     * 发送商品申请短信
     *
     * @param spuName 商品名称
     */
    private void sendSms(String spuName) {
        // 商品审核角色编号
        Long ptSpuCheck = roleService.getPtSpuCheck();
        // 系统用户ids
        List<Long> userIds = permissionService.getPtSpuCheckUserIds(ptSpuCheck);
        // 系统用户s
        List<AdminUserDO> users = adminUserService.getUserList(userIds);

        for (AdminUserDO user : users) {
            SmsCodeSendReqDTO smsCodeSendReqDTO = SmsCodeSendReqDTO.builder()
                    .mobile(user.getMobile())
                    .scene(SmsSceneEnum.SPU_APPLY_INFORM.getScene())
                    .createIp(getClientIP())
                    .name(spuName)
                    .build();
            smsCodeApi.sendSmsCode(smsCodeSendReqDTO);
        }
    }

    /**
     * 是否需要审核
     *
     * @param updateReqVO    原数据
     * @param spuApplyDetail 新数据
     * @return bool
     */
    private static boolean isFlag(SpuApplySaveReqVO updateReqVO, SpuApplyRespVO spuApplyDetail) {
        boolean flag = true;
        for (int i = 0; i < spuApplyDetail.getSkus().size(); i++) {
            if (!spuApplyDetail.getSkus().get(i).getSettlementPrice().equals(updateReqVO.getSkus().get(i).getSettlementPrice()) ||
                    !spuApplyDetail.getSkus().get(i).getCostPrice().equals(updateReqVO.getSkus().get(i).getCostPrice())
            ) {
                flag = false;
                break;
            }
        }
        return flag;
    }

    @Override
    public void deleteSpuApply(Long id) {
        // 校验存在
        validateSpuApplyExists(id);
        // 删除
        spuApplyMapper.deleteById(id);

        ProductSpuDO spu = spuService.getSpuByApplyId(id);
        spuService.deleteSpu(spu.getId());
    }

    private void validateSpuApplyExists(Long id) {
        if (spuApplyMapper.selectById(id) == null) {
            throw exception(SPU_APPLY_NOT_EXISTS);
        }
    }

    private void validateCategory(Long id) {
        categoryService.validateCategory(id);
        // 校验层级
        if (categoryService.getCategoryLevel(id) < CATEGORY_LEVEL) {
            throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR);
        }
    }

    @Override
    public SpuApplyDO getSpuApply(Long id) {
        return spuApplyMapper.selectById(id);
    }

    @Override
    public PageResult<SpuApplyDO> getSpuApplyPage(SpuApplyPageReqVO pageReqVO) {

        UserShopDetailsVO userShopDetails = adminUserService.getUserShopDetails();
        pageReqVO.setShopId(userShopDetails.getShopId());
        pageReqVO.setMerchantId(userShopDetails.getMerId());
        return spuApplyMapper.selectPage(pageReqVO);
    }

    @Override
    public SpuApplyDO getSpu(Long id) {
        return spuApplyMapper.selectById(id);
    }

    @Override
    public SpuApplyRespVO getSpuApplyDetail(Long id) {
        // 获得商品 SPU 申请
        SpuApplyDO spu = getSpu(id);
        if (spu == null) {
            return null;
        }
        // 查询商品 SKU
        List<SkuApplyDO> skus = skuApplyService.getSkuListBySpuId(spu.getId());

        String shopName = spuApplyMapper.selectShopNameById(spu.getShopId());

        SpuApplyRespVO convert = SpuApplyConvert.INSTANCE.convert(spu, skus);
        convert.setShopName(shopName);
        return convert;
    }

    @Override
    public void updateSpuStatus(ProductSpuUpdateStatusReqVO updateReqVO) {

        // 商户不允许回收商品
        if (updateReqVO.getStatus().equals(ProductSpuStatusEnum.RECYCLE.getStatus())) {
            ErrorCode ERROR = new ErrorCode(1_008_005_001, "商户不允许回收商品");
            throw exception(ERROR);
        }

        // 如果商户的商品在回收站中,则商品不允许上下架
        SpuApplyDO spuApplyDO = spuApplyMapper.selectById(updateReqVO.getId());
        if (spuApplyDO.getStatus().equals(ProductSpuStatusEnum.RECYCLE.getStatus())) {
            ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品在回收站中不允许上下架");
            throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR);
        }

        // 校验存在
        validateSpuApplyExists(updateReqVO.getId());
        // TODO 非繁人：【可选】参与活动中的商品，不允许下架？？？

        // 更新状态
        SpuApplyDO productSpuDO = spuApplyMapper.selectById(updateReqVO.getId()).setStatus(updateReqVO.getStatus());
        spuApplyMapper.updateById(productSpuDO);

        ProductSpuDO spu = spuService.getSpuByApplyId(updateReqVO.getId()).setStatus(updateReqVO.getStatus());
        spuService.updateById(spu);


        // 修改首页面的商品展示,如果商品下架要看有没有展示,要去除
        if (updateReqVO.getStatus().equals(ProductSpuStatusEnum.DISABLE.getStatus())) {
            DiyPageDO diyPage = diyPageService.getDiyPage(7L);
            if (diyPage.getProperty().contains(spu.getId().toString() + ",")) {
                diyPage.setProperty(diyPage.getProperty().replace(spu.getId() + ",", ""));
                diyPageService.updateDiyPage(BeanUtils.toBean(diyPage, DiyPageUpdateReqVO.class));
            }else if(diyPage.getProperty().contains(spu.getId() + "]")){
                diyPage.setProperty(diyPage.getProperty().replace("," +spu.getId() + "]", "]"));
                diyPageService.updateDiyPage(BeanUtils.toBean(diyPage, DiyPageUpdateReqVO.class));
            }
        }
    }

}