package com.ghy.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.core.text.Convert;
import com.ghy.common.enums.OrderStatus;
import com.ghy.common.enums.PayStatus;
import com.ghy.common.enums.RefundType;
import com.ghy.common.enums.WxMsgEnum;
import com.ghy.common.exception.base.BaseException;
import com.ghy.common.utils.AdapayUtils;
import com.ghy.common.utils.ObjectUtils;
import com.ghy.common.utils.WechatMsgUtils;
import com.ghy.customer.domain.CustomerAddress;
import com.ghy.customer.service.CustomerAddressService;
import com.ghy.order.domain.AfterServiceImgs;
import com.ghy.order.domain.AfterServiceRecord;
import com.ghy.order.domain.OrderDetail;
import com.ghy.order.domain.OrderMaster;
import com.ghy.order.mapper.AfterServiceRecordMapper;
import com.ghy.order.service.IAfterServiceImgsService;
import com.ghy.order.service.IAfterServiceRecordService;
import com.ghy.order.service.OrderDetailService;
import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.service.AdapayService;
import com.ghy.payment.service.FinancialDetailService;
import com.ghy.payment.service.FinancialMasterService;
import com.ghy.worker.domain.Worker;
import com.ghy.worker.service.WorkerService;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

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

/**
 * 售后记录Service业务层处理
 *
 * @author clunt
 * @date 2022-09-25
 */
@Slf4j
@Service
public class AfterServiceRecordServiceImpl implements IAfterServiceRecordService {
    @Resource
    private AfterServiceRecordMapper afterServiceRecordMapper;
    @Resource
    private IAfterServiceImgsService afterServiceImgsService;
    @Resource
    private FinancialDetailService financialDetailService;
    @Resource
    private OrderMasterService orderMasterService;
    @Resource
    private FinancialMasterService financialMasterService;
    @Resource
    private AdapayService adapayService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private WorkerService workerService;
    @Autowired
    private CustomerAddressService customerAddressService;

    /**
     * 查询售后记录
     *
     * @param id 售后记录主键
     * @return 售后记录
     */
    @Override
    public AfterServiceRecord selectAfterServiceRecordById(String id) {
        return afterServiceRecordMapper.selectAfterServiceRecordById(id);
    }

    /**
     * 查询售后记录列表
     *
     * @param afterServiceRecord 售后记录
     * @return 售后记录
     */
    @Override
    public List<AfterServiceRecord> selectAfterServiceRecordList(AfterServiceRecord afterServiceRecord) {
        if(afterServiceRecord == null){
            afterServiceRecord = new AfterServiceRecord();
            afterServiceRecord.setNeedImgs(false);
        }
        List<AfterServiceRecord> list = afterServiceRecordMapper.selectAfterServiceRecordList(afterServiceRecord);
        if(afterServiceRecord.getNeedImgs() != null && !afterServiceRecord.getNeedImgs()){
            return list;
        }
        list.forEach(record -> {
            AfterServiceImgs param = new AfterServiceImgs();
            param.setAfterServiceRecordId(Long.valueOf(record.getId()));
            record.setImgsList(afterServiceImgsService.selectAfterServiceImgsList(param));
        });
        return list;
    }

