package cn.com.ty.lift.business.contract.service;

import cn.com.ty.lift.business.contract.dao.entity.Contracts;
import cn.com.ty.lift.business.contract.dao.entity.Payment;
import cn.com.ty.lift.business.contract.dao.entity.PaymentHistory;
import cn.com.ty.lift.business.contract.dao.entity.model.request.PaymentRequest;
import cn.com.ty.lift.business.contract.dao.entity.model.response.PaymentDetailResponse;
import cn.com.ty.lift.business.contract.dao.entity.model.response.PaymentListResponse;
import cn.com.ty.lift.business.contract.dao.entity.model.response.PaymentResponse;
import cn.com.ty.lift.business.contract.dao.mapper.PaymentMapper;
import cn.com.ty.lift.business.framework.util.MessageUtils;
import cn.com.ty.lift.common.utils.DateUtils;
import cn.com.xwy.boot.web.dto.RestResponse;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

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

import static java.math.BigDecimal.ZERO;

/**
 * @author bieao
 * @date 2019/12/11
 * @description 收款业务层
 */
@Service
public class PaymentService extends ServiceImpl<PaymentMapper, Payment> {

    @Resource
    private PaymentHistoryService paymentHistoryService;

    @Resource
    private ContractService contractService;

    /**
     * @param request 付款列表查询条件
     * @return RestResponse 付款分页列表结果
     * @description 查询付款列表
     * @date 2020/2/20 3:10 下午
     */
    public IPage<PaymentListResponse> maintenanceList(PaymentRequest request) {
        request.addDesc("c.end_date");
        return baseMapper.findProjectByCondition(request.getPage(), request);
    }

    /**
     * @param request 付款列表查询条件
     * @return RestResponse 付款分页列表结果
     * @description 查询大修付款列表
     * @date 2020/4/27 11:15 上午
     */
    public IPage<PaymentListResponse> capitalList(PaymentRequest request) {
        request.addDesc("c.end_date");
        return baseMapper.findCapitalByCondition(request.getPage(), request);
    }

    /**
     * @param request 付款详情查询条件
     * @return RestResponse 付款详情
     * @description 查询维保付款详情
     * @date 2020/4/28 2:16 下午
     */
    public PaymentResponse maintenanceDetail(PaymentRequest request) {
        PaymentResponse response = new PaymentResponse();
        PaymentDetailResponse detail = baseMapper.queryProjectDetailById(request);
        List<Payment> paymentList = paymentList(request.getId());
        response.setDetail(detail);
        response.setPaymentList(paymentList);
        return response;
    }

    /**
     * @param request 付款详情查询条件
     * @return RestResponse 付款详情
     * @description 查询大修付款详情
     * @date 2020/2/24 10:47 上午
     */
    public PaymentResponse capitalDetail(PaymentRequest request) {
        PaymentResponse response = new PaymentResponse();
        PaymentDetailResponse detail = baseMapper.queryCapitalDetailById(request);
        List<Payment> paymentList = paymentList(request.getId());
        response.setPaymentList(paymentList);
        response.setDetail(detail);
        return response;
    }

    /**
     * @param payments  付款信息
     * @param contracts 合同信息
     * @return 是否成功
     * @description 批量插入收款信息
     * @date 2019/12/11 4:34 PM
     */
    public boolean insertBatch(List<Payment> payments, Contracts contracts) {
        //设置合同付款的合同id
        payments.forEach(entry -> {
            entry.setContractsId(contracts.getId());
            entry.setCode("PA" + DateUtils.generateCode());
            entry.setType(contracts.getType());
        });
        //批量插入付款信息
        return saveBatch(payments);
    }

    private String formatPaymentContent(Payment payment){
        return String.format("应收：%.2f, 实收：%.2f, 开票：%.2f", payment.getPlanMoney(), payment.getWorkMoney(), payment.getAmountInvoice());
    }

