package common.service.impl;


import common.model.DmpIncome;
import common.model.User;
import common.repository.ContractRepository;
import common.repository.DmpIncomeRepository;
import common.service.DmpIncomeService;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import util.ResultModel;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.Map;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class DmpIncomeServiceImpl implements DmpIncomeService {

    Logger logger = LoggerFactory.getLogger(DmpIncomeServiceImpl.class);

    @Autowired
    DmpIncomeRepository dmpIncomeRepository;

    @Autowired
    ContractRepository contractRepository;

    @Autowired
    @Qualifier("dataSource")
    DataSource dataSource;


    @Override
    public List<DmpIncome> listByCode(String contractCode) {
        List<DmpIncome> dmpIncomes = dmpIncomeRepository.findByContractCode(contractCode);
        return dmpIncomes;
    }

    @Override
    public List<DmpIncome> listByDs(String start, String end) {
        List<DmpIncome> dmpIncomes = dmpIncomeRepository.findByContractDs(start, end);
        List<String> codes = dmpIncomes.stream().map(v -> v.getContractCode()).collect(Collectors.toList());
        List<Object[]> contracts = contractRepository.findByDmpContractCode(codes);
        Map<String, Object[]> names = contracts.stream().collect(Collectors.toMap(v -> v[0] + "", v -> v, (v1, v2) -> v1));
        for (DmpIncome dmpIncome : dmpIncomes) {
            Object[] nameItem = names.get(dmpIncome.getCreateTime());
            //my_body_name, customer_body, customer_short, business_type, agreement_type
            if (nameItem != null) {
                dmpIncome.setMyBodyName(nameItem[1] + "");
                dmpIncome.setCustomerBody(nameItem[2] + "");
                dmpIncome.setCustomerShort(nameItem[3] + "");
                dmpIncome.setBusinessType(nameItem[4] + "");
                dmpIncome.setAgreementType(nameItem[5] + "");
            }
        }
        return dmpIncomes;
    }

    @Override
    public HSSFWorkbook exportIncomeList(String startDate, String endDate, String bodyCode, String serchName) {
        List<DmpIncome> dmpIncomes = this.listByDs(startDate, endDate);
        dmpIncomes = dmpIncomes.stream()
                .filter(v -> !StringUtils.isEmpty(bodyCode) && bodyCode.equals(v.getMyBodyName()))
                .filter(v -> StringUtils.isEmpty(serchName) && (v.getContractCode().contains(serchName) || v.getCustomerBody().contains(serchName)))
                .collect(Collectors.toList());

        DecimalFormat df = new DecimalFormat("##,##0.00");
        //创建工作薄对象
        HSSFWorkbook workbook = new HSSFWorkbook();//这里也可以设置sheet的Name
        //创建工作表对象
        HSSFSheet sheet = workbook.createSheet();
        //创建工作表的行
        HSSFRow row = sheet.createRow(0);

        //表头
        String[] title = "我方签约主体,收入月份,签约方,客户简称,合同编号,业务类型,结算周期,系统结算,按月结算,税率,确认收入".split(",");
        for (int i = 0; i < title.length; i++) {
            row.createCell(i).setCellValue(title[i]);
        }

        String[] bussinesName = new String[]{"", "VIP", "共管"};
        for (int j = 0; j < dmpIncomes.size(); j++) {
            HSSFRow rowBody = sheet.createRow(j + 1);
            DmpIncome income = dmpIncomes.get(j);
            String[] dataItem = new String[]{
                    income.getMyBodyName(), income.getIncomeMonth(), income.getCustomerBody(),
                    income.getCustomerShort(), income.getContractCode(), bussinesName[Integer.parseInt(income.getBusinessType())],
                    income.getPeriod(), income.getSysSettlement(), income.getMonthSettlement(),
                    income.getTaxRate(), income.getConfirmSettlement()
            };

            for (int w = 0; w < dataItem.length; w++) {
                rowBody.createCell(w).setCellValue(dataItem[w]);
            }
        }
        return workbook;
    }

    @Override
    public DmpIncome update(DmpIncome dmpIncome) {

        if (dmpIncome.getId() == null) {
            return null;
        }

        DmpIncome dbItem = dmpIncomeRepository.findOne(dmpIncome.getId());
        dbItem.setIncomeMonth(dmpIncome.getIncomeMonth());
        dbItem.setPeriod(dmpIncome.getPeriod());
        dbItem.setSysSettlement(dmpIncome.getSysSettlement());
        dbItem.setMonthSettlement(dmpIncome.getMonthSettlement());
        dbItem.setTaxRate(dmpIncome.getTaxRate());
        dbItem.setConfirmSettlement(dmpIncome.getConfirmSettlement());
        dmpIncomeRepository.save(dbItem);
        return dbItem;
    }

    @Override
    public Long delete(Long id) {
        if (id == null) {
            return null;
        }
        dmpIncomeRepository.delete(id);
        return id;
    }

    @Override
    public ResultModel uploadFile(MultipartFile file, String platform, User loginAccount) {
        InputStream stream = null;
        Workbook workbook = null;
        try {
            stream = file.getInputStream();
            workbook = WorkbookFactory.create(stream);
        } catch (Exception e) {
            logger.error("", e);
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    logger.error("", e);
                }
            }
        }

        if (workbook == null) {
            return ResultModel.ERROR("获取上传文件错误");
        }

        Sheet sheet = workbook.getSheetAt(0);
        Row row = sheet.getRow(0);

        String sheetTitle = "合同编号\t收入月份\t结算周期\t系统结算\t按月结算\t税率\t确认收入";
        int titleLength = sheetTitle.split("\t").length;
        StringBuffer titleUp = new StringBuffer();
        for (int i = 0; i < titleLength; i++) {
            if (i > 0) titleUp.append("\t");
            titleUp.append(row.getCell(i));
        }
        if (!titleUp.toString().equals(sheetTitle)) {
            return ResultModel.ERROR("模板表头错误");
        }

        int rowNumber = sheet.getLastRowNum();
        if (rowNumber <= 1) {
            return ResultModel.ERROR("文件为空");
        }

        CompletableFuture.runAsync(() -> {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            ExecutorService executorService = Executors.newFixedThreadPool(30);
            CompletableFuture[] futures = Stream.iterate(1, n -> n + 1).limit(rowNumber - 1).map(index ->
                    CompletableFuture.runAsync(
                            () -> saveDmpIncomeItem(sheet, index, loginAccount), executorService)
                            .exceptionally((t) -> null)
            ).toArray(size -> new CompletableFuture[size]);
            CompletableFuture.allOf(futures).join();
            executorService.shutdownNow();
            stopWatch.stop();
            logger.info("dmp income upload {} line data  use all {}s ", rowNumber - 1, stopWatch.getTotalTimeSeconds());
        });

        return ResultModel.OK();
    }

    private DmpIncome saveDmpIncomeItem(Sheet sheet, int index, User user) {
        //logger.info(" line index {}", index);
        Row rowItem = sheet.getRow(index);
        //合同编号	收入月份	结算周期	系统结算	按月结算	税率	确认收入
        DmpIncome income = new DmpIncome();
        income.setContractCode(getCellStringValue(rowItem, 0));
        income.setIncomeMonth(getCellStringValue(rowItem, 1));
        income.setPeriod(getCellStringValue(rowItem, 2));
        income.setSysSettlement(getCellStringValue(rowItem, 3));
        income.setMonthSettlement(getCellStringValue(rowItem, 4));
        income.setTaxRate(getCellStringValue(rowItem, 5));
        income.setConfirmSettlement(getCellStringValue(rowItem, 6));
        // 时间 上传人
        income.setCreateTime(new Date());
        income.setUploadUser(user.getName());
        if (StringUtils.isEmpty(income.getContractCode())) {
            return null;
        }

        DmpIncome one = dmpIncomeRepository.findByCodeMonth(income.getContractCode(), income.getIncomeMonth());
        if (one != null) {
            // 同一合同同一月份不重复保存
            return null;
        }
        dmpIncomeRepository.save(income);
        return income;

    }

    private String getCellStringValue(Row row, int index) {
        Cell cell = row.getCell(index);
        return cell == null ? "" : cell.toString();
    }


}
