package com.iformall.service.impl;

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.WxFlowRecordService;
import com.iformall.service.WxFlowService;
import com.iformall.service.WxPropertyContractService;
import com.iformall.utils.Constant;
import org.apache.commons.collections.map.HashedMap;
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.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.*;

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

    @Autowired
    WxPropertyContractMapper wxPropertyContractMapper;

    @Autowired
    WxShopMapper wxShopMapper;

    @Autowired
    WxBillPropertyMapper wxBillPropertyMapper;

    @Autowired
    WxBillPropertyDepositMapper wxBillPropertyDepositMapper;

    @Autowired
    WxMerchantMapper wxMerchantMapper;

    @Autowired
    WxRentContractMapper wxRentContractMapper;

    @Autowired
    WxFlowService wxFlowService;

    @Autowired
    WxFlowRecordService wxFlowRecordService;

    @Override
    public Map<String, Object> listAsPage(WxPropertyContract record, Integer pageIndex, Integer pageSize) {
        Object rentContractStatusInfo = getRentContractStatusInfo(record);
        PageHelper.startPage(pageIndex, pageSize);
        List<Map<String, Object>> rentContractData = wxPropertyContractMapper.queryPropertyContractData(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<>();
        WxPropertyContract wxPropertyContract = wxPropertyContractMapper.selectByPrimaryKey(id);
        if (wxPropertyContract == null) {
            return new ResultData(ErrorCode.PROPERTY_CONTRACT_IS_NOT_FOUND);
        }
        wxPropertyContract.setPrice(wxPropertyContract.getPrice() != null ? wxPropertyContract.getPrice() : 0);
        wxPropertyContract.setDeposit(wxPropertyContract.getDeposit() != null ? wxPropertyContract.getDeposit() : 0);

        result.put("wxPropertyContract", wxPropertyContract);
        //关联的商户
        if (wxPropertyContract.getMerchantId() != null) {
            WxMerchant wxMerchant = wxMerchantMapper.selectByPrimaryKey(wxPropertyContract.getMerchantId());
            result.put("wxMerchant", wxMerchant);
        } else {
            result.put("wxMerchant", null);
        }
        //关联的店铺
        if (wxPropertyContract.getShopId() != null) {
            WxShop record = new WxShop();
            record.setId(wxPropertyContract.getShopId());
            List<Map<String, Object>> list = wxShopMapper.findListMap(record);
            result.put("wxShops", list);
        } else {
            result.put("wxShops", Collections.EMPTY_LIST);
        }

        //租赁费用欠缴
        WxRentContract wxRentContract = new WxRentContract();
        wxRentContract.setId(wxPropertyContract.getRentContractId());
        result.put("rentOweCount",wxRentContractMapper.queryOweCount(wxRentContract));
        //物业费用欠缴
        WxPropertyContract propertyContract = new WxPropertyContract();
        propertyContract.setId(id);
        result.put("propertyOweCount",wxPropertyContractMapper.queryOweCount(propertyContract));
        //押金欠缴
        result.put("depositOweCount",wxBillPropertyDepositMapper.queryOweCount(propertyContract));
        //发起人备注
        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());
        }

