package com.community.huiju.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.community.commom.constant.Constant;
import com.community.commom.mode.ResponseBean;
import com.community.commom.session.UserElement;
import com.community.commom.utils.DateUtils;
import com.community.commom.utils.PayPriceUtils;
import com.community.huiju.dao.*;
import com.community.huiju.exception.WisdomException;
import com.community.huiju.model.*;
import com.community.huiju.service.IBillInvoiceService;
import com.community.huiju.service.IBillService;
import com.community.huiju.service.IBuildingOwnerInfoService;
import com.community.huiju.service.IMessageService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.zxing.common.detector.MathUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * 缴费项表 服务实现类
 * </p>
 *
 * @author weiximei
 * @since 2019-02-13
 */
@Service
@Slf4j
public class BillServiceImpl extends ServiceImpl<BillMapper, Bill> implements IBillService {

    /** 金额 /^\d+$/ **/
    private Pattern pattern = Pattern.compile("/(^[1-9]([0-9]+)?(\\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\\.[0-9]([0-9])?$)/");

    /** 缴费项表 **/
    @Autowired
    private BillMapper billMapper;

    /** 缴费单 **/
    @Autowired
    private BillInvoiceMapper billInvoiceMapper;

    @Autowired
    private IBillInvoiceService iBillInvoiceService;

    /** 账单流水表 **/
    @Autowired
    private BillStatementMapper billStatementMapper;

    @Autowired
    private TpBuildingOwnerInfoMapper tpBuildingOwnerInfoMapper;

    @Autowired
    private TaUserMapper taUserMapper;

    @Autowired
    private IBuildingOwnerInfoService iBuildingOwnerInfoService;

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private IMessageService iMessageService;

    @Autowired
    private TaUserVerifyMapper taUserVerifyMapper;

    @Autowired
    private TpRoomNoMapper tpRoomNoMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean updateBillNameAndBillExplainAndEndDate(UserElement userElement, String parameter) {
        ResponseBean responseBean = new ResponseBean();
        Bill bill = JSONObject.parseObject(parameter, Bill.class);
        if (StringUtils.isEmpty(bill.getBillName())) {
            responseBean.addError("收费项名称不能为空");
            return responseBean;
        }
        if (StringUtils.isEmpty(bill.getBillExplain())) {
            responseBean.addError("缴费项说明");
            return responseBean;
        }
        if (bill.getEndDate() == null) {
            responseBean.addError("截止时间不能为空");
            return responseBean;
        }

        Bill selectBill = billMapper.selectById(bill.getId());
        if (selectBill == null) {
            responseBean.addError("缴费项不存在");
            return responseBean;
        }

        billMapper.updateById(bill);
        responseBean.addSuccess("操作成功");
        return responseBean;
    }

    @Override
    public ResponseBean getByBillId(Integer id) {
        ResponseBean responseBean = new ResponseBean();
        Bill bill = billMapper.selectById(id);
        responseBean.addSuccess(bill);
        return responseBean;
    }
    
