package co.yixiang.yshop.module.order.service.storeaftersales;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.constant.ShopConstants;
import co.yixiang.yshop.framework.common.enums.OrderInfoEnum;
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
import co.yixiang.yshop.module.member.dal.dataobject.user.MemberUserDO;
import co.yixiang.yshop.module.member.service.user.MemberUserService;
import co.yixiang.yshop.module.order.controller.app.afterorder.param.AppProsuctParam;
import co.yixiang.yshop.module.order.controller.app.afterorder.param.AppStoreAfterSalesParam;
import co.yixiang.yshop.module.order.controller.app.afterorder.vo.AppStoreAfterSalesVo;
import co.yixiang.yshop.module.order.controller.app.afterorder.vo.AppStoreOrderCartInfoVo;
import co.yixiang.yshop.module.order.convert.storeaftersales.StoreAfterSalesConvert;
import co.yixiang.yshop.module.order.dal.dataobject.storeaftersales.StoreAfterSalesDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeaftersalesitem.StoreAfterSalesItemDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeaftersalesstatus.StoreAfterSalesStatusDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeordercartinfo.StoreOrderCartInfoDO;
import co.yixiang.yshop.module.order.dal.mysql.storeaftersales.StoreAfterSalesMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeaftersalesitem.StoreAfterSalesItemMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeaftersalesstatus.StoreAfterSalesStatusMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeorder.StoreOrderMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeordercartinfo.StoreOrderCartInfoMapper;
import co.yixiang.yshop.module.order.dal.redis.ofterorder.AfterOrderRedisDAO;
import co.yixiang.yshop.module.order.enums.AfterChangeTypeEnum;
import co.yixiang.yshop.module.order.enums.AfterSalesStatusEnum;
import co.yixiang.yshop.module.order.enums.AfterStatusEnum;
import co.yixiang.yshop.module.order.service.storeaftersalesstatus.StoreAfterSalesStatusService;
import co.yixiang.yshop.module.product.controller.app.cart.vo.AppStoreCartQueryVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.*;

/**
 * 售后记录 Service 实现类
 *
 * @author yshop
 */
