package com.ruoyi.frequency.mallshoppingcar.service.impl;

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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.code.DictConstant;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.enums.CoreExceptionEnum;
import com.ruoyi.controller.req.InsertShoppingCarReq;
import com.ruoyi.controller.req.ShoppingCarCreateOrderReq;
import com.ruoyi.controller.req.ShoppingCartSettlementReq;
import com.ruoyi.controller.resp.ShoppingCarListResp;
import com.ruoyi.controller.resp.ShoppingCarListVo;
import com.ruoyi.enums.MallExceptionEnum;
import com.ruoyi.enums.WalletDetailEnums;
import com.ruoyi.enums.mallorder.MallOrderStatusEnums;
import com.ruoyi.frequency.mallorder.entity.MallOrder;
import com.ruoyi.frequency.mallorder.service.MallOrderService;
import com.ruoyi.frequency.mallorderaddress.entity.MallOrderAddress;
import com.ruoyi.frequency.mallorderaddress.service.MallOrderAddressService;
import com.ruoyi.frequency.mallordergoods.entity.MallOrderGoods;
import com.ruoyi.frequency.mallordergoods.service.MallOrderGoodsService;
import com.ruoyi.frequency.mallorderstatus.service.MallOrderStatusService;
import com.ruoyi.frequency.mallspecifications.entity.MallSpecifications;
import com.ruoyi.frequency.mallspecifications.mapper.MallSpecificationsMapper;
import com.ruoyi.pay.enums.PayEnums;
import com.ruoyi.pay.enums.PaySourceEnums;
import com.ruoyi.pay.utils.PayUtil;
import com.ruoyi.response.ResponseData;
import com.ruoyi.utils.BusinessUtil;
import com.ruoyi.vo.PayVo;
import com.ruoyi.vo.UserVo;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.frequency.mallshoppingcar.mapper.MallShoppingCarMapper;
import com.ruoyi.frequency.mallshoppingcar.entity.MallShoppingCar;
import com.ruoyi.frequency.mallshoppingcar.service.MallShoppingCarService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 购物车Service业务层处理
 *
 * @author liwenlong
 * @date 2024-01-25
 */
@Service
public class MallShoppingCarServiceImpl extends ServiceImpl<MallShoppingCarMapper, MallShoppingCar>  implements MallShoppingCarService
{
    @Autowired
    private MallShoppingCarMapper mallShoppingCarMapper;

    /**
     * 查询购物车
     *
     * @param id 购物车主键
     * @return 购物车
     */
    @Override
    public MallShoppingCar selectMallShoppingCarById(Long id)
    {
        return mallShoppingCarMapper.selectMallShoppingCarById(id);
    }

    /**
     * 查询购物车列表
     *
     * @param mallShoppingCar 购物车
     * @return 购物车
     */
    @Override
    public List<MallShoppingCar> selectMallShoppingCarList(MallShoppingCar mallShoppingCar)
    {
        return mallShoppingCarMapper.selectMallShoppingCarList(mallShoppingCar);
    }

    /**
     * 新增购物车
     *
     * @param mallShoppingCar 购物车
     * @return 结果
     */
    @Override
    public int insertMallShoppingCar(MallShoppingCar mallShoppingCar)
    {
        mallShoppingCar.setCreateData();
        return mallShoppingCarMapper.insert(mallShoppingCar);
    }

    /**
     * 修改购物车
     *
     * @param mallShoppingCar 购物车
     * @return 结果
     */
    @Override
    public int updateMallShoppingCar(MallShoppingCar mallShoppingCar)
    {
        mallShoppingCar.setUpdateData();
        return mallShoppingCarMapper.updateMallShoppingCar(mallShoppingCar);
    }

    /**
     * 批量删除购物车
     *
     * @param ids 需要删除的购物车主键
     * @return 结果
     */
    @Override
    public int deleteMallShoppingCarByIds(Long[] ids,Integer delFlag)
    {
        this.lambdaUpdate().set(MallShoppingCar::getDelFlag,delFlag).in(MallShoppingCar::getId,ids).update();
        return ids.length;
    }

    @Override
    public ResponseData shoppingCarList(UserVo userVo) {

        //返回结果
        ShoppingCarListResp shoppingCarListResp = new ShoppingCarListResp();

        //查询用户购物车列表（包含已经下架的商品）
        List<ShoppingCarListVo> shoppingCarList = this.baseMapper.shoppingCarList(userVo,null);

        if (shoppingCarList.size() > 0){
            shoppingCarList.stream().forEach(s->{

                if (ObjectUtil.equal(s.getGoodsFlag(), PublicCommon.启用) && ObjectUtil.equal(s.getSpecFlag(), PublicCommon.启用)){
                    //用户购物车列表
                    shoppingCarListResp.getEffective().add(s);
                }else {
                    //已经下架的购物车列表
                    shoppingCarListResp.getInvalid().add(s);
                }
            });

        }

        return ResponseData.success(shoppingCarListResp);
    }

    @Autowired
    private BusinessUtil businessUtil;

