package com.ym.mec.biz.service.impl;

import com.ym.mec.biz.dal.dao.GoodsDao;
import com.ym.mec.biz.dal.dao.StudentInstrumentDao;
import com.ym.mec.biz.dal.dao.StudentPaymentOrderDetailDao;
import com.ym.mec.biz.dal.dao.SysConfigDao;
import com.ym.mec.biz.dal.dto.MaintenancePayDto;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.date.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

@Service
public class StudentInstrumentServiceImpl extends BaseServiceImpl<Long, StudentInstrument> implements StudentInstrumentService {

    @Autowired
    private StudentInstrumentDao studentInstrumentDao;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private SysUserCashAccountService sysUserCashAccountService;
    @Autowired
    private PayService payService;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private StudentPaymentRouteOrderService studentPaymentRouteOrderService;
    @Autowired
    private StudentPaymentOrderService studentPaymentOrderService;
    @Autowired
    private ContractService contractService;
    @Autowired
    private SysUserCashAccountDetailService sysUserCashAccountDetailService;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private GoodsCategoryService goodsCategoryService;
    @Autowired
    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;
    @Autowired
    private GoodsDao goodsDao;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public BaseDAO<Long, StudentInstrument> getDAO() {
        return studentInstrumentDao;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map pay(MaintenancePayDto maintenancePayDto) throws Exception {
        StudentInstrument studentInstrument = studentInstrumentDao.get(maintenancePayDto.getId());
        if (studentInstrument == null) {
            throw new BizException("所选乐器不存在，请核查");
        }
        Integer userId = studentInstrument.getStudentId();
        BigDecimal orderAmount = new BigDecimal(sysConfigDao.findConfigValue("maintenance_price"));
        BigDecimal amount = maintenancePayDto.getAmount(); //扣除余额之前的金额
        if (amount.compareTo(orderAmount) != 0) {
            throw new BizException("商品价格不符");
        }

        String channelType = "";
        Date nowDate = new Date();

        BigDecimal balance = BigDecimal.ZERO;
        if (maintenancePayDto.getUseBalance() && amount.compareTo(BigDecimal.ZERO) > 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(userId);
            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                sysUserCashAccountService.updateBalance(userId, balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐保购买");
            }
        }

        String orderNo = idGeneratorService.generatorId("payment") + "";
        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();

        studentPaymentOrder.setPaymentChannel("BALANCE");
        studentPaymentOrder.setUserId(userId);
        studentPaymentOrder.setGroupType(GroupType.MAINTENANCE);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(OrderTypeEnum.MAINTENANCE);
        studentPaymentOrder.setExpectAmount(orderAmount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setBalancePaymentAmount(balance);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setMusicGroupId(studentInstrument.getId().toString());
        studentPaymentOrder.setRemitFee(BigDecimal.ZERO);
        studentPaymentOrder.setCourseRemitFee(BigDecimal.ZERO);
        studentPaymentOrder.setOrganId(studentInstrument.getOrganId());
        studentPaymentOrder.setRoutingOrganId(studentInstrument.getOrganId());
        studentPaymentOrder.setCreateTime(nowDate);
        studentPaymentOrder.setUpdateTime(nowDate);
        studentPaymentOrderService.insert(studentPaymentOrder);

        int isRenew = 0;
        if (studentInstrument.getEndTime() != null) {
            isRenew = 1;
        }

        StudentPaymentOrderDetail maintenanceOrderDetail = new StudentPaymentOrderDetail();
        maintenanceOrderDetail.setType(OrderDetailTypeEnum.MAINTENANCE);
        maintenanceOrderDetail.setPrice(orderAmount);
        maintenanceOrderDetail.setRemitFee(BigDecimal.ZERO);
        maintenanceOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
        maintenanceOrderDetail.setStudentInstrumentId(maintenancePayDto.getId());
        maintenanceOrderDetail.setIsRenew(isRenew);
        maintenanceOrderDetail.setCreateTime(nowDate);
        maintenanceOrderDetail.setUpdateTime(nowDate);
        studentPaymentOrderDetailDao.insert(maintenanceOrderDetail);

        studentPaymentOrder.setVersion(0);
        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            studentPaymentRouteOrderService.addRouteOrder(orderNo, studentInstrument.getOrganId(), balance);
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", channelType);
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            return notifyMap;
        }

        String orderSubject = "乐保服务";
        String receiver = "maintenance";

        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");

        Map payMap = payService.getPayMap(
                amount,
                balance,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/notify",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + orderNo,
                orderSubject,
                orderSubject,
                studentInstrument.getOrganId(),
                receiver
        );

        studentPaymentOrder.setOrganId(studentInstrument.getOrganId());
        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(nowDate);
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderCallback(StudentPaymentOrder studentPaymentOrder) {
        Date nowDate = new Date();
        //更新订单信息
        studentPaymentOrder.setUpdateTime(nowDate);
        int updateCount = studentPaymentOrderService.update(studentPaymentOrder);
        if (updateCount <= 0) {
            throw new BizException("订单更新失败");
        }
        //更新维修单信息
        StudentInstrument studentInstrument = get(Long.parseLong(studentPaymentOrder.getMusicGroupId()));
        if (studentInstrument == null) {
            throw new BizException("乐保信息不存在");
        }

        Integer userId = studentPaymentOrder.getUserId();

        Map<Integer, String> map = new HashMap<>();
        map.put(userId, userId.toString());

        //支付成功
        if (studentPaymentOrder.getStatus() == DealStatusEnum.SUCCESS) {
            try {
                contractService.transferProduceContract(userId, null);
            } catch (Exception e) {
                logger.error("产品协议生成失败", e);
            }
            Date startTime = nowDate;
            Date endTime = DateUtil.addYears(nowDate, 1);
            if (studentInstrument.getEndTime() != null &&
                    studentInstrument.getEndTime().compareTo(nowDate) > 0) {
                startTime = studentInstrument.getStartTime();
                endTime = DateUtil.addYears(studentInstrument.getEndTime(), 1);
            }
            studentInstrument.setStartTime(startTime);
            studentInstrument.setEndTime(endTime);
            studentInstrument.setStatus(1);
            if (this.update(studentInstrument) <= 0) {
                throw new BizException("乐保信息更新失败");
            }

            //插入交易明细
            BigDecimal amount = studentPaymentOrder.getActualAmount();
            if (amount.compareTo(BigDecimal.ZERO) > 0) {
                SysUserCashAccount cashAccount = sysUserCashAccountService.get(userId);
                //充值
                SysUserCashAccountDetail rechargeDetail = new SysUserCashAccountDetail();
                rechargeDetail.setAmount(amount);
                rechargeDetail.setBalance(cashAccount.getBalance().add(amount));
                rechargeDetail.setComment("缴费前充值");
                rechargeDetail.setCreateTime(nowDate);
                rechargeDetail.setStatus(DealStatusEnum.SUCCESS);
                rechargeDetail.setTransNo(studentPaymentOrder.getTransNo());
                rechargeDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
                rechargeDetail.setUpdateTime(nowDate);
                rechargeDetail.setUserId(userId);
                rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
                rechargeDetail.setComAmount(studentPaymentOrder.getComAmount());
                rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount());
                sysUserCashAccountDetailService.insert(rechargeDetail);

                //缴费
                SysUserCashAccountDetail paymentDetail = new SysUserCashAccountDetail();
                paymentDetail.setAmount(amount.negate());
                paymentDetail.setBalance(cashAccount.getBalance());
                paymentDetail.setComment("乐保购买");
                paymentDetail.setCreateTime(nowDate);
                paymentDetail.setStatus(DealStatusEnum.SUCCESS);
                paymentDetail.setTransNo(studentPaymentOrder.getTransNo());
                paymentDetail.setType(PlatformCashAccountDetailTypeEnum.PAY_FEE);
                paymentDetail.setUpdateTime(nowDate);
                paymentDetail.setUserId(userId);
                rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
                sysUserCashAccountDetailService.insert(paymentDetail);
            }

            return true;
        }

        if (studentPaymentOrder.getStatus() == DealStatusEnum.CLOSE || studentPaymentOrder.getStatus() == DealStatusEnum.FAILED) {

            if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
                sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "乐保购买支付失败");
            }

            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_SMS_PUSH_SPORADIC_PAYMENT_FAILED, map, null, 0, null, "STUDENT",
                    studentPaymentOrder.getActualAmount(), "乐保购买");
            return false;
        }
        return false;
    }

    @Override
    public StudentInstrument addStudentInstrument(StudentInstrument studentInstrument) {
        Goods goods = goodsService.get(studentInstrument.getGoodsId());
        GoodsCategory goodsCategory = goodsCategoryService.get(goods.getGoodsCategoryId());
        studentInstrument.setGoodsCategoryId(goods.getGoodsCategoryId());
        studentInstrument.setGoodsCategoryName(goodsCategory.getName());
        studentInstrument.setGoodsName(goods.getName());
        studentInstrument.setGoodsBrand(goods.getBrand());
        studentInstrument.setSpecification(goods.getSpecification());
        studentInstrument.setGoodsImg(goods.getImage());
        studentInstrumentDao.insert(studentInstrument);
        return studentInstrument;
    }

    @Override
    public Boolean addOrderDetail2Instrument(StudentPaymentOrder order) {
        List<OrderDetailTypeEnum> orderDetailTypes = new ArrayList<>();
        orderDetailTypes.add(OrderDetailTypeEnum.MAINTENANCE);
        orderDetailTypes.add(OrderDetailTypeEnum.MUSICAL);
        List<StudentPaymentOrderDetail> orderDetails = studentPaymentOrderDetailDao.getOrderDetailByType(order.getId(), orderDetailTypes);
        List<StudentPaymentOrderDetail> orderDetails4Instruments = orderDetails.stream()
                .filter(e -> e.getType().equals(OrderDetailTypeEnum.MUSICAL))
                .collect(Collectors.toList());
        if (orderDetails4Instruments.size() <= 0) {
            return false;
        }
        List<StudentPaymentOrderDetail> orderDetails4Maintenance = orderDetails.stream()
                .filter(e -> e.getType().equals(OrderDetailTypeEnum.MAINTENANCE)).collect(Collectors.toList());

        StudentPaymentOrderDetail maintenanceDetail = null;
        int maintenanceStatus = 0;
        Date startTime = null;
        Date endTime = null;
        if (orderDetails4Maintenance.size() > 0) {
            maintenanceDetail = orderDetails4Maintenance.get(0);
            maintenanceStatus = 1;
            startTime = new Date();
            endTime = DateUtil.addYears(startTime, 1);
        }

        Integer goodsId = Integer.valueOf(orderDetails4Instruments.get(0).getGoodsIdList());
        StudentInstrument studentInstrument = new StudentInstrument();
        studentInstrument.setStudentId(order.getUserId());
        studentInstrument.setOrganId(order.getOrganId());
        studentInstrument.setGoodsId(goodsId);
        studentInstrument.setStatus(maintenanceStatus);
        studentInstrument.setOrderId(order.getId());
        studentInstrument.setChangeOrderId(order.getId());
        studentInstrument.setStartTime(startTime);
        studentInstrument.setEndTime(endTime);
        addStudentInstrument(studentInstrument);
        if (maintenanceDetail != null) {
            maintenanceDetail.setStudentInstrumentId(studentInstrument.getId());
            studentPaymentOrderDetailDao.update(maintenanceDetail);
        }
        return true;
    }

    @Override
    public Boolean pushNotice() {
        Date endTime = DateUtil.addDays(DateUtil.getLastTimeWithDay(new Date()), +7);
        Date startTime = DateUtil.trunc(endTime);
        List<StudentInstrument> studentInstruments = studentInstrumentDao.getListByEndTime(startTime, endTime);
        if (studentInstruments.size() <= 0) {
            return false;
        }
        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");
        String pushUrl = baseApiUrl + "#/leBao";
        for (StudentInstrument studentInstrument : studentInstruments) {
            Map<Integer, String> userMap = new HashMap<>();
            userMap.put(studentInstrument.getStudentId(), studentInstrument.getStudentId().toString());
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_MAINTENANCE_NOTICE,
                    userMap, null, 0, "5?" + pushUrl, "STUDENT", studentInstrument.getGoodsName());
        }
        return true;
    }

    @Override
    public StudentInstrument updateStudentInstrument(StudentInstrument studentInstrument) {
        Goods goods = goodsService.get(studentInstrument.getGoodsId());
        GoodsCategory goodsCategory = goodsCategoryService.get(goods.getGoodsCategoryId());
        studentInstrument.setGoodsCategoryId(goods.getGoodsCategoryId());
        studentInstrument.setGoodsCategoryName(goodsCategory.getName());
        studentInstrument.setGoodsName(goods.getName());
        studentInstrument.setGoodsBrand(goods.getBrand());
        studentInstrument.setSpecification(goods.getSpecification());
        studentInstrument.setGoodsImg(goods.getImage());
        studentInstrumentDao.update(studentInstrument);
        return studentInstrument;
    }

    @Override
    public Boolean subjectChangeUpdateInstrument(SubjectChange subjectChange) {
        if (subjectChange == null || subjectChange.getChangeMusical() == null ||
                KitGroupPurchaseTypeEnum.OWNED.equals(subjectChange.getKitGroupPurchaseType())) {
            return false;
        }
        StudentInstrument studentInstrument = studentInstrumentDao.getByOrderId(subjectChange.getOriginalOrderId().longValue());

        if (studentInstrument == null) {
            studentInstrument = new StudentInstrument();
            studentInstrument.setStudentId(subjectChange.getStudentId());
            studentInstrument.setOrganId(subjectChange.getOrganId());
            studentInstrument.setOrderId(subjectChange.getOriginalOrderId().longValue());
            studentInstrument.setStatus(0);
        }
        studentInstrument.setChangeOrderId(subjectChange.getOrderId().longValue());
        studentInstrument.setGoodsId(subjectChange.getChangeMusical());
        if (studentInstrument.getId() == null) {
            addStudentInstrument(studentInstrument);
            return true;
        }
        updateStudentInstrument(studentInstrument);
        return true;
    }

    @Override
    public StudentInstrument getStudentInstrument(Integer studentId, Integer goodsId) {
        return studentInstrumentDao.getStudentInstrument(studentId, goodsId);
    }

    @Override
    public Boolean addOldStudentInstrument() {
        Date startTime = null;
        Date nowDate = new Date();
        StudentInstrument studentInstrument = studentInstrumentDao.getStudentInstrument(2094765, 60);
        if (studentInstrument != null) {
            startTime = DateUtil.addMinutes(nowDate, -15);
        }
        List<Goods> goodies = goodsDao.getGoodsByBaseGoodsId(76);
        List<Integer> goodsIds = goodies.stream().map(Goods::getId).collect(Collectors.toList());
        List<StudentInstrument> oldStudentInstruments = studentInstrumentDao.getOldStudentInstrument(startTime, goodsIds);
        for (StudentInstrument oldStudentInstrument : oldStudentInstruments) {
            oldStudentInstrument.setChangeOrderId(oldStudentInstrument.getOrderId());
            if (oldStudentInstrument.getEndTime().compareTo(nowDate) > 0) {
                oldStudentInstrument.setStatus(1);
            } else {
                oldStudentInstrument.setStatus(0);
            }
            StudentInstrument has = studentInstrumentDao.getStudentInstrument(oldStudentInstrument.getStudentId(), oldStudentInstrument.getGoodsId());
            if (has == null) {
                studentInstrumentDao.insert(oldStudentInstrument);
                continue;
            }
            oldStudentInstrument.setId(has.getId());
            if (has.getEndTime() == null) {
                studentInstrumentDao.update(oldStudentInstrument);
                continue;
            }
            if (has.getEndTime().compareTo(oldStudentInstrument.getEndTime()) >= 0) {
                continue;
            }
            studentInstrumentDao.update(oldStudentInstrument);
        }
        return true;
    }
}