    /**
     * 获取收费项列表
     *
     * @param bill
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public ResponseBean getBillList(Bill bill, Integer pageNum, Integer pageSize) {
        ResponseBean responseBean = new ResponseBean();
        Page page = new Page(pageNum,pageSize);
        // 分页查询
        List<Bill> list = billMapper.selectListByParams(page,bill);
        Map<String, Object> map = Maps.newHashMap();
        map.put("list",list);
        map.put("total",page.getTotal());
        responseBean.addSuccess(map);
        return responseBean;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean getExcelData(MultipartFile file) {
        ResponseBean responseBean = new ResponseBean();
        if (file == null) {
            responseBean.addError("对象不能为空");
            return responseBean;
        }

        responseBean = getExcelData(file, responseBean);
        List<TempBill> tempBills = (List<TempBill>) responseBean.getData();

        Map<String, Object> map = Maps.newHashMap();
        map.put("list", tempBills);
        map.put("total", tempBills.size());
        responseBean.addSuccess(map);

        return responseBean;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean getExcelData(Integer billId, MultipartFile file, String billExplain, String billName, Date endDate, String billStatus, UserElement userElement) {
        ResponseBean responseBean = new ResponseBean();

        // 获取本地时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String formatDate = simpleDateFormat.format(date);
        Date parse = null;
        try {
            parse = simpleDateFormat.parse(formatDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        if (endDate.getTime() < parse.getTime()) {
            responseBean.addError("不能小于当前时间!");
            return responseBean;
        }


        List<BillInvoice> records = null;
        if (billId != null) {
            // 查询出这个收费单, 存在的缴费单数据
            QueryWrapper<BillInvoice> billInvoiceQueryWrapper = new QueryWrapper<>();
            billInvoiceQueryWrapper.eq("bill_id", billId);
            billInvoiceQueryWrapper.eq("community_id", userElement.getCommunityId());
            records = billInvoiceMapper.selectList(billInvoiceQueryWrapper);
        }

        // 如果没有携带 excel 文件, 并且这个收费组里面也没有收费单, 那么就提示 发送账单失败，需要先上传账单excel
        if (null == file && "0".equals(billStatus) && (null == records ||records.size() == 0)) {
            responseBean.addError("发送账单失败，需要先上传账单excel");
            return responseBean;
        }

        responseBean = getExcelData(file, responseBean);
        List<TempBill> tempBills = (List<TempBill>) responseBean.getData();

        Double sumDouble = 0.0;
        String strSumDouble = sumDouble + "";
        // 如果 List 有数据, 表示携带了文件上传, 那么就从excel文件里面读取金额
        if (tempBills.size() > 0) {
            sumDouble = tempBills.stream().mapToDouble(TempBill::getPayPrice).sum();
            strSumDouble = sumDouble + "";
        }
        // 如果 List 没有数据, records 有数据, 就表示用户做的修改操作 并且没有上传文件, 那么这里的金额应该从数据库读取
        if (tempBills.size() == 0 && records != null) {
            sumDouble = records.stream().mapToDouble(BillInvoice::getPayPrice).sum();
            strSumDouble = sumDouble + "";
        }

        // 存入缴费项表
        Bill bill = new Bill();
        bill.setBillName(billName);
        bill.setBillExplain(billExplain);
        bill.setEndDate(endDate);
        if (StringUtils.isNotBlank(strSumDouble)) {
            strSumDouble = strSumDouble.substring(0, strSumDouble.lastIndexOf("."));
            bill.setPayPrice(strSumDouble);
        }

        bill.setPayedNum(0);
        bill.setBillStatus(billStatus);
        //为草稿时不创建时间, 2表示草稿
        if(!"2".equals(billStatus)) {
            bill.setCreateDate(new Date());
            bill.setCreateUser(userElement.getId());
        }
        bill.setCommunityId(userElement.getCommunityId());
        Integer payTotalNum = tempBills.size() != 0 ? tempBills.size() : records != null ? records.size() : 0;
        Integer unpayedNum = tempBills.size() != 0 ? tempBills.size() : records != null ? records.size() : 0;
        bill.setPayTotalNum(payTotalNum);
        bill.setUnpayedNum(unpayedNum);

        if (file != null) {
            // 删除掉旧数据
            QueryWrapper<BillInvoice> billInvoiceQuery = new QueryWrapper<>();
            billInvoiceQuery.eq("bill_id", billId);
            billInvoiceMapper.delete(billInvoiceQuery);
        }

        if (billId != null) {
            bill.setCreateUser(null);
            bill.setCreateDate(null);
            if(!"2".equals(billStatus)) {
                bill.setCreateDate(new Date());
                bill.setCreateUser(userElement.getId());
            }
            // 设置主键, 表示修改
            bill.setId(billId);
        }

        // int rows = billMapper.insert(bill);
        boolean b = this.saveOrUpdate(bill);
        if (b) {
            // 草稿时插入消息
            if ("2".equals(bill.getBillStatus())) {
                Message message = new Message();
                message.setCommunityId(userElement.getCommunityId());
                message.setMessageType("7");
                message.setAdviceType("4");
                message.setModelType("2");
                message.setUuid(userElement.getId());
                message.setUuidType("2");
                // 消息是物业端发过来的, 就是 2
                message.setSource("2");
                message.setMessageContent("收费组“" + bill.getBillName() +  "”还未发布，点击发布");
                message.setStatus("1");
                message.setCreateDate(LocalDateTime.now());
                message.setCreateUser(userElement.getId());
                message.setBillId(bill.getId());

                messageMapper.insert(message);

            }
            // 发布时消息为无效
            if ("0".equals(bill.getBillStatus())) {
                QueryWrapper<Message> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("community_id", userElement.getCommunityId());
                queryWrapper.eq("message_type", "7");
                queryWrapper.eq("model_type", "2");
                queryWrapper.eq("source", "2");
                queryWrapper.eq("status", "1");
                queryWrapper.eq("advice_type","4");
                Message message = messageMapper.selectOne(queryWrapper);
                if (null != message) {
                    message.setStatus("0");
                    message.setUpdateDate(LocalDateTime.now());
                    message.setUpdateUser(userElement.getId());
                    messageMapper.updateById(message);
                }


                // 插入消息表, 消息类型为 消息
                Message messageModel = new Message();
                messageModel.setCommunityId(userElement.getCommunityId());
                messageModel.setMessageType("7");
                messageModel.setAdviceType("4");
                messageModel.setModelType("1");
                messageModel.setUuid(userElement.getId());
                messageModel.setUuidType("2");
                // 消息是物业端发过来的, 就是 2
                messageModel.setSource("2");

                messageModel.setMessageContent("收费组“" + bill.getBillName() + "”还有" + DateUtils.getDaysBetween(new Date(), bill.getEndDate()) + "天就到截止日期了，但还有未缴用户，点击去查看");
                messageModel.setStatus("1");
                messageModel.setCreateDate(LocalDateTime.now());
                messageModel.setCreateUser(userElement.getId());
                messageModel.setBillId(bill.getId());

                messageMapper.insert(messageModel);


            }
            List<BillInvoice> billInvoices = tempBills.stream().map(e -> {
                BillInvoice billInvoice = new BillInvoice();
                billInvoice.setCommunityId(userElement.getCommunityId());
                billInvoice.setBillId(bill.getId());

                /**
                 * 查询房号
                 */
                TpRoomNo tpRoomNo = tpRoomNoMapper.selectCommunityIdAndAddressName(userElement.getCommunityId(), e.getPhase(), e.getBuilding(), e.getUnit(), e.getLevel(), e.getRoomNo());
                if (null == tpRoomNo) {
                    throw new WisdomException("房产：" + e.getPhase() + e.getBuilding() + e.getUnit() + e.getLevel() + e.getRoomNo() + " 不存在！请核对！");
                }
                billInvoice.setRoomNoId(tpRoomNo.getId());
                billInvoice.setBillInvoiceExplain(e.getBillExplain());
                billInvoice.setPayPrice(e.getPayPrice());
                billInvoice.setBillStatus("0");
                billInvoice.setCreateUser(userElement.getId());
                billInvoice.setCreateDate(new Date());
                billInvoice.setStatus(1);

