package com.iformall.service.impl;

import cn.afterturn.easypoi.word.WordExportUtil;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.*;
import com.iformall.service.*;
import com.iformall.utils.Constant;
import com.iformall.utils.DateUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author gongbiao
 */
@Service
public class WxRentContractServiceImpl implements WxRentContractService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxRentContractMapper wxRentContractMapper;

    @Autowired
    WxShopMapper wxShopMapper;

    @Autowired
    WxMerchantService wxMerchantService;

    @Autowired
    WxBillRentMapper wxBillRentMapper;

    @Autowired
    WxBillDepositMapper wxBillDepositMapper;

    @Autowired
    WxPropertyContractMapper wxPropertyContractMapper;

    @Autowired
    WxMerchantMapper wxMerchantMapper;

    @Autowired
    WxBusinessMapper wxBusinessMapper;

    @Autowired
    WxMallMapper wxMallMapper;

    @Autowired
    WxBrandMapper WxBrandMapper;

    @Autowired
    WxFlowRecordService wxFlowRecordService;

    @Autowired
    RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private WxFlowService wxFlowService;

    @Override
    public Map<String, Object> listAsPage(WxRentContract record, Integer pageIndex, Integer pageSize) {
        Object rentContractStatusInfo = getRentContractStatusInfo(record);
        PageHelper.startPage(pageIndex, pageSize);
        List<Map<String, Object>> rentContractData = wxRentContractMapper.queryRentContractData(record);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(rentContractData);
        Map<String, Object> result = new HashMap<>();
        result.put("rentContractStatusInfo", rentContractStatusInfo);
        result.put("pageInfo", pageInfo);
        return result;
    }

    @Override
    public ResultData getById(Long id) {
        Map<String, Object> result = new HashMap<>();
        WxRentContract wxRentContract = wxRentContractMapper.selectByPrimaryKey(id);
        if (wxRentContract == null) {
            return new ResultData(ErrorCode.RENT_CONTRACT_IS_NOT_FOUND);
        }

        wxRentContract.setPrice(wxRentContract.getPrice() != null ? wxRentContract.getPrice() : 0);
        wxRentContract.setDeposit(wxRentContract.getDeposit() != null ? wxRentContract.getDeposit() : 0);
        result.put("wxRentContract", wxRentContract);
        //关联的商户
        if (wxRentContract.getMerchantId() != null) {
            WxMerchant wxMerchant = wxMerchantService.getById(wxRentContract.getMerchantId());
            result.put("wxMerchant", wxMerchant);
        } else {
            result.put("wxMerchant", null);
        }
        //关联的店铺
        if (wxRentContract.getShopId() != null) {
            WxShop record = new WxShop();
            record.setId(wxRentContract.getShopId());
            List<Map<String, Object>> list = wxShopMapper.findListMap(record);
            result.put("wxShops", list);
        } else {
            result.put("wxShops", Collections.EMPTY_LIST);
        }
        //设置审批流程状态
        result.put("applyStatus", wxRentContract.getApplyStatus());

        //租赁费用欠缴
        result.put("rentOweCount",wxRentContractMapper.queryOweCount(wxRentContract));
        //物业费用欠缴
        WxPropertyContract propertyContract = new WxPropertyContract();
        propertyContract.setRentContractId(id);
        result.put("propertyOweCount",wxPropertyContractMapper.queryOweCount(propertyContract));
        //押金欠缴
        result.put("depositOweCount",wxBillDepositMapper.queryOweCount(wxRentContract));
        //发起人备注
        WxFlowRecord wxFlowRecord = new WxFlowRecord();
        wxFlowRecord.setBusinessId(id);
        wxFlowRecord.setStatus(EnumFlowRecordStatus.NEW.getCode());
        List<WxFlowRecord> flowRecordList = wxFlowRecordService.findList(wxFlowRecord);
        if(!CollectionUtils.isEmpty(flowRecordList)){
            result.put("remark",flowRecordList.get(0).getRemark());
        }

        //查询预账单用于展示
        WxBillRent wxBillRent = new WxBillRent();
        wxBillRent.setRentContractId(id);
        wxBillRent.setSortColumns(WxBillRent.Field.Period_ASC);
        wxBillRent.setIsPreview(EnumIsPreview.YES.getCode());
        List<WxBillRent> resultList = wxBillRentMapper.findList(wxBillRent);
        wxRentContract.setPreviewBillRentList(resultList);

        return new ResultData(Result.SUCCESS, "查询成功", result);
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData save(WxRentContract record,Long userId,String userName) {
        //保存租赁合同信息
        final IdWorker idWorker = IdWorker.get();
        record.setId(idWorker.nextId());
        if (record.getStartDate().after(record.getRentalStartDate())) {
            return new ResultData(ErrorCode.SYS_PARAMETER_ERROR, "起租开始时间不能大于计租开始时间");
        }
        int dayType = record.getAdjustPeriod().equals(EnumRentContractAdjustPeriod.ADJUST_PERIOD_DAY.getCode()) ? Calendar.DAY_OF_MONTH : Calendar.MONTH;

        //计租开始时间
        Calendar instance = Calendar.getInstance();
        instance.setTime(record.getRentalStartDate());
        instance.add(dayType, record.getLease());
        instance.add(Calendar.DAY_OF_MONTH, -1);
        record.setRentalEndDate(instance.getTime());
        //起租结束时间
        if (!record.getStartDate().equals(record.getRentalStartDate())) {
            instance.clear();
            instance.setTime(record.getRentalStartDate());
            instance.add(Calendar.DAY_OF_MONTH, -1);
            record.setEndDate(instance.getTime());
        } else {
            record.setEndDate(record.getStartDate());
        }

        if (record.getType().equals(EnumRentContractType.RENT_BY_JOINT.getCode())) {
            BigDecimal hundred = new BigDecimal(100);
            BigDecimal revenue = new BigDecimal(record.getRevenue() == null ? 0 : record.getRevenue()).divide(hundred);
            BigDecimal payRatio = new BigDecimal(record.getPayRatio() == null ? 0 : record.getPayRatio()).divide(new BigDecimal(10000));
            BigDecimal price = revenue.multiply(payRatio).setScale(2, RoundingMode.HALF_EVEN);
            record.setPrice(price.multiply(hundred).intValue());
        }
        record.setPrice(record.getPrice() == null ? 0 : record.getPrice());
        record.setDeposit(record.getDeposit() == null ? 0 : record.getDeposit());

        Date date = new Date();
        record.setCreatetime(date);
        record.setUpdatetime(date);
        try {
            WxRentContract wxRentContract = new WxRentContract();
            wxRentContract.setTenantId(record.getTenantId());
            wxRentContract.setShopId(record.getShopId());
            long count = wxRentContractMapper.queryRentContractData(wxRentContract).stream().
                    filter(rc -> !rc.get("status").equals(EnumRentContractStatus.CONTRACT_TERMINATE.getCode())
                            && !rc.get("status").equals(EnumRentContractStatus.WAIT_SIGN.getCode())
                            && !rc.get("status").equals(EnumRentContractStatus.INVALID.getCode())
                            && !rc.get("status").equals(EnumRentContractStatus.CONTRACT_END.getCode())
                            && !rc.get("status").equals(EnumRentContractStatus.INTENTION.getCode())).count();
            if (count > 0) {
                return new ResultData(ErrorCode.RENT_CONTRACT_WITH_SHOP_IS_FOUND);
            }
            record.setApplyStatus(EnumRentContractAppStatus.DEFAULT.getCode());
            wxRentContractMapper.insertSelective(record);
        } catch (Exception e) {
            logger.error("保存租赁合同信息失败,e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }

        // 启动审批流
        if(record.getFlowParams() != null){
            record.getFlowParams().put("businessId",record.getId().toString());
            if(record.getMerchantId() != null) {
                record.getFlowParams().put("supplement", true);  //设置补录
            }
            wxFlowService.start(record.getFlowParams(),userId,userName,record.getTenantId());

            // 合同状态改成待签约
            WxRentContract updateRentContract = new WxRentContract();
            updateRentContract.setId(record.getId());
            updateRentContract.setStatus(EnumRentContractStatus.WAIT_SIGN.getCode());
            wxRentContractMapper.updateStatus(updateRentContract);
            logger.info("id:{},启动审批流成功, 是否补录:{}",record.getId().toString(),record.getMerchantId() != null);
        }

        //生成预览账单（补录第二步，第三步走编辑）
        if(record.getReceivePeriod() != null && record.getLease()!=null && record.getPrice()!= null){
            wxBillRentMapper.deletePreviewBill(record);
            //重新生成
            List<WxBillRent> resultList = buildRent(new WxMerchant(), null, record, EnumIsPreview.YES.getCode());
            record.setPreviewBillRentList(resultList);
        }
        return new ResultData(Result.SUCCESS, "保存租赁合同信息成功", record);
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData update(WxRentContract record, Long userId,String userName) {
        //对比上一次，是否有更改，有，重新生成预账单
        WxRentContract dbRent = wxRentContractMapper.selectByPrimaryKey(record.getId());
        boolean change = false;
        if(record.getReceivePeriod() != null && record.getLease()!=null && record.getPrice()!= null) {
            if (record.getType().equals(EnumRentContractType.RENT_BY_AREA.getCode())) {
                if (!record.getReceivePeriod().equals(dbRent.getReceivePeriod())
                        || !record.getLease().equals(dbRent.getLease())
                        || !record.getType().equals(dbRent.getType())
                        || !record.getPrice().equals(dbRent.getPrice())
                        || !record.getAdjustRatio().replaceAll("\\s*","").equals(dbRent.getAdjustRatio().replaceAll("\\s*",""))
                        ) {
                    change = true;
                }
            } else if (record.getType().equals(EnumRentContractType.RENT_BY_JOINT.getCode())) {
                if (!record.getReceivePeriod().equals(dbRent.getReceivePeriod())
                        || !record.getLease().equals(dbRent.getLease())
                        || !record.getType().equals(dbRent.getType())
                        || !record.getRevenue().equals(dbRent.getRevenue())
                        || !record.getPayRatio().equals(dbRent.getPayRatio())
                        ) {
                    change = true;
                }
            } else if (record.getType().equals(EnumRentContractType.RENT_BY_AREA_AND_JOINT.getCode())) {
                if (!record.getReceivePeriod().equals(dbRent.getReceivePeriod())
                        || !record.getLease().equals(dbRent.getLease())
                        || !record.getType().equals(dbRent.getType())
                        || !record.getPrice().equals(dbRent.getPrice())
                        || !record.getPayRatio().equals(dbRent.getPayRatio())
                        ) {
                    change = true;
                }
            }
        }
        // 更新
        ResultData resultData = getResultDataForUpdate(record, userId);

        //有改变，删除预账单，重新生成
        List<WxBillRent> resultList;
        if(change) {
            wxBillRentMapper.deletePreviewBill(record);
            resultList = buildRent(new WxMerchant(), null, record, EnumIsPreview.YES.getCode());
        }else{
            //查询预账单用于展示
            WxBillRent wxBillRent = new WxBillRent();
            wxBillRent.setRentContractId(record.getId());
            wxBillRent.setSortColumns(WxBillRent.Field.Period_ASC);
            wxBillRent.setIsPreview(EnumIsPreview.YES.getCode());
            resultList = wxBillRentMapper.findList(wxBillRent);
        }

        //启动审批流
        if(record.getFlowParams() != null){
            record.getFlowParams().put("businessId",record.getId().toString());
            if(record.getMerchantId() != null) {
                record.getFlowParams().put("supplement", true);  //设置补录
            }
            wxFlowService.start(record.getFlowParams(),userId,userName,record.getTenantId());

            //合同状态改成待签约
            WxRentContract updateRentContract = new WxRentContract();
            updateRentContract.setId(record.getId());
            updateRentContract.setStatus(EnumRentContractStatus.WAIT_SIGN.getCode());
            wxRentContractMapper.updateStatus(updateRentContract);
            logger.info("id:{},启动审批流成功 ,是否补录:{}",record.getId().toString(),record.getMerchantId() != null);
        }

        // 保存调整金额（预账单调整）
        if(!CollectionUtils.isEmpty(record.getPreviewBillRentList())){
            for (WxBillRent wxBillRent:record.getPreviewBillRentList()) {
                wxBillRentMapper.update(wxBillRent);
            }
        }
        WxRentContract wxRentContract = (WxRentContract)resultData.data;
        wxRentContract.setPreviewBillRentList(resultList);
        return new ResultData(wxRentContract);
    }

    public ResultData getResultDataForUpdate(WxRentContract record, Long userId) {
        //更新租赁合同信息
        WxRentContract wxRentContract = wxRentContractMapper.selectByPrimaryKey(record.getId());
        if (wxRentContract == null) {
            return new ResultData(ErrorCode.RENT_CONTRACT_IS_NOT_FOUND);
        }
        int dayType = wxRentContract.getAdjustPeriod().equals(EnumRentContractAdjustPeriod.ADJUST_PERIOD_DAY.getCode()) ? Calendar.DAY_OF_MONTH : Calendar.MONTH;

        Calendar instance = Calendar.getInstance();
        instance.setTime(record.getRentalStartDate());
        instance.add(dayType, record.getLease());
        instance.add(Calendar.DAY_OF_MONTH, -1);
        record.setRentalEndDate(instance.getTime());

        //起租结束时间
        if (!record.getStartDate().equals(record.getRentalStartDate())) {
            instance.clear();
            instance.setTime(record.getRentalStartDate());
            instance.add(Calendar.DAY_OF_MONTH, -1);
            record.setEndDate(instance.getTime());
        } else {
            record.setEndDate(record.getStartDate());
        }

        if (record.getType().equals(EnumRentContractType.RENT_BY_JOINT.getCode())) {
            BigDecimal hundred = new BigDecimal(100);
            BigDecimal revenue = new BigDecimal(record.getRevenue() == null ? 0 : record.getRevenue()).divide(hundred);
            BigDecimal payRatio = new BigDecimal(record.getPayRatio() == null ? 0 : record.getPayRatio()).divide(new BigDecimal(10000));
            BigDecimal price = revenue.multiply(payRatio).setScale(2, RoundingMode.HALF_EVEN);
            record.setPrice(price.multiply(hundred).intValue());
        }
        record.setPrice(record.getPrice() == null ? 0 : record.getPrice());
        record.setDeposit(record.getDeposit() == null ? 0 : record.getDeposit());

        record.setUpdatetime(new Date());
        try {
            WxRentContract wxRentContractParams = new WxRentContract();
            wxRentContractParams.setTenantId(record.getTenantId());
            wxRentContractParams.setShopId(record.getShopId());
            long count = wxRentContractMapper.queryRentContractData(wxRentContractParams).stream().
                    filter(rc -> !rc.get("status").equals(EnumRentContractStatus.CONTRACT_TERMINATE.getCode())
                            && !rc.get("status").equals(EnumRentContractStatus.WAIT_SIGN.getCode())
                            && !rc.get("status").equals(EnumRentContractStatus.INVALID.getCode())
                            && !rc.get("status").equals(EnumRentContractStatus.CONTRACT_END.getCode())
                            && !rc.get("status").equals(EnumRentContractStatus.INTENTION.getCode())
                            && !rc.get("id").equals(wxRentContract.getId())).count();
            if (count > 0) {
                return new ResultData(ErrorCode.RENT_CONTRACT_WITH_SHOP_IS_FOUND);
            }
            wxRentContractMapper.updateByPrimaryKeySelective(record);
        } catch (Exception e) {
            logger.error("更新租赁合同信息失败,e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "保存租赁合同信息成功", wxRentContract);
    }


    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void buildDeposit(WxMerchant wxMerchant, Long userId,Long rentContractId) {
        WxRentContract wxRentContract = wxRentContractMapper.selectByPrimaryKey(rentContractId);
        if (wxRentContract != null) {
            final IdWorker idWorker = IdWorker.get();
            WxBillDeposit wxBillDeposit = new WxBillDeposit();
            wxBillDeposit.setId(idWorker.nextId());
            wxBillDeposit.setRentContractId(wxRentContract.getId());
            wxBillDeposit.setPay(0);
            int needpay = wxRentContract.getDeposit();
            wxBillDeposit.setReceivePay(needpay);
            wxBillDeposit.setNeedPay(needpay);
            wxBillDeposit.setOwe(needpay);
            //找到计租方式
            int dayType = wxRentContract.getAdjustPeriod().equals(EnumRentContractAdjustPeriod.ADJUST_PERIOD_DAY.getCode()) ? Calendar.DAY_OF_MONTH : Calendar.MONTH;

            Date date = new Date();
            Calendar instance = Calendar.getInstance();
            instance.setTime(wxRentContract.getRentalStartDate());
            instance.add(Calendar.DAY_OF_MONTH, -1);
            Date time = instance.getTime();
            wxBillDeposit.setReceiveDate(time);

            //账单开始时间
            instance.clear();
            instance.setTime(wxBillDeposit.getReceiveDate());
            instance.add(Calendar.DAY_OF_MONTH, 1);
            wxBillDeposit.setStarttime(instance.getTime());
            //账单结束时间
            instance.clear();
            instance.setTime(wxBillDeposit.getReceiveDate());
            instance.add(dayType, wxRentContract.getLease());
            wxBillDeposit.setEndtime(instance.getTime());
            wxBillDeposit.setStatus(EnumBillRentStatus.WAIT_PAY.getCode());
            wxBillDeposit.setExpiredDay(0L);
            wxBillDeposit.setReceiveDate(time);
            wxBillDeposit.setTenantId(wxMerchant.getTenantId());
            wxBillDeposit.setIsDel(0);
            wxBillDeposit.setMerchantId(wxMerchant.getId());
            wxBillDeposit.setUserId(userId);
            wxBillDeposit.setShopId(wxRentContract.getShopId());
            wxBillDeposit.setCreatetime(date);
            wxBillDeposit.setUpdatetime(date);
            wxBillDeposit.setIsDel(EnumDelStatus.NOT_DEL.getCode());
            wxBillDeposit.setRentShopType(wxRentContract.getRentShopType());
            try {
                wxBillDepositMapper.insertSelective(wxBillDeposit);
            } catch (Exception e) {
                logger.error("添加押金账单失败,e:" + e.getMessage());
                throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public List<WxBillRent> buildRent(WxMerchant wxMerchant, Long userId,WxRentContract rentContract,Integer isPreview) {
        List<WxBillRent> rentList = new ArrayList<>();
        //根据商户ID找出合同
        WxRentContract wxRentContract;
        if(rentContract == null){
            wxRentContract = new WxRentContract();
            wxRentContract.setMerchantId(wxMerchant.getId());
            List<WxRentContract> list = wxRentContractMapper.findList(wxRentContract);
            if (list.size() > 0) {
                wxRentContract = list.get(0);
            }
        }else{
            wxRentContract = rentContract;
        }
        if (wxRentContract != null) {
            int receivePeriod = wxRentContract.getReceivePeriod().intValue();
            Integer lease = wxRentContract.getLease();
            Date rentalStartDate = wxRentContract.getRentalStartDate();
            Integer price = wxRentContract.getPrice();
            //按月计租
            if (wxRentContract.getAdjustPeriod().equals(EnumRentContractAdjustPeriod.ADJUST_PERIOD_MONTH.getCode())) {
                rentList = buildRentMonth(wxMerchant, userId, wxRentContract, receivePeriod, lease, rentalStartDate, price,isPreview);
            } else {
                //按日计租
                Map<String,Object> resultMap = buildRent(lease, receivePeriod, price, rentalStartDate, Calendar.DAY_OF_MONTH, wxRentContract, userId, wxMerchant, 0,isPreview);
                rentList = ( List<WxBillRent>)resultMap.get("billList");
            }
        }
        for (int i = 0; i < rentList.size(); i++) {
            rentList.get(i).setPeriod(i+1);
        }
        return rentList;
    }

    public List<WxBillRent> buildRentMonth(WxMerchant wxMerchant, Long userId, WxRentContract wxRentContract, int receivePeriod, Integer lease, Date rentalStartDate, Integer price,Integer isPreview) {
        String adjustRatio = wxRentContract.getAdjustRatio();
        List<Integer> integers = JSONArray.parseArray(adjustRatio, Integer.class);
        integers.add(0, 0);
        int size = integers.size();
        int[] priceArr = new int[size];
        priceArr[0] = price;
        double priceD = price;
        for (int i = 1; i < size; i++) {
            priceD = priceD + priceD * integers.get(i) / 10000.0;
            priceArr[i] = new BigDecimal(priceD).setScale(0, RoundingMode.HALF_EVEN).intValue();
        }
        int month = 12;
        int divide = lease / month;
        int mod = lease % month;
        int[] leaseArr = new int[size];
        for (int i = 0; i < divide; i++) {
            leaseArr[i] = month;
        }
        if (mod > 0) {
            leaseArr[divide] = mod;
        }

        int billcount = 0;
        List<WxBillRent> resultList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            Calendar instance = Calendar.getInstance();
            instance.setTime(rentalStartDate);
            //开始时间
            instance.add(Calendar.MONTH, month * i);
            Map<String,Object> resultMap = buildRent(leaseArr[i], receivePeriod, priceArr[i], instance.getTime(), Calendar.MONTH, wxRentContract, userId, wxMerchant, billcount,isPreview);
            List<WxBillRent> billRentList = (List<WxBillRent>)resultMap.get("billList");
            billcount = (Integer)resultMap.get("billcount");
            resultList.addAll(billRentList);
        }
        return resultList;
    }

    public Map<String,Object> buildRent(int lease, int receivePeriod, int price, Date startdate, int dayType, WxRentContract wxRentContract, Long userId, WxMerchant wxMerchant, int billcount,Integer isPreview) {
        Map<String,Object> resultMap = new HashedMap();
        List<WxBillRent> resultList = new ArrayList<>();
        int extralease = lease % receivePeriod;
        int extracount = extralease > 0 ? 1 : 0;
        int paycount = lease / receivePeriod + extracount;
        int index = paycount - 1;
        final IdWorker idWorker = IdWorker.get();
        for (int i = 0; i < paycount; i++) {
            WxBillRent wxBillRent = new WxBillRent();
            wxBillRent.setIsPreview(isPreview);

            wxBillRent.setId(idWorker.nextId());
            wxBillRent.setRentContractId(wxRentContract.getId());
            wxBillRent.setPay(0);
            System.out.println("-----------price:"+price+",receivePeriod:"+receivePeriod);
            int needpay = price * receivePeriod;
            System.out.println("--------needpay:"+needpay);


            Date date = new Date();
            Calendar instance = Calendar.getInstance();
            instance.setTime(startdate);
            instance.add(dayType, receivePeriod * i);
            instance.add(Calendar.DAY_OF_MONTH, -1);
            Date time = instance.getTime();
            wxBillRent.setReceiveDate(time);

            //账单开始时间
            instance.clear();
            instance.setTime(wxBillRent.getReceiveDate());
            instance.add(Calendar.DAY_OF_MONTH, 1);
            wxBillRent.setStarttime(instance.getTime());
            //账单结束时间
            instance.clear();
            instance.setTime(wxBillRent.getStarttime());
            instance.add(dayType, receivePeriod);
            instance.add(Calendar.DAY_OF_MONTH, -1);
            wxBillRent.setEndtime(instance.getTime());

            if (extracount > 0 && i == index) {
                //账单开始时间
                instance.clear();
                instance.setTime(wxBillRent.getReceiveDate());
                instance.add(Calendar.DAY_OF_MONTH, 1);
                wxBillRent.setStarttime(instance.getTime());
                //账单结束时间
                instance.clear();
                instance.setTime(wxBillRent.getStarttime());
                instance.add(dayType, extralease);
                instance.add(Calendar.DAY_OF_MONTH, -1);
                wxBillRent.setEndtime(instance.getTime());
                needpay = price * extralease;
            }
            wxBillRent.setNeedPay(needpay);
            wxBillRent.setOwe(needpay);
            wxBillRent.setReceivePay(needpay);

            //截止收租日在当前时间之前
            if (wxBillRent.getReceiveDate().before(date)) {
                long day = (time.getTime() - date.getTime()) / (24 * 60 * 60 * 1000);
                wxBillRent.setStatus(EnumBillRentStatus.NOT_PAID.getCode());
                wxBillRent.setExpiredDay(day);
            } else {//截止收租日在当前时间之后
                Calendar now = Calendar.getInstance();
                now.add(dayType, receivePeriod);
                Date currenttime = now.getTime();
                //当前日期加上周期后小于截止收租日就是没有到期，否则当前待缴
                if (currenttime.before(wxBillRent.getReceiveDate())) {
                    wxBillRent.setStatus(EnumBillRentStatus.NOT_EXPIRED.getCode());
                    wxBillRent.setExpiredDay(0L);
                } else {
                    wxBillRent.setStatus(EnumBillRentStatus.WAIT_PAY.getCode());
                    wxBillRent.setExpiredDay(0L);
                }
            }

            wxBillRent.setTenantId(wxMerchant.getTenantId());
            wxBillRent.setIsDel(0);
            wxBillRent.setMerchantId(wxMerchant.getId());
            wxBillRent.setUserId(userId);
            wxBillRent.setShopId(wxRentContract.getShopId());
            wxBillRent.setCreatetime(date);
            wxBillRent.setUpdatetime(date);
            wxBillRent.setIsDel(EnumDelStatus.NOT_DEL.getCode());
            wxBillRent.setRentShopType(wxRentContract.getRentShopType());
            wxBillRent.setPeriod(++billcount);
            try {
                wxBillRentMapper.insertSelective(wxBillRent);
                resultList.add(wxBillRent);
            } catch (Exception e) {
                logger.error("添加租赁账单失败,e:" + e.getMessage());
                throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
            }
        }
        resultMap.put("billcount",billcount);
        resultMap.put("billList",resultList);
        return resultMap;
    }


    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData deleteById(String id) {
        wxRentContractMapper.deleteByPrimaryKey(id);
        return new ResultData(Result.SUCCESS, "删除租赁合同信息成功");
    }

    @Override
    public void download(HttpServletRequest request, HttpServletResponse response, String tenantId) {
        String id = request.getParameter("id");
        WxRentContract wxRentContract = wxRentContractMapper.selectByPrimaryKey(id);
        String filesuffix = wxRentContract.getFilepath().substring(wxRentContract.getFilepath().lastIndexOf("."));
        String filename = UUID.randomUUID() + filesuffix;
        String filepath = Constant.fileDirectory;
        String destPath = filepath + filename;
        File dest = new File(destPath);
        File pDest = dest.getParentFile();
        if (!pDest.exists()) {
            pDest.mkdirs();
        }
        try {
            String exportFileName = wxRentContract.getFilename();
            downLoadFromUrl(wxRentContract.getFilepath(), filename, filepath);
            downFile(destPath, wxRentContract.getFilename(), exportFileName, response, request);
            org.apache.commons.io.FileUtils.forceDelete(dest);
        } catch (IOException e) {
            logger.info("创建本地文件失败" + e.getMessage());
        }
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Object getRentContractStatusInfo(WxRentContract rentContract) {

        Map<String, Object> resultData = new HashMap();
        //商铺信息
        WxShop wxShop = new WxShop();
        wxShop.setTenantId(rentContract.getTenantId());
        wxShop.setType(rentContract.getRentShopType());
        wxShop.setStatus(EnumShopStatus.RENT.getCode());
        List<WxShop> rentedList = wxShopMapper.findList(wxShop);
        wxShop.setStatus(EnumShopStatus.NOT_RENT.getCode());
        List<WxShop> unrentedList = wxShopMapper.findList(wxShop);

        HashMap<String, Object> shopMap = new HashMap<>(3);
        int rentedCount = rentedList.size();
        int unrentedCount = unrentedList.size();
        shopMap.put("rentedCount", rentedCount);
        shopMap.put("unrentedCount", unrentedCount);
        shopMap.put("allCount", rentedCount + unrentedCount);
        resultData.put("shopCountInfo", shopMap);

        //需要更新的状态
        resultData.putAll(updateStatus(rentContract));
        return resultData;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData endRentContract(Long id, Integer status) {

        WxRentContract wxRentContract = wxRentContractMapper.selectByPrimaryKey(id);
        if (wxRentContract == null) {
            return new ResultData(ErrorCode.RENT_CONTRACT_IS_NOT_FOUND);
        }
        wxRentContract.setStatus(EnumRentContractStatus.CONTRACT_TERMINATE.getCode());
        try {
            wxRentContract.setUpdatetime(new Date());
            wxRentContractMapper.updateByPrimaryKeySelective(wxRentContract);
            //停用商户
            wxMerchantService.disable(wxRentContract.getMerchantId());
            //物业合同终止
            if (status == 1) {
                WxPropertyContract wxPropertyContract = new WxPropertyContract();
                wxRentContract.setTenantId(wxRentContract.getTenantId());
                wxPropertyContract.setRentContractId(id);
                List<Map<String, Object>> contractData = wxPropertyContractMapper.queryPropertyContractData(wxPropertyContract);
                if (contractData.size() > 0) {
                    Map<String, Object> propertyContract = contractData.get(0);
                    Long propertyContractId = (Long) propertyContract.get("id");
                    if (propertyContract != null && propertyContractId != null) {
                        WxPropertyContract propertyContractUpdate = wxPropertyContractMapper.selectByPrimaryKey(propertyContractId);
                        propertyContractUpdate.setStatus(EnumRentContractStatus.CONTRACT_TERMINATE.getCode());
                        propertyContractUpdate.setUpdatetime(new Date());
                        wxPropertyContractMapper.updateByPrimaryKeySelective(propertyContractUpdate);
                    }
                }
            }
        } catch (MallinkException e) {
            logger.info("终止合同失败:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchant(WxRentContract wxRentContract) {
        WxRentContract record = wxRentContractMapper.selectByPrimaryKey(wxRentContract);
        if (wxRentContract == null) {
            return new ResultData(ErrorCode.RENT_CONTRACT_IS_NOT_FOUND);
        }
        record.setMerchantId(wxRentContract.getMerchantId());
        try {
            wxRentContractMapper.updateByPrimaryKeySelective(record);
        } catch (MallinkException e) {
            logger.info("关联合同商户失败:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");
    }

    @Override
    public PageInfo<WxRentContract> getRentContractList(WxRentContract rentContract, Integer pageIndex, Integer pageSize) {
        PageInfo<WxRentContract> pageInfo = PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxRentContractMapper.getRentContractList(rentContract));
        return pageInfo;
    }

    public Map<String, Object> updateStatus(WxRentContract record) {
        Map<String, Object> resultData = new HashMap();
        WxRentContract wxRentContract = new WxRentContract();
        wxRentContract.setTenantId(record.getTenantId());
        wxRentContract.setRentShopType(record.getRentShopType());

        int allCount = wxRentContractMapper.selectCount(wxRentContract);
        resultData.put("allCount", allCount);

        //审核流程中止
        List<Long> collect = wxRentContractMapper.getRentInvalidList(wxRentContract).stream()
                .map(r -> r.getId()).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(collect)) {
            for (Long id:collect) {
                try {
                    logger.info("合同id:{},开始停止...",id);
                    //结束审批流 by luozukai
                    List<Task> tasks = taskService.createTaskQuery().processDefinitionKey(WxFlowServiceImpl.getFlowKeyByType(1))
                            .processVariableValueEquals("businessId",id).list();
                    if (!CollectionUtils.isEmpty(tasks)) {
                        for (Task task:tasks) {
                            logger.info("合同id:{},taskid:{}",id,task.getId());
                            runtimeService.deleteProcessInstance(task.getProcessInstanceId(), "合同作废");
                        }
                    }
                    // 修改合同审核状态
                    WxRentContract rentContract = new WxRentContract();
                    rentContract.setId(id);
                    rentContract.setApplyStatus(EnumRentContractAppStatus.CANCLE.getCode());
                    updateApplyStatus(rentContract);

                    // 保存审批历史入
                    WxFlowRecord updateRecord = new WxFlowRecord();
                    updateRecord.setBusinessId(id);
                    updateRecord.setStatus(EnumFlowRecordStatus.CANCLE.getCode());
                    updateRecord.setBusinessType(1);
                    wxFlowRecordService.saveOrUpdate(updateRecord);
                }catch (Exception e){
                    logger.error("deleteProcessInstance error",e);
                }
            }
        }

        //把状态为意见而商户未关联的数据改为待签约状态
        //wxRentContractMapper.updateStatusForUnsign(wxRentContract);

        //作废合同
        wxRentContract.setStatus(EnumRentContractStatus.INVALID.getCode());
        wxRentContractMapper.updateRentInvalidStatus(wxRentContract);

        //待签约
        wxRentContract.setStatus(EnumRentContractStatus.WAIT_SIGN.getCode());
        //wxRentContractMapper.updateRentWaitSignStatus(wxRentContract);
        int waitSignCount = wxRentContractMapper.queryRentContractWaitSignStatus(wxRentContract);
        resultData.put("waitSignCount", waitSignCount);

        //计租中
        wxRentContract.setStatus(EnumRentContractStatus.RENT_PAID.getCode());
        wxRentContractMapper.updateRentContractPaidStatus(wxRentContract);
        int rendPaidCount = wxRentContractMapper.queryRentContractPaidStatus(wxRentContract);
        resultData.put("rendPaidCount", rendPaidCount);

        //将到期
        wxRentContract.setStatus(EnumRentContractStatus.CONTRACT_END_SOON.getCode());
        wxRentContractMapper.updateRentContractEndSoonStatus(wxRentContract);
        int endSoonCount = wxRentContractMapper.queryRentContractEndSoonStatus(wxRentContract);
        resultData.put("endSoonCount", endSoonCount);

        //到期
        wxRentContract.setStatus(EnumRentContractStatus.CONTRACT_END.getCode());
        wxRentContractMapper.updateRentContractEndStatus(wxRentContract);
        int endCount = wxRentContractMapper.queryRentContractEndStatus(wxRentContract);
        resultData.put("endCount", endCount);

        //合同到期
        contractEnd(record.getTenantId());

        return resultData;
    }

    private void contractEnd(String tenantId) {
        //查询状态为合同正常到期的数据
        WxRentContract wxRentContract = new WxRentContract();
        wxRentContract.setTenantId(tenantId);
        wxRentContract.setStatus(EnumRentContractStatus.CONTRACT_END.getCode());
        List<Map<String, Object>> rentContractData = wxRentContractMapper.queryRentContractData(wxRentContract);
        for (int i = 0, size = rentContractData.size(); i < size; i++) {
            Map<String, Object> contract = rentContractData.get(i);
            Object merchantId = contract.get("merchantId");
            if (merchantId != null) {
                WxMerchant merchant = wxMerchantMapper.selectByPrimaryKey(merchantId);
                Integer status = merchant.getStatus();
                if (status.equals(EnumMerchantStatus.VALID.getCode())) {
                    wxMerchantService.disable((Long) merchantId);
                }
            }
        }
    }

    public static void downLoadFromUrl(String urlStr, String fileName, String savePath) throws IOException {
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //设置超时间为3秒
        conn.setConnectTimeout(3 * 1000);
        //防止屏蔽程序抓取而返回403错误
        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

        //得到输入流
        InputStream inputStream = conn.getInputStream();
        //获取自己数组
        byte[] getData = readInputStream(inputStream);

        //文件保存位置
        File saveDir = new File(savePath);
        if (!saveDir.exists()) {
            saveDir.mkdir();
        }
        File file = new File(saveDir + File.separator + fileName);
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(getData);
        if (fos != null) {
            fos.close();
        }
        if (inputStream != null) {
            inputStream.close();
        }


        System.out.println("info:" + url + " download success");

    }

    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

    public void downFile(String filePath, String filename, String exportFileName, HttpServletResponse response,
                         HttpServletRequest req) {
        try {
            response.reset();
            response.setContentType("bin");
            String agent = req.getHeader("user-agent");
            if (agent.contains("Firefox")) {
                response.setHeader("Content-disposition", "attachment; filename=" + new String(exportFileName.getBytes("GB2312"), "ISO-8859-1"));
            } else {
                response.setHeader("Content-disposition", "attachment; filename=" + java.net.URLEncoder.encode(exportFileName, "UTF-8"));
            }
            // 循环取出流中的数据
            byte[] b = new byte[1024];
            int len;
            InputStream inStream = new FileInputStream(filePath);
            while ((len = inStream.read(b)) > 0)
                response.getOutputStream().write(b, 0, len);
            inStream.close();
        } catch (Exception e) {
            logger.info("下载合同失败" + e.getMessage());
            e.printStackTrace();
        }
    }

    @Override
    public void exportContract(HttpServletRequest request, HttpServletResponse response, String tenantId, Long id) {
        String contracType = "0";
        String templatePath = null;
        Map<String, Object> result = null;
        if (EnumContractType.ALL.getCode().toString().equals(contracType)) {
            logger.info("获取租赁及物业合同数据");
            result = getRentAndPropertyInfo(id);
            result.put("contractType", EnumContractType.ALL.getMessage());
            if (EnumRentContractType.RENT_BY_AREA.getCode().equals(result.get("type"))) {
                templatePath = "contract-word-template/contract_rent_property.docx";
            } else {
                templatePath = "contract-word-template/contract_rent_property_by_ratio.docx";
            }
            logger.info("租赁及物业合同数据结果:" + result);
        }

        if (templatePath == null) {
            logger.info("没有租赁及物业合同模板");
            return;
        }
        String filepath = Constant.fileDirectory;
        String filename = UUID.randomUUID() + ".docx";
        String exportFileName = result.get("merchantName").toString() + "合同.docx";
        exportWord(templatePath, filepath, filename, exportFileName, result, request, response);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public ResultData updateFile(WxRentContract record, Long userId,String userName) {
        // 保存调整金额（预账单调整）
        if(!CollectionUtils.isEmpty(record.getPreviewBillRentList())){
            for (WxBillRent wxBillRent:record.getPreviewBillRentList()) {
                wxBillRentMapper.update(wxBillRent);
            }
        }
        ResultData resultData = getResultDataForUpdate(record, userId);
        // 启动审批流
        if(record.getFlowParams() != null){
            record.getFlowParams().put("businessId",record.getId().toString());
            if(record.getMerchantId() != null) {
                record.getFlowParams().put("supplement", true);  //设置补录
            }
            wxFlowService.start(record.getFlowParams(),userId,userName,record.getTenantId());

            // 合同状态改成待签约
            WxRentContract updateRentContract = new WxRentContract();
            updateRentContract.setId(record.getId());
            updateRentContract.setStatus(EnumRentContractStatus.WAIT_SIGN.getCode());
            wxRentContractMapper.updateStatus(updateRentContract);
            logger.info("id:{},启动审批流成功,是否补录:{}",record.getId().toString(),record.getMerchantId() != null);
        }
        return resultData;
    }

    @Override
    public ResultData updateRentContractStatus(Long id) {
        if (id == null) {
            return new ResultData(ErrorCode.SYS_PARAMETER_ERROR);
        }
        //更新合同状态为签约
        WxRentContract wxRentContract = new WxRentContract();
        wxRentContract.setId(id);
        wxRentContract.setStatus(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode());
        wxRentContractMapper.updateByPrimaryKeySelective(wxRentContract);
        //建立账单
        WxRentContract record = wxRentContractMapper.selectByPrimaryKey(id);
        if (record != null &&
                record.getMerchantId() != null &&
                record.getStatus().equals(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode()) &&
                record.getReceivePeriod() != null &&
                record.getDeposit() > 0 &&
                record.getPrice() > 0) {
            WxBillRent wxBillRent = new WxBillRent();
            wxBillRent.setMerchantId(record.getMerchantId());

            //预览账单改为正式,并写入商户id
            WxBillRent billRent = new WxBillRent();
            billRent.setRentContractId(id);
            billRent.setIsPreview(EnumIsPreview.NO.getCode());
            billRent.setMerchantId(record.getMerchantId());
            wxBillRentMapper.updatePreviewStatus(billRent);

//            List<Map<String, Object>> billRentList = wxBillRentMapper.queryBillRentList(wxBillRent);
//            if (billRentList.size() == 0) {
                WxMerchant wxMerchant = new WxMerchant();
                wxMerchant.setId(record.getMerchantId());
                wxMerchant.setTenantId(record.getTenantId());
                //租金
//                buildRent(wxMerchant, null,null);
                //押金
                buildDeposit(wxMerchant, null,id);
//            }
        }
        return new ResultData(Result.SUCCESS, "操作成功");
    }

    public Map<String, Object> getRentAndPropertyInfo(Long id) {
        logger.info("获取租赁物业合同数据>>>>>>id:" + id);
        WxRentContract wxRentContract = wxRentContractMapper.selectByPrimaryKey(id);
        WxShop record = new WxShop();
        record.setId(wxRentContract.getShopId());
        Map<String, Object> wxShop = wxShopMapper.findListMap(record).get(0);
        Map<String, Object> result = new HashMap<>();
        //MALL信息
        WxMall wxMall = new WxMall();
        wxMall.setTenantId(wxRentContract.getTenantId());
        wxMall = wxMallMapper.findList(wxMall).get(0);
        result.put("mallName", wxMall.getName());
        result.put("province", wxMall.getProvince());
        result.put("city", wxMall.getCity());
        //经营业态
        WxBusiness wxBusiness = wxBusinessMapper.selectByPrimaryKey(wxRentContract.getBusinessId());
        result.put("business", wxBusiness.getTitle());
        //店铺信息
        result.put("shopNumber", wxShop.get("shopNumber"));
        result.put("floorName", wxShop.get("floor"));
        result.put("buildingName", wxShop.get("building"));
        result.put("buildArea", wxShop.get("buildArea"));
        result.put("operationArea", wxShop.get("operationArea"));
        //商户信息
        WxMerchant merchant = wxMerchantService.getById(wxRentContract.getMerchantId());
        if (merchant != null) {
            result.put("merchantName", merchant.getName());
            //法人信息
            WxMerchantCorp wxMerchantCorp = merchant.getWxMerchantCorp();
            result.put("corpPapersNumber", StringUtils.isNotEmpty(wxMerchantCorp.getCorpPapersNumber()) ? wxMerchantCorp.getCorpPapersNumber() : " ");
            result.put("corpPapersType", wxMerchantCorp.getCorpPapersType() != null ? EnumPapersType.getEnum(wxMerchantCorp.getCorpPapersType()).getMessage() : " ");
            result.put("corpPapersPerson", StringUtils.isNotEmpty(wxMerchantCorp.getCorpPapersPerson()) ? wxMerchantCorp.getCorpPapersPerson() : " ");
            //税务信息
            WxMerchantTax wxMerchantTax = merchant.getWxMerchantTax();
            result.put("taxPapersType", wxMerchantTax.getTaxPapersType() != null ? EnumTaxpayerType.getEnum(wxMerchantTax.getTaxPapersType()).getMessage() : " ");
            result.put("bankName", StringUtils.isNotEmpty(wxMerchantTax.getBankName()) ? wxMerchantTax.getBankName() : " ");
            result.put("bankAccount", StringUtils.isNotEmpty(wxMerchantTax.getBankAccount()) ? wxMerchantTax.getBankAccount() : " ");
            result.put("invoiceAddressPhone", StringUtils.isNotEmpty(wxMerchantTax.getInvoiceAddressPhone()) ? wxMerchantTax.getInvoiceAddressPhone() : " ");
        } else {
            result.put("merchantName", "");
            //法人信息
            result.put("corpPapersNumber", " ");
            result.put("corpPapersType", " ");
            result.put("corpPapersPerson", " ");
            //税务信息
            result.put("taxPapersType", " ");
            result.put("bankName", " ");
            result.put("bankAccount", " ");
            result.put("invoiceAddressPhone", " ");
        }
        //租赁合同信息
        String rentalStartDate = DateUtils.date2String(wxRentContract.getRentalStartDate(), "yyyy-MM-dd");
        result.put("rentalStartDate", rentalStartDate);
        result.put("rentalStartDateYear", rentalStartDate.substring(0, 4));
        result.put("rentalStartDateMonth", rentalStartDate.substring(5, 7));
        result.put("rentalStartDateDay", rentalStartDate.substring(8));
        String rentalEndDate = DateUtils.date2String(wxRentContract.getRentalEndDate(), "yyyy-MM-dd");
        result.put("rentalEndDate", rentalEndDate);
        result.put("rentalEndDateYear", rentalEndDate.substring(0, 4));
        result.put("rentalEndDateMonth", rentalEndDate.substring(5, 7));
        result.put("rentalEndDateDay", rentalEndDate.substring(8));
        result.put("price", wxRentContract.getPrice());
        result.put("contractNumber", wxRentContract.getContractNumber());
        Integer lease = wxRentContract.getLease();
        Integer receivePeriod = wxRentContract.getReceivePeriod();
        result.put("lease", lease);
        result.put("receivePeriod", receivePeriod);
        result.put("payAccount", wxRentContract.getPayAccount().equals("") ? " " : wxRentContract.getPayAccount());
        result.put("signDate", DateUtils.date2String(wxRentContract.getSignDate(), "yyyy-MM-dd"));
        //品牌
        Long brandId = wxRentContract.getBrand();
        String brand = " ";
        if (brandId != null) {
            WxBrand wxBrand = WxBrandMapper.selectByPrimaryKey(brandId);
            if (wxBrand != null) {
                brand = wxBrand.getName();
            }
        }
        result.put("brand", brand);
        // TODO
        //double adjustRatio = wxRentContract.getAdjustRatio() != null ? wxRentContract.getAdjustRatio() / 100.0 : 0;
        result.put("adjustRatio", 0);
        double priceRent = new BigDecimal(wxRentContract.getPrice())
                .divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
        result.put("priceRent", priceRent);
        double unitPrice = new BigDecimal(wxRentContract.getPrice())
                .divide(new BigDecimal(wxRentContract.getRentArea()), 2, RoundingMode.HALF_EVEN)
                .divide(new BigDecimal(100))
                .setScale(2, RoundingMode.HALF_EVEN).doubleValue();
        result.put("unitPriceRent", unitPrice);
        result.put("priceRentUpper", digitUppercase(priceRent));
        result.put("unitPriceRentUpper", digitUppercase(unitPrice));
        //租赁保证金
        int cashDepositMonthRent = 3;
        double cashDepositRent = new BigDecimal(wxRentContract.getPrice()).multiply(new BigDecimal(cashDepositMonthRent))
                .divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
        result.put("cashDepositMonthRent", cashDepositMonthRent);
        result.put("cashDepositRent", cashDepositRent);
        result.put("cashDepositRentUpper", digitUppercase(cashDepositRent));
        result.put("type", wxRentContract.getType());
        int extralease = lease % 12;
        int extracount = extralease > 0 ? 1 : 0;
        int paycount = lease / 12 + extracount;
        int index = 10 - paycount;
        int count = paycount - 1;
        BigDecimal rentPrice = new BigDecimal(priceRent);
        if (wxRentContract.getType().equals(EnumRentContractType.RENT_BY_AREA.getCode())) {
            areaWay(wxRentContract, result, lease, 0, extralease, extracount, paycount, index, count, rentPrice);
        } else {
            //保底
            double revenue = new BigDecimal(wxRentContract.getRevenue())
                    .divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
            result.put("revenue", revenue);
            result.put("revenueUpper", digitUppercase(revenue));
            ratioWay(wxRentContract, result, lease, 0, extralease, extracount, paycount, index, count, rentPrice);
        }
        //物业合同信息
        WxPropertyContract propertyContract = new WxPropertyContract();
        propertyContract.setTenantId(wxRentContract.getTenantId());
        propertyContract.setRentContractId(wxRentContract.getId());
        Optional<Map<String, Object>> first = wxPropertyContractMapper.queryPropertyContractData(propertyContract)
                .stream().filter(rc -> !rc.get("status").equals(EnumRentContractStatus.CONTRACT_TERMINATE.getCode())
                        && !rc.get("status").equals(EnumRentContractStatus.WAIT_SIGN.getCode())
                        && !rc.get("status").equals(EnumRentContractStatus.INVALID.getCode())
                        && !rc.get("status").equals(EnumRentContractStatus.CONTRACT_END.getCode())
                        && !rc.get("status").equals(EnumRentContractStatus.INTENTION.getCode())).findFirst();
        Map<String, Object> wxPropertyContract = null;
        if (first.isPresent()) {
            wxPropertyContract = first.get();
        }
        if (wxPropertyContract != null) {
            Integer receivePeriodProperty = (Integer) wxPropertyContract.get("receivePeriod");
            result.put("receivePeriodProperty", receivePeriodProperty);
            double priceProperty = new BigDecimal(wxPropertyContract.get("price").toString())
                    .divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
            result.put("priceProperty", priceProperty);
            double unitPriceProperty = new BigDecimal(wxPropertyContract.get("price").toString())
                    .divide(new BigDecimal(wxRentContract.getRentArea()), 2, RoundingMode.HALF_EVEN)
                    .divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
            result.put("unitPriceProperty", unitPriceProperty);
            result.put("pricePropertyUpper", digitUppercase(priceProperty));
            result.put("unitPricePropertyUpper", digitUppercase(unitPriceProperty));
            //首期物业费
            Calendar instance = Calendar.getInstance();
            instance.setTime(wxRentContract.getRentalStartDate());
            instance.add(Calendar.MONTH, 0);
            Date starttime = instance.getTime();
            String startdate = DateUtils.date2String(starttime, "yyyy-MM-dd");
            result.put("rentalStartDateProperty", startdate);
            result.put("rentalStartDateYearProperty", startdate.substring(0, 4));
            result.put("rentalStartDateMonthProperty", startdate.substring(5, 7));
            result.put("rentalStartDateDayProperty", startdate.substring(8));
            //结束时间
            instance.clear();
            instance.setTime(starttime);
            instance.add(Calendar.MONTH, receivePeriodProperty);
            instance.add(Calendar.DAY_OF_MONTH, -1);
            Date endtime = instance.getTime();
            String enddate = DateUtils.date2String(endtime, "yyyy-MM-dd");
            result.put("rentalEndDateProperty", enddate);
            result.put("rentalEndDateYearProperty", enddate.substring(0, 4));
            result.put("rentalEndDateMonthProperty", enddate.substring(5, 7));
            result.put("rentalEndDateDayProperty", enddate.substring(8));
            double pricePropertyFirst = new BigDecimal(priceProperty)
                    .multiply(new BigDecimal(receivePeriodProperty))
                    .setScale(2, RoundingMode.HALF_EVEN).doubleValue();
            result.put("pricePropertyFirst", pricePropertyFirst);
            result.put("pricePropertyFirstUpper", digitUppercase(pricePropertyFirst));


            //物业保证金
            int cashDepositMonthProperty = 3;
            double cashDepositProperty = new BigDecimal(wxPropertyContract.get("price").toString()).multiply(new BigDecimal(cashDepositMonthProperty))
                    .divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
            result.put("cashDepositMonthProperty", cashDepositMonthProperty);
            result.put("cashDepositProperty", cashDepositProperty);
            result.put("cashDepositPropertyUpper", digitUppercase(cashDepositProperty));


        } else {
            result.put("receivePeriodProperty", " ");
            result.put("priceProperty", " ");
            result.put("unitPriceProperty", " ");
            result.put("pricePropertyUpper", " ");
            result.put("unitPricePropertyUpper", " ");
            //首期物业费
            result.put("rentalStartDateProperty", " ");
            result.put("rentalStartDateYearProperty", " ");
            result.put("rentalStartDateMonthProperty", " ");
            result.put("rentalStartDateDayProperty", " ");
            //结束时间
            result.put("rentalEndDateProperty", " ");
            result.put("rentalEndDateYearProperty", " ");
            result.put("rentalEndDateMonthProperty", " ");
            result.put("rentalEndDateDayProperty", " ");
            result.put("pricePropertyFirst", " ");
            result.put("pricePropertyFirstUpper", " ");
            //物业保证金
            result.put("cashDepositMonthProperty", " ");
            result.put("cashDepositProperty", " ");
            result.put("cashDepositPropertyUpper", " ");
        }


        return result;
    }

    public void ratioWay(WxRentContract wxRentContract, Map<String, Object> result, Integer lease, double adjustRatio, int extralease, int extracount, int paycount, int index, int count, BigDecimal rentPrice) {

        double payRatio = wxRentContract.getPayRatio() != null ? wxRentContract.getPayRatio() / 100.0 : 0;
        //常规租期
        for (int i = 0; i <= count; i++) {
            //开始时间
            Calendar instance = Calendar.getInstance();
            instance.setTime(wxRentContract.getRentalStartDate());
            instance.add(Calendar.MONTH, lease * i);
            Date starttime = instance.getTime();
            String startdate = DateUtils.date2String(starttime, "yyyy-MM-dd");
            result.put("rentalStartDate" + i, startdate);
            result.put("rentalStartDateYear" + i, startdate.substring(0, 4));
            result.put("rentalStartDateMonth" + i, startdate.substring(5, 7));
            result.put("rentalStartDateDay" + i, startdate.substring(8));
            //结束时间
            instance.clear();
            instance.setTime(starttime);
            instance.add(Calendar.MONTH, lease);
            instance.add(Calendar.DAY_OF_MONTH, -1);
            Date endtime = instance.getTime();
            String enddate = DateUtils.date2String(endtime, "yyyy-MM-dd");
            result.put("rentalEndDate" + i, enddate);
            result.put("rentalEndDateYear" + i, enddate.substring(0, 4));
            result.put("rentalEndDateMonth" + i, enddate.substring(5, 7));
            result.put("rentalEndDateDay" + i, enddate.substring(8));
            result.put("adjustRatio" + i, wxRentContract.getAdjustRatio());
            result.put("adjustPeriod" + i, wxRentContract.getAdjustPeriod());
            result.put("payRatio" + i, wxRentContract.getPayRatio());

        }
        if (extracount > 0) {
            //额外租期
            //开始时间
            Calendar instance = Calendar.getInstance();
            instance.setTime(wxRentContract.getRentalStartDate());
            instance.add(Calendar.MONTH, lease * count);
            Date starttime = instance.getTime();
            String startdate = DateUtils.date2String(starttime, "yyyy-MM-dd");
            result.put("rentalStartDate" + count, startdate);
            result.put("rentalStartDateYear" + count, startdate.substring(0, 4));
            result.put("rentalStartDateMonth" + count, startdate.substring(5, 7));
            result.put("rentalStartDateDay" + count, startdate.substring(8));
            //结束时间
            instance.clear();
            instance.setTime(starttime);
            instance.add(Calendar.MONTH, extralease);
            instance.add(Calendar.DAY_OF_MONTH, -1);
            Date endtime = instance.getTime();
            String enddate = DateUtils.date2String(endtime, "yyyy-MM-dd");
            result.put("rentalEndDate" + count, enddate);
            result.put("rentalEndDateYear" + count, enddate.substring(0, 4));
            result.put("rentalEndDateMonth" + count, enddate.substring(5, 7));
            result.put("rentalEndDateDay" + count, enddate.substring(8));
            result.put("adjustRatio" + count, wxRentContract.getAdjustRatio());
            result.put("adjustPeriod" + count, wxRentContract.getAdjustPeriod());
            result.put("payRatio" + count, wxRentContract.getPayRatio());

        }
        //无数据租期
        for (int i = paycount; i <= index; i++) {
            result.put("rentalStartDate" + i, "/");
            result.put("rentalStartDateYear" + i, "/");
            result.put("rentalStartDateMonth" + i, "/");
            result.put("rentalStartDateDay" + i, "/");
            result.put("rentalEndDate" + i, "/");
            result.put("rentalEndDateYear" + i, "/");
            result.put("rentalEndDateMonth" + i, "/");
            result.put("rentalEndDateDay" + i, "/");
            result.put("adjustRatio" + i, "/");
            result.put("adjustPeriod" + i, "/");
            result.put("payRatio" + i, "/");
        }
    }

    public void areaWay(WxRentContract wxRentContract, Map<String, Object> result, Integer lease, double adjustRatio, int extralease, int extracount, int paycount, int index, int count, BigDecimal rentPrice) {
        //常规租期
        for (int i = 0; i <= count; i++) {
            //开始时间
            Calendar instance = Calendar.getInstance();
            instance.setTime(wxRentContract.getRentalStartDate());
            instance.add(Calendar.MONTH, lease * i);
            Date starttime = instance.getTime();
            String startdate = DateUtils.date2String(starttime, "yyyy-MM-dd");
            result.put("rentalStartDate" + i, startdate);
            result.put("rentalStartDateYear" + i, startdate.substring(0, 4));
            result.put("rentalStartDateMonth" + i, startdate.substring(5, 7));
            result.put("rentalStartDateDay" + i, startdate.substring(8));
            //结束时间
            instance.clear();
            instance.setTime(starttime);
            instance.add(Calendar.MONTH, lease);
            instance.add(Calendar.DAY_OF_MONTH, -1);
            Date endtime = instance.getTime();
            String enddate = DateUtils.date2String(endtime, "yyyy-MM-dd");
            result.put("rentalEndDate" + i, enddate);
            result.put("rentalEndDateYear" + i, enddate.substring(0, 4));
            result.put("rentalEndDateMonth" + i, enddate.substring(5, 7));
            result.put("rentalEndDateDay" + i, enddate.substring(8));
            if (i > 0) {
                rentPrice = rentPrice.multiply(new BigDecimal(adjustRatio))
                        .add(rentPrice).setScale(2, RoundingMode.HALF_EVEN);
                result.put("priceRentUpper" + i, digitUppercase(rentPrice.doubleValue()));
                result.put("priceRent" + i, rentPrice.doubleValue());
            }
            result.put("adjustRatio" + i, wxRentContract.getAdjustRatio());
        }
        if (extracount > 0) {
            //额外租期
            //开始时间
            Calendar instance = Calendar.getInstance();
            instance.setTime(wxRentContract.getRentalStartDate());
            instance.add(Calendar.MONTH, lease * count);
            Date starttime = instance.getTime();
            String startdate = DateUtils.date2String(starttime, "yyyy-MM-dd");
            result.put("rentalStartDate" + count, startdate);
            result.put("rentalStartDateYear" + count, startdate.substring(0, 4));
            result.put("rentalStartDateMonth" + count, startdate.substring(5, 7));
            result.put("rentalStartDateDay" + count, startdate.substring(8));
            //结束时间
            instance.clear();
            instance.setTime(starttime);
            instance.add(Calendar.MONTH, extralease);
            instance.add(Calendar.DAY_OF_MONTH, -1);
            Date endtime = instance.getTime();
            String enddate = DateUtils.date2String(endtime, "yyyy-MM-dd");
            result.put("rentalEndDate" + count, enddate);
            result.put("rentalEndDateYear" + count, enddate.substring(0, 4));
            result.put("rentalEndDateMonth" + count, enddate.substring(5, 7));
            result.put("rentalEndDateDay" + count, enddate.substring(8));

            rentPrice = rentPrice.multiply(new BigDecimal(adjustRatio))
                    .add(rentPrice).setScale(2, RoundingMode.HALF_EVEN);
            result.put("priceRentUpper" + count, digitUppercase(rentPrice.doubleValue()));
            result.put("priceRent" + count, rentPrice.doubleValue());
            result.put("adjustRatio" + count, wxRentContract.getAdjustRatio());

        }
        //无数据租期
        for (int i = paycount; i <= index; i++) {
            result.put("rentalStartDate" + i, "/");
            result.put("rentalStartDateYear" + i, "/");
            result.put("rentalStartDateMonth" + i, "/");
            result.put("rentalStartDateDay" + i, "/");
            result.put("rentalEndDate" + i, "/");
            result.put("rentalEndDateYear" + i, "/");
            result.put("rentalEndDateMonth" + i, "/");
            result.put("rentalEndDateDay" + i, "/");
            result.put("priceRentUpper" + i, "/");
            result.put("priceRent" + i, "/");
            result.put("adjustRatio" + i, "/");
        }
    }

    /**
     * 导出word
     * <p>第一步生成替换后的word文件，只支持docx</p>
     * <p>第二步下载生成的文件</p>
     * <p>第三步删除生成的临时文件</p>
     * 模版变量中变量格式：{{foo}}
     *
     * @param templatePath word模板地址
     * @param temDir       生成临时文件存放地址
     * @param fileName     文件名
     * @param params       替换的参数
     * @param request      HttpServletRequest
     * @param response     HttpServletResponse
     */
    public void exportWord(String templatePath, String temDir, String fileName, String exportFileName, Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) {
        Assert.notNull(templatePath, "模板路径不能为空");
        Assert.notNull(temDir, "临时文件路径不能为空");
        Assert.notNull(exportFileName, "导出文件名不能为空");
        Assert.isTrue(exportFileName.endsWith(".docx"), "word导出请使用docx格式");
        if (!temDir.endsWith("/")) {
            temDir = temDir + File.separator;
        }
        File dir = new File(temDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        try {
//            String userAgent = request.getHeader("user-agent").toLowerCase();
//            if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
//                exportFileName = URLEncoder.encode(exportFileName, "UTF-8");
//            } else {
//                exportFileName = new String(exportFileName.getBytes("utf-8"), "ISO-8859-1");
//            }


            XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
            String tmpPath = temDir + fileName;
            FileOutputStream fos = new FileOutputStream(tmpPath);
            doc.write(fos);
            // 设置强制下载不打开
            response.setContentType("application/force-download");
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;fileName=" + exportFileName);
            String userAgent = request.getHeader("user-agent");
            if (userAgent.contains("Firefox")) {
                response.setHeader("Content-disposition",
                        "attachment; filename="
                                + new String(exportFileName.getBytes("GB2312"),
                                "ISO-8859-1"));
            } else {
                response
                        .setHeader("Content-disposition",
                                "attachment; filename="
                                        + java.net.URLEncoder.encode(exportFileName,
                                        "UTF-8"));
            }
            OutputStream out = response.getOutputStream();
            doc.write(out);
            out.close();
            FileUtils.forceDelete(new File(tmpPath));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 数字金额大写转换，思想先写个完整的然后将如零拾替换成零 要用到正则表达式
     */
    public static String digitUppercase(double n) {
        String fraction[] = {"角", "分"};
        String digit[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        String unit[][] = {{"圆", "万", "亿"}, {"", "拾", "佰", "仟"}};

        String head = n < 0 ? "负" : "";
        n = Math.abs(n);

        String s = "";
        for (int i = 0; i < fraction.length; i++) {
            s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
        }
        if (s.length() < 1) {
            s = "整";
        }
        int integerPart = (int) Math.floor(n);

        for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
            String p = "";
            for (int j = 0; j < unit[1].length && n > 0; j++) {
                p = digit[integerPart % 10] + unit[1][j] + p;
                integerPart = integerPart / 10;
            }
            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
        }
        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }

    @Override
    public void updateApplyStatus(WxRentContract wxRentContract) {
        wxRentContractMapper.updateApplyStatus(wxRentContract);
    }

}