@Service
@Validated
public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMapper, StoreAfterSalesDO> implements AppStoreAfterSalesService {

    @Resource
    private StoreAfterSalesMapper storeAfterSalesMapper;
    @Resource
    private StoreOrderMapper storeOrderMapper;
    @Resource
    private AfterOrderRedisDAO afterOrderRedisDAO;
    @Resource
    private StoreOrderCartInfoMapper storeOrderCartInfoMapper;
    @Resource
    private StoreAfterSalesItemMapper storeAfterSalesItemMapper;
    @Resource
    private StoreAfterSalesStatusMapper storeAfterSalesStatusMapper;
    @Resource
    private MemberUserService memberUserService;
    @Resource
    private StoreAfterSalesStatusService storeAfterSalesStatusService;

    /**
     * 创建售后订单
     *
     * @param userId               用户id
     * @param storeAfterSalesParam /
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void applyForAfterSales(Long userId, AppStoreAfterSalesParam storeAfterSalesParam) {

        MemberUserDO userDO = memberUserService.getById(userId);
        StoreOrderDO yxStoreOrder = storeOrderMapper.selectOne(Wrappers.<StoreOrderDO>lambdaQuery()
                .eq(StoreOrderDO::getOrderId, storeAfterSalesParam.getOrderCode())
                .eq(StoreOrderDO::getUid, userId));
        afterOrderRedisDAO.set(userId,storeAfterSalesParam.getOrderCode(),yxStoreOrder.getStatus().toString());
        checkOrder(yxStoreOrder);
        //商品除去优惠后的总价格
        BigDecimal totalPrice = BigDecimal.ZERO;
        //拿到所有的商品
        List<StoreOrderCartInfoDO> yxStoreOrderCartInfos = storeOrderCartInfoMapper
                .selectList(Wrappers.<StoreOrderCartInfoDO>lambdaQuery()
                        .eq(StoreOrderCartInfoDO::getOid, yxStoreOrder.getId()));
        for (StoreOrderCartInfoDO yxStoreOrderCartInfo : yxStoreOrderCartInfos) {
            AppStoreCartQueryVo cartInfo = JSONObject.parseObject(yxStoreOrderCartInfo.getCartInfo(), AppStoreCartQueryVo.class);
            AppProsuctParam prosuctParam = storeAfterSalesParam.getProductParamList().stream()
                    .filter(item -> item.getProductId().equals(yxStoreOrderCartInfo.getProductId()))
                    .findFirst().orElse(new AppProsuctParam());
            if (prosuctParam.getProductId() != null) {
                //商品优惠前总金额
                BigDecimal totalAmountOfGoods = NumberUtil.mul(cartInfo.getTruePrice(), cartInfo.getCartNum());
                //商品优惠总金额
                BigDecimal commodityDiscountAmount = NumberUtil.mul(NumberUtil.div(totalAmountOfGoods, NumberUtil.sub(yxStoreOrder.getTotalPrice(), yxStoreOrder.getPayPostage())), yxStoreOrder.getCouponPrice());
                //商品优惠后总金额
                totalPrice = NumberUtil.add(totalPrice, NumberUtil.sub(totalAmountOfGoods, commodityDiscountAmount));
                // todo 根据自己的业务逻辑修改，是否退运费，默认退运费
                totalPrice = NumberUtil.add(totalPrice, yxStoreOrder.getPayPostage());
                yxStoreOrderCartInfo.setIsAfterSales(0);
                storeOrderCartInfoMapper.updateById(yxStoreOrderCartInfo);

            }
        }
        //更新订单状态
        yxStoreOrder.setStatus(OrderInfoEnum.STATUS_NE1.getValue());
        yxStoreOrder.setRefundStatus(OrderInfoEnum.REFUND_STATUS_1.getValue());
        yxStoreOrder.setRefundReasonWap(storeAfterSalesParam.getReasonForApplication());
        yxStoreOrder.setRefundReasonWapExplain(storeAfterSalesParam.getApplicationInstructions());
        yxStoreOrder.setRefundReasonTime(LocalDateTime.now());
        storeOrderMapper.updateById(yxStoreOrder);
        //生成售后订单
        StoreAfterSalesDO storeAfterSales = new StoreAfterSalesDO();
        storeAfterSales.setOrderCode(storeAfterSalesParam.getOrderCode());
        storeAfterSales.setRefundAmount(totalPrice);
        storeAfterSales.setServiceType(storeAfterSalesParam.getServiceType());
        storeAfterSales.setReasons(storeAfterSalesParam.getReasonForApplication());
        storeAfterSales.setExplains(storeAfterSalesParam.getApplicationInstructions());
        storeAfterSales.setExplainImg(storeAfterSalesParam.getApplicationDescriptionPicture());
        storeAfterSales.setState(AfterSalesStatusEnum.STATUS_0.getValue());
        storeAfterSales.setSalesState(AfterStatusEnum.STATE_0.getValue());
        storeAfterSales.setCreateTime(LocalDateTime.now());
        storeAfterSales.setUserId(userId);
        this.baseMapper.insert(storeAfterSales);
        //售后商品详情
        for (AppProsuctParam prosuctParam : storeAfterSalesParam.getProductParamList()) {
            StoreOrderCartInfoDO yxStoreOrderCartInfo = yxStoreOrderCartInfos.stream()
                    .filter(item -> item.getProductId().equals(prosuctParam.getProductId()))
                    .findFirst().orElse(new StoreOrderCartInfoDO());
            StoreAfterSalesItemDO storeAfterSalesItem = new StoreAfterSalesItemDO();
            storeAfterSalesItem.setStoreAfterSalesId(storeAfterSales.getId());
            storeAfterSalesItem.setProductId(yxStoreOrderCartInfo.getProductId());
            storeAfterSalesItem.setCartInfo(yxStoreOrderCartInfo.getCartInfo());
            storeAfterSalesItemMapper.insert(storeAfterSalesItem);
        }

        //操作记录
        storeAfterSalesStatusService.create(storeAfterSales.getUserId(),storeAfterSales.getId()
                ,AfterChangeTypeEnum.STATE_0.getValue(),AfterChangeTypeEnum.STATE_0.getDesc());

    }

    /**
     * 查询订单详情
     * @param key 订单号
     * @return
     */
    @Override
    public List<AppStoreOrderCartInfoVo> checkOrderDetails(String key) {
        List<StoreOrderCartInfoDO> yxStoreOrderCartInfos = storeOrderCartInfoMapper.selectList(Wrappers.<StoreOrderCartInfoDO>lambdaQuery().eq(StoreOrderCartInfoDO::getOid, key));
        StoreOrderDO yxStoreOrder = storeOrderMapper.selectById(key);
        //查询 售后信息
        StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery().eq(StoreAfterSalesDO::getOrderCode, yxStoreOrder.getOrderId()));
        List<AppStoreOrderCartInfoVo> yxStoreOrderCartInfoVos = new ArrayList<>();
        for (StoreOrderCartInfoDO yxStoreOrderCartInfo : yxStoreOrderCartInfos) {

            AppStoreOrderCartInfoVo yxStoreOrderCartInfoVo = new AppStoreOrderCartInfoVo();
            yxStoreOrderCartInfoVo.setId(yxStoreOrderCartInfo.getId());
            yxStoreOrderCartInfoVo.setOid(yxStoreOrderCartInfo.getOid());
            yxStoreOrderCartInfoVo.setCartId(yxStoreOrderCartInfo.getCartId());
            yxStoreOrderCartInfoVo.setProductId(yxStoreOrderCartInfo.getProductId());
            AppStoreCartQueryVo cartInfo = JSONObject.parseObject(yxStoreOrderCartInfo.getCartInfo(), AppStoreCartQueryVo.class);
            yxStoreOrderCartInfoVo.setCartInfo(cartInfo);
            yxStoreOrderCartInfoVo.setUnique(yxStoreOrderCartInfo.getUnique());
            yxStoreOrderCartInfoVo.setIsAfterSales(yxStoreOrderCartInfo.getIsAfterSales() == null ? 0 : yxStoreOrderCartInfo.getIsAfterSales());

            //商品优惠前总金额
            BigDecimal totalAmountOfGoods = NumberUtil.mul(cartInfo.getTruePrice(), cartInfo.getCartNum());
            //商品优惠总金额
            BigDecimal commodityDiscountAmount = NumberUtil.mul(NumberUtil.div(totalAmountOfGoods, NumberUtil.sub(yxStoreOrder.getTotalPrice(), yxStoreOrder.getPayPostage())), yxStoreOrder.getCouponPrice());

            yxStoreOrderCartInfoVo.setRefundablePrice(NumberUtil.sub(totalAmountOfGoods, commodityDiscountAmount));

            yxStoreOrderCartInfoVo.setReasons(storeAfterSales.getReasons());
            yxStoreOrderCartInfoVos.add(yxStoreOrderCartInfoVo);
        }

        return yxStoreOrderCartInfoVos;

    }


    /**
     * 查询列表
     * @param uid 用户id
     * @param status 状态    //状态 0已提交等待平台审核 1平台已审核 等待用户发货/退款 2 用户已发货 3退款成功
     * @param page 页
     * @param orderCode
     * @param limit 数量
     * @return
     */
    @Override
    public List<AppStoreAfterSalesVo> salesList(Long uid, Integer status, Integer page, String orderCode, Integer limit) {
        Page<StoreAfterSalesDO> storeAfterSalesPage = new Page<>(page, limit);
        List<Integer> integers = new ArrayList<>();
        if (status == 1) {
            integers.add(AfterSalesStatusEnum.STATUS_0.getValue());
            integers.add(AfterSalesStatusEnum.STATUS_1.getValue());
            integers.add(AfterSalesStatusEnum.STATUS_2.getValue());
        }else if (status == 2) {
            integers.add(AfterSalesStatusEnum.STATUS_3.getValue());
        }else {
            integers.add(AfterSalesStatusEnum.STATUS_0.getValue());
            integers.add(AfterSalesStatusEnum.STATUS_1.getValue());
            integers.add(AfterSalesStatusEnum.STATUS_2.getValue());
            integers.add(AfterSalesStatusEnum.STATUS_3.getValue());
        }
        baseMapper.selectPage(storeAfterSalesPage, Wrappers.<StoreAfterSalesDO>lambdaQuery()
                .eq(uid != null, StoreAfterSalesDO::getUserId, uid).in(status.equals(AfterSalesStatusEnum.STATUS_1.getValue()), StoreAfterSalesDO::getState, integers)
                .in(!status.equals(AfterSalesStatusEnum.STATUS_0.getValue()), StoreAfterSalesDO::getState, integers)
                .eq(StringUtils.isNotBlank(orderCode), StoreAfterSalesDO::getOrderCode, orderCode)
                .orderByDesc(StoreAfterSalesDO::getCreateTime));

        List<AppStoreAfterSalesVo> storeAfterSalesVos = StoreAfterSalesConvert.INSTANCE.convertList1(storeAfterSalesPage.getRecords());
        return storeAfterSalesVos.stream().map(this::handleSales).collect(Collectors.toList());
    }


    /**
     * 查询详情
     * @param key 订单号
     * @param id 售后单id
     * @param uid 用户id
     */
    @Override
    public AppStoreAfterSalesVo getStoreInfoByOrderCodeAndAfterIdAndUid(String key, Long id, Long uid) {
        if (StrUtil.isEmpty(key)) {
            throw exception(PARAM_ERROR);
        }
        StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery()
                .eq(id != null, StoreAfterSalesDO::getId, id)
                .eq(StoreAfterSalesDO::getUserId, uid).eq(StoreAfterSalesDO::getOrderCode, key));

        AppStoreAfterSalesVo salesVo = StoreAfterSalesConvert.INSTANCE.convert1(storeAfterSales);
        return this.handleSales(salesVo);
    }

    /**
     * 查询详情
     * @param key 订单号
     * @param uid 用户id
     */
    @Override
    public List<AppStoreAfterSalesVo> getStoreInfoByOrderCodeAndUid(String key, Long uid) {
        if (StrUtil.isEmpty(key)) {
            throw exception(PARAM_ERROR);
        }
        List<StoreAfterSalesDO> storeAfterSales = baseMapper.selectList(Wrappers.<StoreAfterSalesDO>lambdaQuery().eq(StoreAfterSalesDO::getUserId, uid).eq(StoreAfterSalesDO::getOrderCode, key));
        if (ObjectUtil.isNull(storeAfterSales)) {
            throw exception(STORE_AFTER_SALES_NOT_EXISTS);
        }
        List<AppStoreAfterSalesVo> list = StoreAfterSalesConvert.INSTANCE.convertList1(storeAfterSales);
        list.forEach(item ->
                this.handleSales(item)
        );

        return list;
    }

    /**
     * 撤销申请
     * @param key 订单号
     * @param uid 用户id
     * @param id Long
     * @return Boolean
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean revoke(String key, Long uid, Long id) {
        StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery().
                eq(StoreAfterSalesDO::getUserId, uid).eq(StoreAfterSalesDO::getId, id)
                .eq(StoreAfterSalesDO::getOrderCode, key));
        if (StrUtil.isEmpty(key)) {
            throw exception(PARAM_ERROR);
        }
        if (storeAfterSales == null) {
            throw exception(STORE_AFTER_SALES_NOT_EXISTS);
        }
        if (storeAfterSales.getState().equals(AfterSalesStatusEnum.STATUS_2.getValue())
                || storeAfterSales.getState().equals(AfterSalesStatusEnum.STATUS_3.getValue())) {
            throw exception(ORDER_NOT_REVOKE);
        }
        storeAfterSales.setSalesState(1);

        StoreOrderDO yxStoreOrder = storeOrderMapper.selectOne(Wrappers.<StoreOrderDO>lambdaQuery().eq(StoreOrderDO::getOrderId, key));
        String o = afterOrderRedisDAO.get(key,uid);
        yxStoreOrder.setStatus(o == null ? 0 : Integer.parseInt(o));
        yxStoreOrder.setRefundStatus(OrderInfoEnum.STATUS_0.getValue());
        storeOrderMapper.updateById(yxStoreOrder);

        List<StoreOrderCartInfoDO> yxStoreOrderCartInfos = storeOrderCartInfoMapper.selectList(Wrappers.<StoreOrderCartInfoDO>lambdaQuery()
                .eq(StoreOrderCartInfoDO::getOid, yxStoreOrder.getId()));
        for (StoreOrderCartInfoDO yxStoreOrderCartInfo : yxStoreOrderCartInfos) {
            yxStoreOrderCartInfo.setIsAfterSales(ShopCommonEnum.IS_STATUS_1.getValue());
            storeOrderCartInfoMapper.updateById(yxStoreOrderCartInfo);
        }

        //操作记录
        storeAfterSalesStatusService.create(storeAfterSales.getUserId(),storeAfterSales.getId()
                ,AfterChangeTypeEnum.STATE_5.getValue(),AfterChangeTypeEnum.STATE_5.getDesc());

        afterOrderRedisDAO.delete(key,uid);
        return baseMapper.updateById(storeAfterSales) > 0;
    }

    /**
     * 添加快递信息
     *
     * @param code       物流公司编码
     * @param name       物流公司名称
     * @param postalCode
     * @param orderCode
     * @param id
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean addLogisticsInformation(String code, String name, String postalCode, String orderCode, Long id) {
        if (StrUtil.isEmpty(code) || StrUtil.isEmpty(name) || StrUtil.isEmpty(postalCode)) {
            throw exception(PARAM_ERROR);
        }
        StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery()
                .eq(StoreAfterSalesDO::getId, id)
                .eq(StoreAfterSalesDO::getOrderCode, orderCode)
        );
        if (!storeAfterSales.getState().equals(AfterSalesStatusEnum.STATUS_1.getValue())) {
            throw exception(ORDER_STATUS_NOT_EXPRESS_);
        }
        storeAfterSales.setShipperCode(code);
        storeAfterSales.setDeliverySn(postalCode);
        storeAfterSales.setDeliveryName(name);
        storeAfterSales.setState(AfterSalesStatusEnum.STATUS_2.getValue());

        //操作记录
        storeAfterSalesStatusService.create(storeAfterSales.getUserId(),storeAfterSales.getId()
                ,AfterChangeTypeEnum.STATE_2.getValue(),AfterChangeTypeEnum.STATE_2.getDesc());

        return baseMapper.updateById(storeAfterSales) > 0;
    }

    /**
     * 删除售后订单
     * @param orderCode /
     * @param id
     * @return /
     */
    @Override
    public Boolean deleteAfterSalesOrder(String orderCode, Long id) {
        if (StrUtil.isEmpty(orderCode) || ObjectUtil.isEmpty(id)) {
            throw exception(PARAM_ERROR);
        }
        StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery().eq(StoreAfterSalesDO::getId, id).eq(StoreAfterSalesDO::getOrderCode, orderCode));
        return baseMapper.deleteById(storeAfterSales.getId()) > 0;
    }

    /**
     * 处理售后订单返回的状态
     *
     * @param storeAfterSalesVo /
     * @return StoreAfterSalesVo /
     */
    private AppStoreAfterSalesVo handleSales(AppStoreAfterSalesVo storeAfterSalesVo) {
        List<StoreAfterSalesItemDO> storeAfterSalesItems = storeAfterSalesItemMapper
                .selectList(Wrappers.<StoreAfterSalesItemDO>lambdaQuery()
                        .eq(StoreAfterSalesItemDO::getStoreAfterSalesId, storeAfterSalesVo.getId()));
        List<AppStoreCartQueryVo> cartInfo = storeAfterSalesItems.stream()
                .map(cart -> JSON.parseObject(cart.getCartInfo(), AppStoreCartQueryVo.class))
                .collect(Collectors.toList());
        storeAfterSalesVo.setCartInfo(cartInfo);
        List<StoreAfterSalesStatusDO> storeAfterSalesStatuses = storeAfterSalesStatusMapper
                .selectList(Wrappers.<StoreAfterSalesStatusDO>lambdaQuery()
                        .eq(StoreAfterSalesStatusDO::getStoreAfterSalesId, storeAfterSalesVo.getId()));

        storeAfterSalesVo.setCompleteTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 3).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
        storeAfterSalesVo.setDeliveryTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 2).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
        storeAfterSalesVo.setAuditFailedTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 4).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
        storeAfterSalesVo.setReviewTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 1).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
        storeAfterSalesVo.setRevocationTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 5).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
        return storeAfterSalesVo;
    }

    /**
     * 检查订单是否符合售后订单
     *
     * @param yxStoreOrder 订单
     */
    private void checkOrder(StoreOrderDO yxStoreOrder) {
        if (yxStoreOrder == null) {
            throw exception(STORE_ORDER_NOT_EXISTS);
        }

        if (!yxStoreOrder.getPaid().equals(OrderInfoEnum.PAY_STATUS_1.getValue())
                || !yxStoreOrder.getRefundStatus().equals(OrderInfoEnum.REFUND_STATUS_0.getValue())
                || yxStoreOrder.getStatus() < OrderInfoEnum.STATUS_0.getValue()) {
            throw exception(ORDER_REFUND_NOT);
        }
    }


}