    @Override
    public PayVo shoppingCarSettlement(ShoppingCartSettlementReq req, UserVo userVo) {

        //判断购物车商品 并返回购物车商品
        List<ShoppingCarListVo> shoppingCarList = judgeShoppingCarGoods(userVo, req.getShoppingCardIdList());

        //购物车结算金额
        return shoppingCarCount(shoppingCarList,userVo);

    }

    /**
     * 购物车结算金额
     * @param shoppingCarList
     * @return
     */
    private PayVo shoppingCarCount(List<ShoppingCarListVo> shoppingCarList,UserVo userVo) {

        //购物车总金额
        BigDecimal totalPrice = new BigDecimal(0);

        //购物车总积分
        BigDecimal totalIntegral = new BigDecimal(0);

        for (ShoppingCarListVo vo : shoppingCarList) {
            totalPrice = totalPrice.add(vo.getPrice().multiply(new BigDecimal(vo.getQuantity())));

            totalIntegral = totalIntegral.add(vo.getIntegral().multiply(new BigDecimal(vo.getQuantity())));
        }

        //获取购物车最大使用赠送金额
        BigDecimal maxGivePrice =  businessUtil.userMaxGivePrice(userVo,totalPrice);

        return new PayVo(totalPrice,totalIntegral,maxGivePrice);
    }

    /**
     * 判断购物车商品 并返回购物车商品
     * @param userVo
     * @param shoppingCardIdList
     * @return 购物车商品
     */
    private  List<ShoppingCarListVo> judgeShoppingCarGoods(UserVo userVo, List<Long> shoppingCardIdList) {

        //查询用户购物车列表（包含已经下架的商品）
        List<ShoppingCarListVo> shoppingCarList = this.baseMapper.shoppingCarList(userVo,shoppingCardIdList);

        //下架的购物车列表
        List<ShoppingCarListVo> invalidList = new ArrayList<>();

        //库存不足的购物车列表
        List<ShoppingCarListVo> notStockList = new ArrayList<>();

        if (shoppingCarList.size() > 0){
            shoppingCarList.stream().forEach(s->{

                if (ObjectUtil.notEqual(s.getGoodsFlag(), PublicCommon.启用) || ObjectUtil.notEqual(s.getSpecFlag(), PublicCommon.启用)){
                    invalidList.add(s);
                }

                if (s.getQuantity() > s.getStock()){
                    notStockList.add(s);
                }
            });

            //判断购物车中商品是否下架
            if (invalidList.size() > 0){
                throw new CustomException(MallExceptionEnum.GOODS_DEL_FLAG,invalidList);
            }
            //判断商品库存是否足够
            if (notStockList.size() > 0){
                throw new CustomException(MallExceptionEnum.NOT_STOCK,notStockList);
            }

        }

        return shoppingCarList;
    }

    @Override
    public ResponseData insertShoppingCar(InsertShoppingCarReq req, UserVo userVo) {

        //查询购物车
        MallShoppingCar shoppingCar = baseMapper.selectOne(new QueryWrapper<MallShoppingCar>().lambda()
                .eq(MallShoppingCar::getUserId, userVo.getUserId())
                .eq(MallShoppingCar::getUserType, userVo.getUserType())
                .eq(MallShoppingCar::getSkuId, req.getSpeId()));

        if (shoppingCar != null) {
            shoppingCar.setQuantity(req.getQuantity());
            if (shoppingCar.getQuantity() == 0) {
                baseMapper.deleteById(shoppingCar.getId());
            } else {
                int resultCount = this.baseMapper.updateById(shoppingCar);
                if (resultCount == 0) {
                    return ResponseData.error("加入购物车失败");
                }
            }
        } else {
            shoppingCar = new MallShoppingCar();
            shoppingCar.setUserId(userVo.getUserId());
            shoppingCar.setUserType(userVo.getUserType());
            shoppingCar.setGoodsId(req.getGoodsId());
            shoppingCar.setSkuId(req.getSpeId());
            shoppingCar.setQuantity(req.getQuantity());
            int resultCount = this.baseMapper.insert(shoppingCar);
            if (resultCount == 0) {
                return ResponseData.error("加入购物车失败");
            }
        }
        return ResponseData.success();
    }

    @Override
    public ResponseData removeShoppingCarGoods(List<Long> ids, UserVo userVo) {

        if (CollectionUtil.isEmpty(ids)){
            return ResponseData.error(CoreExceptionEnum.NOT_NULL_PARAM);
        }

        int result = this.baseMapper.deleteBatchIds(ids);

        if (result == 0) {
            return ResponseData.error(MallExceptionEnum.DELETER_SHOPPING_CAR_ERROR);
        }

        return ResponseData.success();
    }

    @Autowired
    private MallSpecificationsMapper specificationsMapper;

    @Autowired
    private PayUtil payUtil;

    @Autowired
    private MallOrderAddressService orderAddressService;