//        //生成预览账单
//        if(wxPropertyContract.getReceivePeriod() != null && wxPropertyContract.getLease()!=null) {
//            wxBillPropertyMapper.deletePreviewBill(wxPropertyContract);
//            //重新生成
//            List<WxBillProperty> billList = buildProperty(new WxMerchant(),wxPropertyContract,EnumIsPreview.YES.getCode());
//            wxPropertyContract.setPreviewBillRentList(billList);
//        }
        //查询预账单用于展示
        WxBillProperty wxBillRent = new WxBillProperty();
        wxBillRent.setPropertyContractId(id);
        wxBillRent.setSortColumns(WxBillProperty.Field.Period_ASC);
        wxBillRent.setIsPreview(EnumIsPreview.YES.getCode());
        List<WxBillProperty> resultList = wxBillPropertyMapper.findList(wxBillRent);
        wxPropertyContract.setPreviewBillRentList(resultList);

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

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public ResultData saveOrUpdate(WxPropertyContract record, Long userId,String userName) {
        // 保存调整金额（预账单调整）
        if(!CollectionUtils.isEmpty(record.getPreviewBillRentList())){
            for (WxBillProperty wxBillProperty:record.getPreviewBillRentList()) {
                wxBillPropertyMapper.update(wxBillProperty);
            }
        }

        if (null == record.getShopId()) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "shopId不能为空");
        }

        WxRentContract wxRentContract = wxRentContractMapper.selectByPrimaryKey(record.getRentContractId());
        if (wxRentContract != null) {
            if (wxRentContract.getStatus().equals(EnumRentContractStatus.CONTRACT_END.getCode()) ||
                    wxRentContract.getStatus().equals(EnumRentContractStatus.CONTRACT_TERMINATE.getCode()) ||
                    wxRentContract.getStatus().equals(EnumRentContractStatus.WAIT_SIGN.getCode()) ||
                    wxRentContract.getStatus().equals(EnumRentContractStatus.INVALID.getCode())) {
                return new ResultData(ErrorCode.RENT_CONTRACT_IS_TERMINATED);
            }
        }
        if (null == record.getMerchantId()) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "merchantId不能为空");
        }
        WxMerchant merchant = wxMerchantMapper.selectByPrimaryKey(record.getMerchantId());
        if (merchant == null) {
            return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
        }
        if (null == record.getReceivePeriod()) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "付款周期不能为空");
        }
        if (null == record.getLease()) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "租期不能为空");
        }
        if (null == record.getPrice()) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "物业费不能为空");
        }
        if (null == record.getDeposit()) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "押金不能为空");
        }
        if (record.getPrice().intValue() <= 0) {
            return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "物业费要大于0");
        }
        if (record.getDeposit().intValue() <= 0) {
            return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "押金要大于0");
        }

        WxPropertyContract propertyContract = new WxPropertyContract();
        propertyContract.setTenantId(record.getTenantId());
        propertyContract.setRentContractId(record.getRentContractId());
        long count = wxPropertyContractMapper.findList(propertyContract)
                .stream().filter(p -> p.getStatus().equals(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode()) ||
                        p.getStatus().equals(EnumRentContractStatus.RENT_PAID.getCode()) ||
                        p.getStatus().equals(EnumRentContractStatus.CONTRACT_END_SOON.getCode())).count();
        if (count > 0) {
            return new ResultData(ErrorCode.RENT_CONTRACT_WITH_SHOP_IS_FOUND);
        }
        int dayType = record.getAdjustPeriod().equals(EnumRentContractAdjustPeriod.ADJUST_PERIOD_DAY.getCode()) ? Calendar.DAY_OF_MONTH : Calendar.MONTH;
        //保存物业合同信息
        String message;
        if (record.getId() == null) {
            final IdWorker idWorker = IdWorker.get();
            record.setId(idWorker.nextId());
            //计租开始时间
            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());
            }
            Date date = new Date();
            record.setCreatetime(date);
            record.setUpdatetime(date);
            record.setStatus(EnumRentContractStatus.WAIT_SIGN.getCode());
            record.setApplyStatus(EnumRentContractAppStatus.DEFAULT.getCode());
            try {
                wxPropertyContractMapper.insertSelective(record);
            } catch (Exception e) {
                logger.error("保存物业合同信息失败,e:" + e.getMessage());
                throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
            }

            //生成预览账单
            wxBillPropertyMapper.deletePreviewBill(record);
            //重新生成
            List<WxBillProperty> billList = buildProperty(new WxMerchant(),userId,record,EnumIsPreview.YES.getCode());
            record.setPreviewBillRentList(billList);

            message = "保存物业合同信息成功";
        } else {//更新物业合同信息
            WxPropertyContract wxPropertyContract = wxPropertyContractMapper.selectByPrimaryKey(record.getId());
            if (wxPropertyContract == null) {
                return new ResultData(ErrorCode.PROPERTY_CONTRACT_IS_NOT_FOUND);
            }
            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());
            }
            record.setPrice(record.getPrice() != null ? record.getPrice() : 0);
            record.setDeposit(record.getDeposit() != null ? record.getDeposit() : 0);
            record.setUpdatetime(new Date());
            record.setStatus(EnumRentContractStatus.WAIT_SIGN.getCode());
            try {
                wxPropertyContractMapper.updateByPrimaryKeySelective(record);
            } catch (Exception e) {
                logger.error("更新物业合同信息失败,e:" + e.getMessage());
                throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
            }

            //生成预览账单
            if(!wxPropertyContract.getReceivePeriod().equals(record.getReceivePeriod())
                    ||!wxPropertyContract.getPrice().equals(record.getPrice())
                    ||!wxPropertyContract.getDeposit().equals(record.getDeposit())){
                wxBillPropertyMapper.deletePreviewBill(record);
                //重新生成
                wxPropertyContract.setPrice(record.getPrice());
                wxPropertyContract.setDeposit(record.getDeposit());
                wxPropertyContract.setReceivePeriod(record.getReceivePeriod());
                wxPropertyContract.setPayAccount(record.getPayAccount());
                List<WxBillProperty> billList = buildProperty(new WxMerchant(),userId,wxPropertyContract,EnumIsPreview.YES.getCode());
                record.setPreviewBillRentList(billList);
            }else{
                //查询预账单用于展示
                WxBillProperty wxBillRent = new WxBillProperty();
                wxBillRent.setPropertyContractId(record.getId());
                wxBillRent.setSortColumns(WxBillProperty.Field.Period_ASC);
                wxBillRent.setIsPreview(EnumIsPreview.YES.getCode());
                List<WxBillProperty> billList = wxBillPropertyMapper.findList(wxBillRent);
                record.setPreviewBillRentList(billList);
            }
            message = "更新物业合同信息成功";
        }

        //启动审批流
        if(!CollectionUtils.isEmpty(record.getFlowParams())) {
            record.getFlowParams().put("businessId", record.getId().toString());
            wxFlowService.start(record.getFlowParams(), userId, userName, record.getTenantId());

            // 合同状态改成待签约
            WxPropertyContract updateRentContract = new WxPropertyContract();
            updateRentContract.setId(record.getId());
            updateRentContract.setStatus(EnumRentContractStatus.WAIT_SIGN.getCode());
            wxPropertyContractMapper.updateStatus(updateRentContract);
            logger.info("id:{},启动审批流成功",record.getId().toString());
        }
        return new ResultData(Result.SUCCESS, message, record);
    }

    @Override
    public ResultData updatePropertyContractStatus(Long id) {
        if (id == null) {
            return new ResultData(ErrorCode.SYS_PARAMETER_ERROR);
        }
        //更新合同状态为签约
        WxPropertyContract wxPropertyContract = new WxPropertyContract();
        wxPropertyContract.setId(id);
        wxPropertyContract.setStatus(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode());
        wxPropertyContractMapper.updateByPrimaryKeySelective(wxPropertyContract);
        //建立账单
        WxPropertyContract record = wxPropertyContractMapper.selectByPrimaryKey(id);
        if (record.getMerchantId() != null && record.getStatus().equals(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode())
                && record.getReceivePeriod() != null && record.getDeposit() > 0 && record.getPrice() > 0) {
            //WxBillProperty wxBillProperty = new WxBillProperty();
            //wxBillProperty.setMerchantId(record.getMerchantId());
            //List<Map<String, Object>> billPropertyList = wxBillPropertyMapper.queryBillPropertyList(wxBillProperty);
            //if (billPropertyList.size() == 0) {
                //预览账单改为正式,并写入商户id
                WxBillProperty billProperty = new WxBillProperty();
                billProperty.setPropertyContractId(id);
                billProperty.setIsPreview(EnumIsPreview.NO.getCode());
                billProperty.setMerchantId(record.getMerchantId());
                wxBillPropertyMapper.updatePreviewStatus(billProperty);

                WxMerchant wxMerchant = new WxMerchant();
                wxMerchant.setId(record.getMerchantId());
                wxMerchant.setTenantId(record.getTenantId());
                //物业账单
                //buildProperty(wxMerchant,null);
                //物业押金账单
                buildDeposit(wxMerchant,id);
            //}
        }
        return new ResultData(Result.SUCCESS, "操作成功");
    }

    @Transactional(rollbackFor = {Exception.class})
    public void buildDeposit(WxMerchant wxMerchant,Long propertyContractId) {
        WxPropertyContract wxPropertyContract = wxPropertyContractMapper.selectByPrimaryKey(propertyContractId);
        if (wxPropertyContract != null) {
            //找到计租方式
            int dayType = wxPropertyContract.getAdjustPeriod().equals(EnumRentContractAdjustPeriod.ADJUST_PERIOD_DAY.getCode()) ? Calendar.DAY_OF_MONTH : Calendar.MONTH;
            final IdWorker idWorker = IdWorker.get();
            WxBillPropertyDeposit wxBillDeposit = new WxBillPropertyDeposit();
            wxBillDeposit.setId(idWorker.nextId());
            wxBillDeposit.setPropertyContractId(wxPropertyContract.getId());
            wxBillDeposit.setPay(0);
            int needpay = wxPropertyContract.getDeposit();
            wxBillDeposit.setNeedPay(needpay);
            wxBillDeposit.setReceivePay(needpay);
            wxBillDeposit.setOwe(needpay);
            Date date = new Date();
            Calendar instance = Calendar.getInstance();
            instance.setTime(wxPropertyContract.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, wxPropertyContract.getLease());
            wxBillDeposit.setEndtime(instance.getTime());
            wxBillDeposit.setStatus(EnumBillRentStatus.WAIT_PAY.getCode());
            wxBillDeposit.setExpiredDay(0L);
            wxBillDeposit.setTenantId(wxMerchant.getTenantId());
            wxBillDeposit.setIsDel(0);
            wxBillDeposit.setMerchantId(wxMerchant.getId());
            wxBillDeposit.setShopId(wxPropertyContract.getShopId());
            wxBillDeposit.setCreatetime(date);
            wxBillDeposit.setUpdatetime(date);
            wxBillDeposit.setIsDel(EnumDelStatus.NOT_DEL.getCode());
            wxBillDeposit.setRentShopType(wxPropertyContract.getRentShopType());
            try {
                wxBillPropertyDepositMapper.insertSelective(wxBillDeposit);
            } catch (Exception e) {
                logger.error("添加物业押金账单失败,e:" + e.getMessage());
                throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
            }
        }
    }

    public List<WxBillProperty> buildRentMonth(WxMerchant wxMerchant, Long userId, WxPropertyContract wxPropertyContract, int receivePeriod, Integer lease, Date rentalStartDate, Integer price,Integer isPreview) {
        String adjustRatio = wxPropertyContract.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<WxBillProperty> 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, wxPropertyContract, userId, wxMerchant, billcount,isPreview);
            List<WxBillProperty> billRentList = (List<WxBillProperty>)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, WxPropertyContract wxPropertyContract, Long userId, WxMerchant wxMerchant, int billcount,Integer isPreview) {
        Map<String,Object> resultMap = new HashedMap();
        List<WxBillProperty> 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++) {
            WxBillProperty wxBillRent = new WxBillProperty();
            wxBillRent.setIsPreview(isPreview);

            wxBillRent.setId(idWorker.nextId());
            wxBillRent.setPropertyContractId(wxPropertyContract.getId());
            wxBillRent.setPay(0);
            int needpay = price * receivePeriod;

            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(wxPropertyContract.getShopId());
            wxBillRent.setCreatetime(date);
            wxBillRent.setUpdatetime(date);
            wxBillRent.setIsDel(EnumDelStatus.NOT_DEL.getCode());
            wxBillRent.setRentShopType(wxPropertyContract.getRentShopType());
            wxBillRent.setPeriod(++billcount);
            try {
                wxBillPropertyMapper.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;
    }

    /**
     * 根据商户/指定物业合同生成物业账单
     * @param wxMerchant
     * @param propertyContract
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public List<WxBillProperty> buildProperty(WxMerchant wxMerchant,Long userId,WxPropertyContract propertyContract,Integer isPreview) {
        List<WxBillProperty> result = new ArrayList<>();

        WxPropertyContract wxPropertyContract;
        if(propertyContract == null){
            //根据商户ID找出合同
            wxPropertyContract = new WxPropertyContract();
            wxPropertyContract.setMerchantId(wxMerchant.getId());
            List<WxPropertyContract> list = wxPropertyContractMapper.findList(wxPropertyContract);
            if (list.size() > 0) {
                wxPropertyContract = list.get(0);
            }
        }else{
            wxPropertyContract = propertyContract;
        }

        if (wxPropertyContract != null) {
            int receivePeriod = wxPropertyContract.getReceivePeriod().intValue();
            Integer lease = wxPropertyContract.getLease();
            Date rentalStartDate = propertyContract.getRentalStartDate();
            Integer price = propertyContract.getPrice();

            //按月计租
            if (propertyContract.getAdjustPeriod().equals(EnumRentContractAdjustPeriod.ADJUST_PERIOD_MONTH.getCode())) {
                result = buildRentMonth(wxMerchant, userId, propertyContract, receivePeriod, lease, rentalStartDate, price,isPreview);
            } else {
                //按日计租
                Map<String,Object> resultMap = buildRent(lease, receivePeriod, price, rentalStartDate, Calendar.DAY_OF_MONTH, propertyContract, userId, wxMerchant, 0,isPreview);
                result = (List<WxBillProperty>)resultMap.get("billList");
            }
        }
        for (int i = 0; i < result.size(); i++) {
            result.get(i).setPeriod(i+1);
        }
        return result;
    }


    @Override
    public void deleteById(Long id) {
        wxPropertyContractMapper.deleteByPrimaryKey(id);
    }


    @Override
    public void download(HttpServletRequest request, HttpServletResponse response, String tenantId) {
        String id = request.getParameter("id");
        WxPropertyContract wxPropertyContract = wxPropertyContractMapper.selectByPrimaryKey(id);

        String filesuffix = wxPropertyContract.getFilepath().substring(wxPropertyContract.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 = wxPropertyContract.getFilename();
            downLoadFromUrl(wxPropertyContract.getFilepath(), filename, filepath);
            downFile(destPath, wxPropertyContract.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(WxPropertyContract record) {

        Map<String, Object> resultData = new HashMap();
        //商铺信息
        WxShop wxShop = new WxShop();
        wxShop.setTenantId(record.getTenantId());
        wxShop.setType(record.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(record));
        return resultData;
    }

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

        WxPropertyContract wxPropertyContract = wxPropertyContractMapper.selectByPrimaryKey(id);
        if (wxPropertyContract == null) {
            return new ResultData(ErrorCode.PROPERTY_CONTRACT_IS_NOT_FOUND);
        }
        wxPropertyContract.setStatus(EnumRentContractStatus.CONTRACT_TERMINATE.getCode());
        try {
            wxPropertyContract.setUpdatetime(new Date());
            wxPropertyContractMapper.updateByPrimaryKeySelective(wxPropertyContract);
        } 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 Object getRentContractList(WxPropertyContract record) {
        Map<String, Object> params = new HashMap<>();
        params.put("tenantId", record.getTenantId());
        params.put("rentShopType", record.getRentShopType());
        List<WxRentContract> contractList = wxPropertyContractMapper.getRentContractList(params);
        return contractList;
    }

    @Override
    public ResultData endPropertyContractByRentContractId(Long rentContractId) {
        WxPropertyContract wxPropertyContractParam = new WxPropertyContract();
        wxPropertyContractParam.setRentContractId(rentContractId);
        List<Map<String, Object>> contractData = wxPropertyContractMapper.queryPropertyContractData(wxPropertyContractParam);
        if (contractData.size() == 0) {
            return new ResultData(ErrorCode.PROPERTY_CONTRACT_IS_NOT_FOUND);
        }
        Map<String, Object> contractMap = contractData.get(0);
        WxPropertyContract wxPropertyContract = wxPropertyContractMapper.selectByPrimaryKey(contractMap.get("id"));
        wxPropertyContract.setStatus(EnumRentContractStatus.CONTRACT_TERMINATE.getCode());
        try {
            wxPropertyContractMapper.updateByPrimaryKeySelective(wxPropertyContract);
        } 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 ResultData hasRentContract(Long rentContractId) {
        if (null == rentContractId) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL, "rentContractId不能为空");
        }

        WxRentContract wxRentContract = wxRentContractMapper.selectByPrimaryKey(rentContractId);
        if (wxRentContract != null) {
            WxPropertyContract wxPropertyContract = new WxPropertyContract();
            wxPropertyContract.setTenantId(wxRentContract.getTenantId());
            wxPropertyContract.setShopId(wxRentContract.getShopId());
            List<WxPropertyContract> select = wxPropertyContractMapper.select(wxPropertyContract);
            if (select.size() > 0) {
                long count = select.stream().filter(propertyContract -> propertyContract.getStatus().equals(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode()) ||
                        propertyContract.getStatus().equals(EnumRentContractStatus.RENT_PAID.getCode()) ||
                        propertyContract.getStatus().equals(EnumRentContractStatus.CONTRACT_END_SOON.getCode())).count();
                if (count > 0) {
                    return new ResultData(true);
                }
            }
        }
        return new ResultData(false);
    }

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

        int allCount = wxPropertyContractMapper.selectCount(wxPropertyContract);
        resultData.put("allCount", allCount);

        //作废合同
        wxPropertyContract.setStatus(EnumRentContractStatus.INVALID.getCode());
        wxPropertyContractMapper.updateRentInvalidStatus(wxPropertyContract);

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

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

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

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

        return resultData;
    }

    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();
        }
    }

}