    /**
     * @param oldPaymentList 原有付款列表
     * @param paymentList    修改的付款列表
     * @return 操作是否成功
     * @description 新增、删除、修改付款列表
     * @date 2020/4/29 2:11 下午
     */
    public RestResponse modifyPayment(Collection<Payment> oldPaymentList, List<Payment> paymentList) {
        List<Payment> updateList = new ArrayList<>();
        List<Payment> deleteList = new ArrayList<>();
        List<PaymentHistory> histories = new ArrayList<>();
        //新增付款项
        List<Payment> insertList = paymentList.stream().filter(entry -> Objects.isNull(entry.getId())).collect(Collectors.toList());
        if (IterUtil.isNotEmpty(insertList)) {
            for (Payment payment : insertList) {
                PaymentHistory history = new PaymentHistory();
                history.setPaymentId(payment.getId());
                history.setContractsId(payment.getContractsId());
                history.setDescription("新增收款项");
                history.setBeforeContent("--");
                String afterContent = formatPaymentContent(payment);
                history.setAfterContent(afterContent);
                history.setOperatorId(10000L);
                history.setOperateDate(LocalDateTime.now());
                histories.add(history);
            }
        }
        if (CollUtil.isEmpty(oldPaymentList)) {
            updateList.addAll(paymentList);
        } else {
            //比较原有收款项
            for (Payment payment : oldPaymentList) {
                PaymentHistory history = new PaymentHistory();
                history.setPaymentId(payment.getId());
                history.setContractsId(payment.getContractsId());
                String before = formatPaymentContent(payment);
                history.setBeforeContent(before);
                history.setOperatorId(10000L);
                history.setOperateDate(LocalDateTime.now());
                Optional<Payment> newPayment = paymentList.stream().filter(entry -> payment.getId().equals(entry.getId())).findFirst();
                if (newPayment.isPresent()) {
                    history.setDescription("修改收费项");
                    Payment p = newPayment.get();
                    String after = formatPaymentContent(p);
                    if (!Objects.equals(before, after)) {
                        history.setAfterContent(after);
                        histories.add(history);
                        updateList.add(p);
                    }
                } else {
                    history.setDescription("删除付款项");
                    history.setAfterContent("--");
                    histories.add(history);
                    deleteList.add(payment);
                }
            }
        }
        if (CollUtil.isNotEmpty(deleteList)) {
            boolean deleteResult = removeByIds(deleteList.stream().map(Payment::getId).collect(Collectors.toList()));
            if (!deleteResult) return RestResponse.fail(MessageUtils.get("msg.delete.batch.fail"));
        }
        if (CollUtil.isNotEmpty(updateList)) {
            boolean updateResult = updateBatchById(updateList, updateList.size());
            if (!updateResult) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RestResponse.fail(MessageUtils.get("msg.modify.batch.fail"));
            }
        }
        if (CollUtil.isNotEmpty(insertList)) {
            boolean save = saveBatch(insertList, insertList.size());
            if (!save) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RestResponse.fail(MessageUtils.get("msg.add.batch.fail"));
            }
        }
        boolean history = paymentHistoryService.saveBatch(histories, histories.size());
        if (!history) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail("插入付款操作记录失败");
        }
        return RestResponse.success(null, MessageUtils.get("msg.modify.success"));
    }

    /**
     * @param request 收款信息列表
     * @return 1.成功, 0.失败, 消息描述
     * @description 批量修改收款信息
     * @date 2019/12/11 3:50 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse modifyBatchById(PaymentRequest request) {
        List<Payment> paymentList = request.getPaymentList();
        List<Long> paymentIdList = paymentList.stream().map(Payment::getId).collect(Collectors.toList());
        //查询原有付款列表
        Collection<Payment> oldPaymentList = paymentList(paymentIdList);
        //设置合同付款的合同id
        paymentList.forEach(entry -> {
            entry.setContractsId(request.getContractId());
            entry.setCode("PA" + DateUtils.generateCode());
            entry.setType(request.getContractType());
        });
        Long contractId = request.getContractId();
        Contracts contracts = contractService.getOne(contractId);
        if (Objects.nonNull(contracts)) {
            //应收金额总计
            BigDecimal planMoneyTotal = paymentList.stream().map(Payment::getPlanMoney).reduce(ZERO, BigDecimal::add);
            contracts.setPlanMoneyTotal(planMoneyTotal);
            //实收金额总计
            BigDecimal workMoneyTotal = paymentList.stream().map(Payment::getWorkMoney).reduce(ZERO, BigDecimal::add);
            contracts.setWorkMoneyTotal(workMoneyTotal);
            //开票金额总计
            BigDecimal invoiceTotal = paymentList.stream().map(Payment::getAmountInvoice).reduce(ZERO, BigDecimal::add);
            contracts.setInvoiceMoneyTotal(invoiceTotal);
            boolean result = contractService.updateById(contracts);
            if (result) {
                return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
            }
        }
        return modifyPayment(oldPaymentList, paymentList);
    }


    /**
     * @param paymentIdList 付款id列表
     * @return Collection<Payment> 付款列表
     * @description 根据付款id列表查询付款列表
     * @date 2020/4/30 1:55 下午
     */
    public Collection<Payment> paymentList(List<Long> paymentIdList) {
        QueryWrapper<Payment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", paymentIdList);
        return listByIds(paymentIdList);
    }

    /**
     * @param contractId 合同id
     * @return paymentList 付款列表
     * @description 查询付款列表
     * @date 2020/1/17 2:57 下午
     */
    public List<Payment> paymentList(Long contractId) {
        QueryWrapper<Payment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("contracts_id", contractId);
        return list(queryWrapper);
    }
}