    @Autowired
    private MallOrderStatusService orderStatusService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseData shoppingCarCreateOrder(ShoppingCarCreateOrderReq req, UserVo userVo) {


        //判断购物车商品 并返回购物车商品
        List<ShoppingCarListVo> shoppingCarList = judgeShoppingCarGoods(userVo, req.getShoppingCardIdList());

        if (shoppingCarList.size() == 0){
            return ResponseData.error("购物车数据为空");
        }

        //购物车结算金额
        PayVo payVo = shoppingCarCount(shoppingCarList, userVo);

        //判断余额
        if (ObjectUtil.equal(PayEnums.balance.getCode(),req.getPayType())){
            businessUtil.judgeBalancePay(userVo,payVo.getPrice(),req.getBalancePayPwd());
        }

        //判断积分余额
        businessUtil.judgeIntegralPay(userVo,payVo.getIntegral(),req.getBalancePayPwd());

        //扣除库存
        List<MallSpecifications> specList = shoppingCarList.stream().map(s -> new MallSpecifications().setId(s.getSpecId()).setStock(s.getQuantity())).collect(Collectors.toList());
        Boolean updateStock = specificationsMapper.subStock(specList);
        if (!updateStock){
            throw new CustomException(MallExceptionEnum.NOT_STOCK);
        }

        //组装订单
        MallOrder order = assembleOrder(userVo, req,payVo);
        orderService.save(order);

        //关联订单商品中间表
        List<MallOrderGoods> mallOrderGoods = assembleOrderGoods(shoppingCarList, order.getId());
        orderGoodsService.saveBatch(mallOrderGoods);

        //关联订单地址关联表
        MallOrderAddress orderAddress = orderAddressService.assembleOrderAddress(order.getId(),req.getAddressId());
        orderAddressService.saveOrUpdate(orderAddress);

        //删除购物车
        this.baseMapper.deleteBatchIds(req.getShoppingCardIdList());

        //记录订单状态
        orderStatusService.recordOrderStatus(order, MallOrderStatusEnums.待付款);

        //支付
        ResponseData responseData = payUtil.pay(userVo, order.getId(), req.getPayType(), payVo.getPrice().subtract(payVo.getMaxGivePrice()), payVo.getMaxGivePrice(), order.getPayOrderNo(), PaySourceEnums.mall_order_pay, WalletDetailEnums.MALL_ORDER_PAY);

        //支付成功/支付金额为0
        if (responseData.getSuccess() || responseData.getCode().equals(210)) {
            //余额支付/苹果支付
            if (req.getPayType().equals(PayEnums.balance.getCode()) || req.getPayType().equals(PayEnums.apple.getCode())) {
                orderService.after(order);
            }
        }

        Map<String,Object> map = new HashMap<>();
        map.put("orderId",order.getId());
        responseData.setData(JSONObject.toJSON(map));

        return responseData;
    }

    @Autowired
    private MallOrderGoodsService orderGoodsService;

    /**
     * 组装订单
     * @param userVo
     * @param req
     * @return
     */
    private MallOrder assembleOrder(UserVo userVo,ShoppingCarCreateOrderReq req,
                                    PayVo payVo){

        MallOrder order = new MallOrder()
                .setOrderNo(orderService.generateOrderNo(1))
                .setUserId(userVo.getUserId())
                .setUserType(userVo.getUserType())
                .setGoodsPrice(payVo.getPrice())
                .setPayType(req.getPayType())
                .setRemark(req.getRemark())
                .setPayOrderNo(orderService.generateOrderNo(2))
                .setPayPrice(payVo.getPrice())
                .setOrderStatus(MallOrderStatusEnums.待付款.getCode())
                .setIntegralPrice(payVo.getIntegral())
                .setGivePrice(payVo.getMaxGivePrice())
                ;

        //售后时间
        SysDictData dictOne = businessUtil.getDict(DictConstant.MallOrderDict.售后天数);
        order.setAfterSalesDays(dictOne == null ? 7 : Integer.valueOf(dictOne.getDictValue()));

        return order;
    }

    /**
     * 订单商品中间表
     * @param shoppingCarListVos
     * @param orderId
     * @return
     */
    private List<MallOrderGoods> assembleOrderGoods(List<ShoppingCarListVo> shoppingCarListVos,Long orderId){

        //订单商品关联集合
        List<MallOrderGoods> orderGoodsList = new ArrayList<>();

        //生成订单商品表
        for (ShoppingCarListVo s : shoppingCarListVos) {

            //订单商品
            MallOrderGoods orderGoods = new MallOrderGoods().setGoodsId(s.getGoodsId())
                    .setGoodsName(s.getGoodsName())
                    .setOrderId(orderId)
                    .setGoodsImage(s.getCoverImage())
                    .setSpecImage(s.getImage())
                    .setUnitPrice(s.getPrice())
                    .setUnitIntegral(s.getIntegral())
                    .setBuyNum(s.getQuantity())
                    .setSpecName(s.getSpecName())
                    .setGoodsId(s.getGoodsId())
                    .setSpecId(s.getSpecId())
                    ;
            orderGoodsList.add(orderGoods);
        }

        return orderGoodsList;
    }

    @Autowired
    private MallOrderService orderService;

}
