package com.hfkj.service.order.impl;

import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.common.security.UserCenter;
import com.hfkj.common.utils.RandomUtils;
import com.hfkj.dao.BsOrderAfterSalesApplyMapper;
import com.hfkj.entity.*;
import com.hfkj.model.UserSessionObject;
import com.hfkj.model.order.OrderChildModel;
import com.hfkj.service.SecUserService;
import com.hfkj.service.order.*;
import com.hfkj.sysenum.order.OrderAfterSalesApplyStatusEnum;
import com.hfkj.sysenum.order.OrderAfterSalesApplyTypeEnum;
import com.hfkj.sysenum.order.OrderChildStatusEnum;
import com.hfkj.sysenum.order.OrderRefundStatusEnum;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @className: BsOrderAfterSalesApplyServiceImpl
 * @author: HuRui
 * @date: 2024/5/15
 **/
@Service("orderAfterSalesApplyService")
public class BsOrderAfterSalesApplyServiceImpl implements BsOrderAfterSalesApplyService {
    @Resource
    private BsOrderAfterSalesApplyMapper orderAfterSalesApplyMapper;
    @Resource
    private BsOrderAfterSalesOpRecordService orderAfterSalesOpRecordService;
    @Resource
    private BsOrderChildService orderChildService;
    @Resource
    private BsOrderService orderService;
    @Resource
    private BsOrderRefundService orderRefundService;
    @Resource
    private SecUserService secUserService;
    @Override
    public void editData(BsOrderAfterSalesApply data) {
        data.setUpdateTime(new Date());
        if (data.getId() == null) {
            data.setCreateTime(new Date());
            orderAfterSalesApplyMapper.insert(data);
        } else {
            orderAfterSalesApplyMapper.updateByPrimaryKey(data);
        }
    }

    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW,rollbackFor= {RuntimeException.class})
    public void createApply(OrderAfterSalesApplyTypeEnum applyType, String childOrderNo, Integer productCount, String photo, String remarks) {
        // 查询子订单
        OrderChildModel orderChild = orderChildService.getDetail(childOrderNo);
        if (orderChild == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "");
        }
        if (!orderChild.getStatus().equals(OrderChildStatusEnum.status2.getCode())
                && !orderChild.getStatus().equals(OrderChildStatusEnum.status3.getCode()) ) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "订单状态错误,无法提交");
        }
        // 查询订单
        BsOrder order = orderService.getOrder(orderChild.getOrderNo());
        if (order == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的订单");
        }
        // 查询子订单申请记录
        BsOrderAfterSalesApply record = getDetailByChildOrderNo(childOrderNo);
        if (record != null
                && (!record.getStatus().equals(OrderAfterSalesApplyStatusEnum.type5.getCode()) && !record.getStatus().equals(OrderAfterSalesApplyStatusEnum.type2.getCode()))) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "此订单已提交售后，请勿重复提交");
        }

        BsOrderAfterSalesApply apply = new BsOrderAfterSalesApply();
        apply.setType(applyType.getCode());
        apply.setUserId(order.getUserId());
        apply.setUserPhone(order.getUserPhone());
        apply.setMerId(orderChild.getMerId());
        // 子订单编号 + 5位随机数
        apply.setApplyNo(orderChild.getChildOrderNo() + RandomUtils.number(5,false));
        apply.setOrderNo(orderChild.getOrderNo());
        apply.setChildOrderNo(orderChild.getChildOrderNo());
        apply.setProductType(orderChild.getProductType());
        apply.setProductId(orderChild.getProductId());
        apply.setProductName(orderChild.getProductName());
        apply.setProductImg(orderChild.getProductImg());
        apply.setProductSpecId(orderChild.getProductSpecId());
        apply.setProductSpecName(orderChild.getProductSpecName());
        apply.setProductCount(productCount);
        apply.setPhoto(photo);
        apply.setRemarks(remarks);
        apply.setStatus(OrderAfterSalesApplyStatusEnum.type1.getCode());

        if (orderChild.getSurplusRefundCount().equals(productCount)) {
            // 全部退款
            apply.setRefundPrice(orderChild.getSurplusRefundPrice());
            apply.setRefundIntegral(orderChild.getSurplusRefundIntegral());
        } else {
            // 部分退款
            // 计算单价
            BigDecimal unitPrice = orderChild.getSurplusRefundPrice().divide(new BigDecimal(orderChild.getProductCount().toString()), 2, BigDecimal.ROUND_DOWN).setScale(2);
            BigDecimal unitPriceIntegral = new BigDecimal(orderChild.getSurplusRefundIntegral().toString()).divide(new BigDecimal("100"))
                    .divide(new BigDecimal(orderChild.getProductCount().toString()), 2, BigDecimal.ROUND_DOWN).setScale(2);
            apply.setRefundPrice(unitPrice.multiply(new BigDecimal(productCount.toString())));
            apply.setRefundIntegral(unitPriceIntegral.multiply(new BigDecimal("100")).longValue());
        }
        editData(apply);

        // 操作记录
        BsOrderAfterSalesOpRecord opRecord = new BsOrderAfterSalesOpRecord();
        opRecord.setApplyNo(apply.getApplyNo());
        opRecord.setStatus(OrderAfterSalesApplyStatusEnum.type1.getCode());
        opRecord.setPhoto(photo);
        opRecord.setRemarks(remarks);
        opRecord.setOpUserType(2);
        opRecord.setOpUserId(apply.getUserId());
        opRecord.setOpUserName(apply.getUserPhone());
        orderAfterSalesOpRecordService.create(opRecord);
    }

    @Override
    public void audit(String applyNo, Boolean applyStatus, String remarks, Long opUserId) {
        // 查询申请
        BsOrderAfterSalesApply apply = getDetailByApplyNo(applyNo);
        if (apply == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的申请");
        }
        if (OrderAfterSalesApplyStatusEnum.type1.getCode() != apply.getStatus()) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "审核失败！当前申请不处于审核状态");
        }
        SecUser secUser = secUserService.getDetail(opUserId);
        if (secUser == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的操作人");
        }

        apply.setAuditTime(new Date());
        apply.setAuditRemarks(remarks);

        if (applyStatus.equals(true)) {
            if (OrderAfterSalesApplyTypeEnum.type1.getCode() == apply.getType()) {
                // 退款
                BsOrderRefund orderRefund = orderRefundService.tradeOrderChildRefund(apply.getChildOrderNo(), apply.getProductCount(), null);
                if (orderRefund.getRefundStatus().equals(OrderRefundStatusEnum.status2.getCode())) {
                    apply.setRefundOrderNo(orderRefund.getRefundOrderNo());
                    apply.setRefundPrice(orderRefund.getRefundPrice());
                    apply.setRefundIntegral(orderRefund.getRefundIntegral());
                    apply.setStatus(OrderAfterSalesApplyStatusEnum.type5.getCode());
                    apply.setFinishTime(new Date());
                } else {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败！" + orderRefund.getRefundFailReason());
                }
            } else if (OrderAfterSalesApplyTypeEnum.type2.getCode() == apply.getType()) {
                apply.setStatus(OrderAfterSalesApplyStatusEnum.type3.getCode());

            } else {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知申请类型");
            }

        } else {
            apply.setStatus(OrderAfterSalesApplyStatusEnum.type2.getCode());
        }

        // 操作记录
        BsOrderAfterSalesOpRecord opRecord = new BsOrderAfterSalesOpRecord();
        opRecord.setApplyNo(apply.getApplyNo());
        opRecord.setStatus(apply.getStatus());
        opRecord.setRemarks(remarks);
        opRecord.setOpUserType(1);
        opRecord.setOpUserId(secUser.getId());
        opRecord.setOpUserName(secUser.getUserName());
        orderAfterSalesOpRecordService.create(opRecord);

        editData(apply);
    }

    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW,rollbackFor= {RuntimeException.class})
    public void sendExpress(String applyNo, String sendExpressNo) {
        // 查询申请
        BsOrderAfterSalesApply apply = getDetailByApplyNo(applyNo);
        if (apply == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的申请");
        }
        if (OrderAfterSalesApplyStatusEnum.type3.getCode() != apply.getStatus()) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "审核失败！当前申请不处于待邮寄中");
        }
        apply.setStatus(OrderAfterSalesApplyStatusEnum.type4.getCode());
        apply.setSendExpressNo(sendExpressNo);
        apply.setSendExpressTime(new Date());
        editData(apply);

        // 操作记录
        BsOrderAfterSalesOpRecord opRecord = new BsOrderAfterSalesOpRecord();
        opRecord.setApplyNo(apply.getApplyNo());
        opRecord.setStatus(apply.getStatus());
        opRecord.setRemarks(sendExpressNo);
        opRecord.setOpUserType(1);
        opRecord.setOpUserId(apply.getId());
        opRecord.setOpUserName(apply.getUserPhone());
        orderAfterSalesOpRecordService.create(opRecord);
    }

    @Override
    public void finish(String applyNo, Long opUserId) {
        // 查询申请
        BsOrderAfterSalesApply apply = getDetailByApplyNo(applyNo);
        if (apply == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的申请");
        }
        // 退款
        BsOrderRefund orderRefund = orderRefundService.tradeOrderChildRefund(apply.getChildOrderNo(), apply.getProductCount(), null);
        if (orderRefund.getRefundStatus().equals(OrderRefundStatusEnum.status2.getCode())) {
            // 查询操作用户
            SecUser secUser = secUserService.getDetail(opUserId);
            if (secUser == null) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的操作人");
            }
            apply.setStatus(OrderAfterSalesApplyStatusEnum.type5.getCode());
            apply.setFinishTime(new Date());
            editData(apply);

            // 操作记录
            BsOrderAfterSalesOpRecord opRecord = new BsOrderAfterSalesOpRecord();
            opRecord.setApplyNo(apply.getApplyNo());
            opRecord.setStatus(apply.getStatus());
            opRecord.setOpUserType(1);
            opRecord.setOpUserId(secUser.getId());
            opRecord.setOpUserName(secUser.getUserName());
            orderAfterSalesOpRecordService.create(opRecord);
        } else {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败！" + orderRefund.getRefundFailReason());
        }
    }

    @Override
    public BsOrderAfterSalesApply getDetailByApplyNo(String applyNo) {
        BsOrderAfterSalesApplyExample example = new BsOrderAfterSalesApplyExample();
        example.createCriteria().andApplyNoEqualTo(applyNo);
        List<BsOrderAfterSalesApply> list = orderAfterSalesApplyMapper.selectByExample(example);
        if (!list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public BsOrderAfterSalesApply getDetailByChildOrderNo(String childOrderNo) {
        BsOrderAfterSalesApplyExample example = new BsOrderAfterSalesApplyExample();
        example.createCriteria().andChildOrderNoEqualTo(childOrderNo);
        List<BsOrderAfterSalesApply> list = orderAfterSalesApplyMapper.selectByExample(example);
        if (!list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<BsOrderAfterSalesApply> getApplyList(Map<String, Object> param) {
        BsOrderAfterSalesApplyExample example = new BsOrderAfterSalesApplyExample();
        BsOrderAfterSalesApplyExample.Criteria criteria = example.createCriteria();

        if (MapUtils.getLong(param, "merId") != null) {
            criteria.andMerIdEqualTo(MapUtils.getLong(param, "merId"));
        }

        if (MapUtils.getLong(param, "userId") != null) {
            criteria.andUserIdEqualTo(MapUtils.getLong(param, "userId"));
        }

        if (MapUtils.getInteger(param, "type") != null) {
            criteria.andTypeEqualTo(MapUtils.getInteger(param, "type"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "userPhone"))) {
            criteria.andUserPhoneLike("%"+MapUtils.getString(param, "userPhone")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "orderNo"))) {
            criteria.andOrderNoLike("%"+MapUtils.getString(param, "orderNo")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "childOrderNo"))) {
            criteria.andChildOrderNoLike("%"+MapUtils.getString(param, "childOrderNo")+"%");
        }

        if (MapUtils.getInteger(param, "productType") != null) {
            criteria.andProductTypeEqualTo(MapUtils.getInteger(param, "productType"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "productName"))) {
            criteria.andProductNameLike("%"+MapUtils.getString(param, "productName")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "applyNo"))) {
            criteria.andApplyNoLike("%"+MapUtils.getString(param, "applyNo")+"%");
        }

        if (MapUtils.getInteger(param, "status") != null) {
            criteria.andStatusEqualTo(MapUtils.getInteger(param, "status"));
        }

        if (MapUtils.getLong(param, "createTimeS") != null) {
            criteria.andCreateTimeGreaterThanOrEqualTo(new Date(MapUtils.getLong(param, "createTimeS")));
        }

        if (MapUtils.getLong(param, "createTimeE") != null) {
            criteria.andCreateTimeLessThanOrEqualTo(new Date(MapUtils.getLong(param, "createTimeE")));
        }

        example.setOrderByClause("create_time desc");
        return orderAfterSalesApplyMapper.selectByExample(example);
    }
}