                return billInvoice;
            }).collect(Collectors.toList());

            boolean batchBool = iBillInvoiceService.saveBatch(billInvoices);
            if (batchBool) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm");
                // 发布时, 往 APP端推送
                if ("0".equals(bill.getBillStatus())) {
                    List<Message> messageList = billInvoices.stream().map(e -> {

                        // 往APP端用户上面的每一个用户推送
                        Message messageModelAPP = new Message();
                        messageModelAPP.setCommunityId(userElement.getCommunityId());
                        messageModelAPP.setMessageType("7");
                        messageModelAPP.setAdviceType("1");
                        messageModelAPP.setModelType("2");
                        messageModelAPP.setUuid(e.getTaUserId());
                        messageModelAPP.setUuidType("1");
                        // 消息是物业端 发过来的, 就是 2
                        messageModelAPP.setSource("2");
                        messageModelAPP.setMessageContent("您有待缴费的账单，点击查看并缴费 " + dateFormat.format(new Date()) + bill.getBillName());
                        messageModelAPP.setStatus("1");
                        messageModelAPP.setCreateDate(LocalDateTime.now());
                        messageModelAPP.setCreateUser(userElement.getId());
                        messageModelAPP.setBillId(e.getId());

                        return messageModelAPP;

                    }).collect(Collectors.toList());
                    iMessageService.saveBatch(messageList);
                }

            }
        }
        responseBean.addSuccess("操作成功!");
        return responseBean;
    }

    private ResponseBean getExcelData(MultipartFile file, ResponseBean responseBean) {

        // 数据
        List<TempBill> tempBills = Lists.newArrayList();
        if (null == file) {
            responseBean.addSuccess(tempBills);
            return responseBean;
        }

        //获取文件的名字
        String originalFilename = file.getOriginalFilename();
        Workbook workbook = null;
        try {
            if (originalFilename.endsWith(Constant.SUFFIX_2003)) {
                workbook = new HSSFWorkbook(file.getInputStream());
            } else if (originalFilename.endsWith(Constant.SUFFIX_2007)) {
                workbook = new XSSFWorkbook(file.getInputStream());
            }
        } catch (Exception e) {
            log.info(originalFilename);
            e.printStackTrace();
            responseBean.addError("格式错误");
            return responseBean;
        }

        // 获取 Sheet 第一页
        Sheet sheetAt = workbook.getSheetAt(0);
        int lastRowNum = sheetAt.getLastRowNum();

        // 从第7行开始读取
        for (int i= 6; i<= lastRowNum; i++) {
            int currentRow = i + 1;
            Row row = sheetAt.getRow(i);
            Cell cell = getCell(row.getCell(0));
            if (null == cell) {
                throw new WisdomException("第" + currentRow + "行 期/区 不能为空");
            }
            String phase = cell.getStringCellValue().trim();
            cell = getCell(row.getCell(1));
            if (null == cell) {
                throw new WisdomException("第" + currentRow + "行 楼栋 不能为空");
            }
            String building = cell.getStringCellValue().trim();
            cell = getCell(row.getCell(2));
            if (null == cell) {
                throw new WisdomException("第" + currentRow + "行 单元 不能为空");
            }
            String unit = cell.getStringCellValue().trim();
            cell = getCell(row.getCell(3));
            if (null == cell) {
                throw new WisdomException("第" + currentRow + "行 楼层 不能为空");
            }
            String level = cell.getStringCellValue().trim();
            cell = getCell(row.getCell(4));
            if (null == cell) {
                throw new WisdomException("第" + currentRow + "行 房号 不能为空");
            }
            String roomNo = cell.getStringCellValue().trim();


            // 收费说明可以为空
            cell = getCell(row.getCell(5));
            String billExplain = null;
            if (null != cell) {
                billExplain = cell.getStringCellValue().trim();
                if (billExplain.length() > 100) {
                    throw new WisdomException("第" + currentRow + "行 收费说明超出100字，请精简到100字以内");
                }
            }

            cell = getCell(row.getCell(6));
            if (null == cell) {
                throw new WisdomException("第" + currentRow + "行 金额 不能为空");
            }
            String money = cell.getStringCellValue().trim();


            TempBill temp = new TempBill();
            temp.setPhase(phase);
            temp.setBuilding(building);
            temp.setLevel(level);
            temp.setUnit(unit);
            temp.setRoomNo(roomNo);
            // temp.setOwnerName(ownerName);
            temp.setBillExplain(billExplain);


            if (StringUtils.isNotBlank(money)) {
                Double moneyDouble = Double.valueOf(money) * 100;
                money = moneyDouble + "";
                money = money.substring(0, money.lastIndexOf("."));
                temp.setPayPrice(Integer.valueOf(money));
//                Matcher matcher = pattern.matcher(money);
//                if (matcher.find()) {
//                    temp.setMoney(PayPriceUtils.yuanConversionPoints(Double.valueOf(money)*100));
//                } else {
//                    throw new WisdomException("第" + i + "行 金额 格式不合法");
//                }
//                else {
//                    throw new WisdomException("第" + i + "行 金额 格式不合法");
//                }
            }

            tempBills.add(temp);
        }

        responseBean.addSuccess(tempBills);
        return responseBean;
    }

    @Override
    public ResponseBean updateBillStatus(UserElement userElement, Integer billStatus, Integer id) {
        ResponseBean responseBean = new ResponseBean();
        Bill bill = billMapper.selectById(id);
        if (null == bill) {
            responseBean.addError("数据不存在!");
            return responseBean;
        }
        bill.setBillStatus(billStatus + "");
        billMapper.updateById(bill);
        responseBean.addSuccess("操作成功!");
        return responseBean;
    }

    @Override
    public ResponseBean deleteBillBeach(UserElement userElement, List<Integer> ids) {
        ResponseBean responseBean = new ResponseBean();
        ids.forEach(e -> {
            Bill bill = billMapper.selectById(e);
            Integer payedNum = bill.getPayedNum();
            if (payedNum > 0) {
                throw new WisdomException("项目已经有人缴费了，无法删除");
            }
            billMapper.deleteById(bill);
            QueryWrapper<BillInvoice> deleteQueryWrapper = new QueryWrapper<>();
            deleteQueryWrapper.eq("bill_id", bill.getId());
            billInvoiceMapper.delete(deleteQueryWrapper);

            // 发布时消息为无效
            QueryWrapper<Message> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("community_id", userElement.getCommunityId());
            queryWrapper.eq("message_type", "7");
            queryWrapper.eq("model_type", "2");
            queryWrapper.eq("source", "2");
            queryWrapper.eq("source", "2");
            queryWrapper.eq("uuid_type", "1");

            List<Message> messages = messageMapper.selectList(queryWrapper);
            messages.forEach(message-> {
                message.setStatus("0");
                message.setUpdateDate(LocalDateTime.now());
                message.setUpdateUser(userElement.getId());
                messageMapper.updateById(message);
            });

        });

        responseBean.addSuccess("操作成功!");
        return responseBean;
    }

    private Cell getCell(Cell ce){
        Cell cell = ce;
        if (null == cell) {
            return null;
        }
        //把数字当成String来读，避免出现1读成1.0的情况
        if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
            cell.setCellType(Cell.CELL_TYPE_STRING);
        }

        return cell;
    }

    @Data
    private class TempBill {
        // 期 / 区
        private String phase;
        // 栋
        private String building;
        // 单元
        private String unit;
        // 楼层
        private String level;
        // 户号
        private String roomNo;
        // 业主姓名
        private String ownerName;
        // 金额
        private Integer payPrice;

        // 收费说明
        private String billExplain;
    }

    @Override
    public ResponseBean downloadExcel(UserElement userElement) {
        ResponseBean responseBean = new ResponseBean();

        InputStream inputStream = null;
        inputStream = this.getClass().getResourceAsStream("/缴费单模板.xls");

        HSSFWorkbook workbook = null;
        try {
            workbook = new HSSFWorkbook(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        HSSFSheet sheet = workbook.getSheetAt(0);
        // 创建行
        HSSFRow row = null;
        // 创建列
        HSSFCell cell = null;

        Integer pageNum = 0;
        Integer pageSize = 10;
        // 分页查询

        List<TpRoomNo> records = tpRoomNoMapper.selectCommunityIdList(userElement.getCommunityId(), pageNum * pageSize, pageSize);
        // 总页数
        Long pages = tpRoomNoMapper.selectCommunityIdCount(userElement.getCommunityId());


        // 行数 默认从 第 6 行开始
        int currentRow = 6;
        // 记录坐标
        int index = 0;

        if (records.size() > 0) {
            do {
                TpRoomNo tpRoomNo = records.get(index);
                row = sheet.createRow(currentRow);
                cell = row.createCell(0);
                cell.setCellValue(tpRoomNo.getPhaseName());
                cell = row.createCell(1);
                cell.setCellValue(tpRoomNo.getBuildingName());
                cell = row.createCell(2);
                cell.setCellValue(tpRoomNo.getUnitName());
                cell = row.createCell(3);
                cell.setCellValue(tpRoomNo.getLevelName());
                cell = row.createCell(4);
                cell.setCellValue(tpRoomNo.getName());
                currentRow ++;
                index ++;
                if (index == records.size()) {
                    index = 0;
                    pageNum ++;
                    records = tpRoomNoMapper.selectCommunityIdList(userElement.getCommunityId(), pageNum * pageSize, pageSize);
                }
                if (records.isEmpty()) {
                    break;
                }
            } while (pageNum <= pages);
        }

        responseBean.addSuccess(workbook);
        return responseBean;
    }

    private void setExcelData(String [][] data, HSSFSheet sheet, HSSFRow row, HSSFCell cell){
        int crrentRow = 5;
        // 行数
        for (int i = 0; i < data.length; i++) {
            row = sheet.createRow(i + crrentRow);
            for (int t = 0; t < data[i].length; t++) {
                cell = row.createCell(t);
                cell.setCellValue(data[i][t]);
            }
        }
    }

}