    /**
     * 新增售后记录
     *
     * @param afterServiceRecord 售后记录
     * @return 结果
     */
    @Override
    public int insertAfterServiceRecord(AfterServiceRecord afterServiceRecord) {
        AfterServiceRecord unfinished = unfinished(afterServiceRecord.getOrderDetailId());
        if (unfinished != null) {
            log.warn("订单[{}]存在未完成的售后记录", afterServiceRecord.getOrderDetailId());
            throw new BaseException("存在未完成的售后记录，请勿重复申请！");
        }
        int result = afterServiceRecordMapper.insertAfterServiceRecord(afterServiceRecord);
        // 发一起一次售后发起通知
        // 通知师傅新订单
        try {
            OrderDetail orderDetail =  orderDetailService.selectById(afterServiceRecord.getOrderDetailId());
            OrderMaster orderMaster = orderMasterService.selectById(orderDetail.getOrderMasterId());
            Worker worker = workerService.selectById(orderDetail.getWorkerId());
            // 推送公众号通知数据。
            // 消息组装。
            Map<String, Object> paramsNew = new HashMap<>();
            // 订单编号
            paramsNew.put("thing9", "您收到1条售后/投诉单");
            // 名称
            paramsNew.put("thing11", "请进入【我的订单--售后中】操作处理");
            CustomerAddress address = customerAddressService.selectByCustomerAddressId(orderMaster.getAddressId());
            paramsNew.put("thing10", address.getName());
            // 预约时间
            paramsNew.put("time13", com.ghy.common.utils.DateUtils.parseDateToStr("yyyy年MM月dd日 HH:mm", new Date()));
            WechatMsgUtils.sendWeChatMsg(WechatMsgUtils.getToken(), worker.getWxOpenId(), WxMsgEnum.AFTER_SALES_ORDER, paramsNew);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        if (afterServiceRecord.getImgsList() != null && afterServiceRecord.getImgsList().size() > 0) {
            afterServiceRecord.getImgsList().forEach(imgUrl -> {
                imgUrl.setAfterServiceRecordId(Long.valueOf(afterServiceRecord.getId()));
                afterServiceImgsService.insertAfterServiceImgs(imgUrl);
            });
        }
        return result;
    }

    /**
     * 查询未完成的售后记录 用于判断是否可以申请售后
     *
     * @return 未完成的售后记录
     */
    public AfterServiceRecord unfinished(Long orderDetailId) {
        return afterServiceRecordMapper.unfinished(orderDetailId);
    }

    public AfterServiceRecord getUnfinishedByOrderDetailId(Long orderDetailId) {
        return afterServiceRecordMapper.unfinished(orderDetailId);
    }

    /**
     * 修改售后记录
     *
     * @param param 售后记录
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateAfterServiceRecord(AfterServiceRecord param) throws BaseAdaPayException {
        Long one = 1L;
        Long two = 2L;
        AfterServiceRecord afterServiceRecord = this.selectAfterServiceRecordById(param.getId());
        Assert.notNull(afterServiceRecord, "售后记录不存在！");
        OrderDetail orderDetail = orderDetailService.selectById(afterServiceRecord.getOrderDetailId());
        boolean drawCash = orderDetail.getDrawCashTime() != null;
        // 更新为售后未超时
        orderDetailService.updateAfterTimeout(afterServiceRecord.getOrderDetailId(), 0, 0);
        log.info("客户是否同意{}，客户操作{}",one.equals(param.getCustomerFinalCheck()),param);
        log.info("修改后的售后订单{}",orderDetail);
        if (param.getCustomerFinalCheck()!=null ) {
            // 师傅同意 且 客户同意退款
            //afterServiceRecord.setCustomerFinalCheck(1L);
            if (one.equals(param.getCustomerFinalCheck())) {
                afterServiceRecord.setCustomerFinalCheck(1L);
            }else{
                afterServiceRecord.setCustomerFinalCheck(0L);
            }
            afterServiceRecord.setRefundApplyTime(new Date());
            // 售后客户回复通知
            // 通知师傅新订单
            try {
                Worker worker = workerService.selectById(orderDetail.getWorkerId());
                OrderMaster orderMaster = orderMasterService.selectById(orderDetail.getOrderMasterId());
                // 推送公众号通知数据。
                // 消息组装。
                Map<String, Object> paramsNew = new HashMap<>();
                // 订单编号
                paramsNew.put("thing9", "您有1条售后/投诉单，客户已回复");
                // 名称
                paramsNew.put("thing11", "请进入【我的订单--售后中】查看处理");
                CustomerAddress address = customerAddressService.selectByCustomerAddressId(orderMaster.getAddressId());
                paramsNew.put("thing10", address.getName());
                // 预约时间
                paramsNew.put("time13", com.ghy.common.utils.DateUtils.parseDateToStr("yyyy年MM月dd日 HH:mm", new Date()));
                WechatMsgUtils.sendWeChatMsg(WechatMsgUtils.getToken(), worker.getWxOpenId(), WxMsgEnum.AFTER_SALES_ORDER, paramsNew);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            // DrawCashTime不为空说明已经发起过分账
            if (drawCash) {
                log.warn("子单[{}]已发起分账，不能退款", afterServiceRecord.getOrderDetailId());
                afterServiceRecord.setOriginalRefund(BigDecimal.ZERO);
                afterServiceRecordMapper.updateAfterServiceRecord(afterServiceRecord);
                return AjaxResult.error("本单已划款，师傅/服务人员已到帐或即将到帐，双方达成退款的，请对方线下支付后点“对方已退款”");
            } else {
                agreeRefund(afterServiceRecord);
            }
//            orderDetailService.updateAfterTimeout(afterServiceRecord.getOrderDetailId(), 0, 0);
        } else if (one.equals(afterServiceRecord.getWorkerFeedbackResult()) && param.getCustomerFinalCheck() == null) {
            // 师傅同意 且 客户未处理
            afterServiceRecordMapper.updateAfterServiceRecord(param);
            return drawCash ? AjaxResult.error("本单银联已确认货款结算完毕(订单支付完成)，款项已到达或即将到达您所绑定帐户，需同意退款的同意后您线下与客户另行操作，系统无法提供原路返回退款!") : AjaxResult.success();
        } else {
            if(two.equals(param.getCustomerFinalCheck())){
                // 客户不同意师傅的意见,如果订单是确认中,则需要将订单改为服务中
                if(orderDetail.getOrderStatus() == OrderStatus.FINISH_CHECK.code() && orderDetail.getDrawCashTime()!= null ){
                    orderDetail.setOrderStatus(OrderStatus.SERVER.code());
                    orderDetailService.updateOrderDetail(orderDetail);
                    // 如果发现是唯一子单,则需要将主单也更新为服务中
                    OrderMaster orderMaster = orderMasterService.selectById(orderDetail.getOrderMasterId());
                    if(orderMaster.getOrderStatus() == OrderStatus.FINISH_CHECK.code()){
                        orderMaster.setOrderStatus(OrderStatus.SERVER.code());
                        orderMasterService.updateOrderMaster(orderMaster);
                    }
                }
            }
            afterServiceRecordMapper.updateAfterServiceRecord(param);
        }
        return AjaxResult.success();
    }

    private int agreeRefund(AfterServiceRecord afterServiceRecord) throws BaseAdaPayException {
        OrderDetail orderDetail = orderDetailService.selectById(afterServiceRecord.getOrderDetailId());
        Assert.notNull(orderDetail, "子单不存在！");
        FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(afterServiceRecord.getOrderDetailId());
        Assert.notNull(financialDetail, "财务子单不存在！");
        OrderMaster orderMaster = orderMasterService.selectById(orderDetail.getOrderMasterId());
        Assert.notNull(orderMaster, "找不到对应的订单");
        FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderDetail.getOrderMasterId());
        Assert.notNull(financialMaster, "找不到支付记录");
        // 是否已付款,用于判断是否需要退款
        boolean payReverse = PayStatus.PAID.getCode().equals(financialMaster.getPayStatus());
        // 申请退款金额
        BigDecimal refundMoney;
        if (ObjectUtils.isNotEmpty(afterServiceRecord.getAgreedRefund())) {
            refundMoney = afterServiceRecord.getAgreedRefund();
        } else {
            refundMoney = afterServiceRecord.getRefund();
        }
        log.info("AfterServiceRecord[{}].refundMoney: {},操作数据{}", afterServiceRecord.getId(), refundMoney,afterServiceRecord);
        // 是不是大师傅的子单
        boolean isMaster = orderMaster.getWorkerId().equals(orderDetail.getWorkerId());
        log.info("isMaster: {}", isMaster);
        if (isMaster) {
            // 如果这是大师傅的子单 退款金额最大可以等于主单服务金额
            // 判断退款金额 >= 主单服务金额
            boolean refundAll = refundMoney.compareTo(financialMaster.getServerMoney()) > -1;
            log.info("refundAll: {}", refundAll);
            List<OrderDetail> orderDetails = orderDetailService.selectByOrderMasterId(orderMaster.getId());
            // 判断是否有派单给子师傅
            boolean noneSubWorker = true;
            for (OrderDetail od : orderDetails) {
                if (!orderMaster.getWorkerId().equals(od.getWorkerId())) {
                    noneSubWorker = false;
                    break;
                }
            }
            log.info("noneSubWorker: {}", noneSubWorker);
            if (refundAll && noneSubWorker) {
                // 如果退款金额 >= 主单服务金额 并且 没有派单给子师傅 则退整个主单
                orderMasterService.cancelAgree(orderMaster.getId(), 1);
                afterServiceRecord.setOriginalRefund(financialMaster.getPayMoney());
            } else if (refundAll) {
                // 如果退款金额 >= 主单服务金额 但是有派单给子师傅
                afterServiceRecord.setOriginalRefund(financialMaster.getServerMoney());
                // 退款金额就是主单服务金额
                String reverseAmt = AdapayUtils.bigDecimalToString(financialMaster.getServerMoney());
                log.info("大师傅子单[{}]退款 refundMoney: {}", orderDetail.getId(), reverseAmt);
                // 更新主财务单 PayMoney=PayMoney-ServerMoney ，ServerMoney=0
                financialMaster.setPayMoney(financialMaster.getPayMoney().subtract(financialMaster.getServerMoney()));
                financialMaster.setServerMoney(BigDecimal.ZERO);
                financialMasterService.updateFinancialMaster(financialMaster);

                // 发起支付撤销
                if (payReverse) {
                    payReverse(orderMaster.getDeptId(), financialMaster.getPaymentId(), reverseAmt);
                }
            } else {
                // 如果退款金额 < 主单服务金额
                log.info("大师傅子单[{}]退款 refundMoney: {}", orderDetail.getId(), refundMoney);
                afterServiceRecord.setOriginalRefund(refundMoney);
                financialMaster.setPayMoney(financialMaster.getPayMoney().subtract(refundMoney));
                financialMaster.setServerMoney(financialMaster.getServerMoney().subtract(refundMoney));
                financialMasterService.updateFinancialMaster(financialMaster);
                String reverseAmt = AdapayUtils.bigDecimalToString(refundMoney);
                // 发起支付撤销
                if (payReverse) {
                    payReverse(orderMaster.getDeptId(), financialMaster.getPaymentId(), reverseAmt);
                }
            }
        } else {
            // 是子师傅的子单 退款金额最大可以等于子单的派单金额
            log.info("financialDetail.getPayMoney()[{}].refundMoney: {}", financialDetail.getPayMoney(), refundMoney);
            if (refundMoney.compareTo(financialDetail.getPayMoney()) > -1) {
                // 子单全额退款 直接走取消流程
                orderDetailService.cancelAgree(orderDetail.getId(), 1);
                afterServiceRecord.setOriginalRefund(financialDetail.getPayMoney());
            } else {
                log.info("小师傅子单[{}]退款 refundMoney = {}", orderDetail.getId(), refundMoney);
                afterServiceRecord.setOriginalRefund(refundMoney);
                financialDetail.setPayMoney(financialDetail.getPayMoney().subtract(refundMoney));
                financialMaster.setPayMoney(financialMaster.getPayMoney().subtract(refundMoney));
                // 更新主/子财务单金额
                financialMasterService.updateFinancialMaster(financialMaster);
                financialDetailService.updateFinancialDetail(financialDetail);

                // 发起支付撤销
                if (payReverse) {
                    String reverseAmt = AdapayUtils.bigDecimalToString(refundMoney);
                    payReverse(orderMaster.getDeptId(), financialMaster.getPaymentId(), reverseAmt);
                }

            }
        }
        afterServiceRecord.setRefundApplyTime(new Date());
        return afterServiceRecordMapper.updateAfterServiceRecord(afterServiceRecord);
    }

    private void payReverse(Long deptId, String paymentId, String reverseAmt) throws BaseAdaPayException {
        JSONObject response = adapayService.payReverse(deptId, paymentId, reverseAmt, RefundType.RAS);
        if (!AdapayStatusEnum.pending.code.equals(response.getString("status"))) {
            log.error("发起退款异常，异常信息：{}", response);
            if ("reverse_amt_over".equals(response.getString("error_code"))) {
                throw new BaseException("退款金额超出订单金额");
            } else {
                throw new BaseException("发起退款失败");
            }
        }
    }

    /**
     * 批量删除售后记录
     *
     * @param ids 需要删除的售后记录主键
     * @return 结果
     */
    @Override
    public int deleteAfterServiceRecordByIds(String ids) {
        return afterServiceRecordMapper.deleteAfterServiceRecordByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除售后记录信息
     *
     * @param id 售后记录主键
     * @return 结果
     */
    @Override
    public int deleteAfterServiceRecordById(String id) {
        return afterServiceRecordMapper.deleteAfterServiceRecordById(id);
    }

}
