package cn.com.poc.formreport.aggregate.impl;


import cn.com.poc.common.constant.FormReportingConstant;
import cn.com.poc.common.service.BosConfigService;
import cn.com.poc.common.utils.DateUtils;
import cn.com.poc.formreport.FormReportRequest;
import cn.com.poc.formreport.aggregate.FormReportingService;
import cn.com.poc.formreport.strategy.AgentDataAnalyzeApiChannelFormReportStrategy;
import cn.com.poc.formreport.strategy.FormReportStrategy;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;

/**
 * @author Helen
 * @date 2021/12/20 10:00
 */
@Service
public class FormReportingServiceImpl implements FormReportingService {

    @Resource
    private BosConfigService bosConfigService;

    @Resource
    private AgentDataAnalyzeApiChannelFormReportStrategy agentDataAnalyzeApiChannelFormReportStrategy;


    @Override
    public String report(FormReportRequest reportRequest, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 数据校验
        String returnStr = null;
        Assert.notNull(reportRequest.getReportRequestType(), "请求类型不能为null！");
        if (reportRequest.getReportRequestType().equals(FormReportingConstant.REPORT_TYPE.API_CHANNEL_POINT_USAGE)) {
            // 执行报表导出
            doNormalReport(request, response, reportRequest, agentDataAnalyzeApiChannelFormReportStrategy);
        }
        return returnStr;
    }

    /**
     * 报表导出的抽象，只需要提供 FormReportStrategy的实现类就可以导出数据
     *
     * @param request
     * @param response
     * @param strategy
     * @throws Exception
     */
    public void doNormalReport(HttpServletRequest request, HttpServletResponse response, FormReportRequest reportRequest, FormReportStrategy strategy) throws Exception {
        // 设置响应体
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(strategy.getExcelName(reportRequest) + ".xls", "utf-8"));
        // 创建一个工作簿
        EasyExcel.write(response.getOutputStream(), strategy.getExcelEntityClass())
                .needHead(true) // excel表头
                .excelType(ExcelTypeEnum.XLS) // excel类型
                .registerWriteHandler(new AbstractColumnWidthStyleStrategy() {
                    @Override
                    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
                        // 设置列宽
                        Sheet sheet = writeSheetHolder.getSheet();
                        sheet.setColumnWidth(cell.getColumnIndex(), FormReportingConstant.EXCEL_CONFIG.COLUMN_WIDTH);
                    }
                }).sheet(strategy.getExcelName(reportRequest)).doWrite(strategy.getFormReportData(reportRequest));// 写数据
    }

    /**
     * 报表导出的抽象，只需要提供 FormReportStrategy的实现类就可以导出数据
     *
     * @param request
     * @param response
     * @param strategy
     * @throws Exception
     */
    public String doNormalReportAndUpload2Oss(HttpServletRequest request, HttpServletResponse response, FormReportRequest reportRequest, FormReportStrategy strategy, Boolean needHead) throws Exception {
        // 设置响应体
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(strategy.getExcelName(reportRequest) + ".xls", "utf-8"));
        // 创建一个工作簿

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        EasyExcel.write(byteArrayOutputStream, strategy.getExcelEntityClass())
                .needHead(needHead) // excel表头
                .excelType(ExcelTypeEnum.XLS) // excel类型
                .registerWriteHandler(new AbstractColumnWidthStyleStrategy() {
                    @Override
                    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
                        // 设置列宽
                        Sheet sheet = writeSheetHolder.getSheet();
                        sheet.setColumnWidth(cell.getColumnIndex(), FormReportingConstant.EXCEL_CONFIG.COLUMN_WIDTH);
                    }
                }).sheet(strategy.getExcelName(reportRequest)).doWrite(strategy.getFormReportData(reportRequest)); // 写数据
        byte[] buffer = byteArrayOutputStream.toByteArray();
        InputStream sbs = new ByteArrayInputStream(buffer);
        return bosConfigService.upload(sbs, getFileDownloadName(strategy.getExcelName(reportRequest), reportRequest.getQueryBeginScheduleDate()), "xls");
    }

    private String getFileDownloadName(String excelName, Date queryBeginScheduleDate) throws Exception {
        return excelName + "(" + DateUtils.formatDate(queryBeginScheduleDate, "yyyy-MM") + ")";
    }

    /**
     * 报表导出的抽象，只需要提供多个FormReportStrategy的实现类就可以根据FormReportStrategy分成多个Sheet导出数据
     *
     * @param request
     * @param response
     * @param strategy
     * @throws Exception
     */
    public void doNormalReports(HttpServletRequest request, HttpServletResponse response, FormReportRequest reportRequest, FormReportStrategy... strategy) throws Exception {
        // 设置响应体
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(strategy[0].getExcelName(reportRequest) + ".xls", "utf-8"));

        // 创建多个工作簿
        int i = 0;
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                .needHead(true)
                .registerWriteHandler(new AbstractColumnWidthStyleStrategy() {
                    @Override
                    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
                        // 设置列宽
                        Sheet sheet = writeSheetHolder.getSheet();
                        sheet.setColumnWidth(cell.getColumnIndex(), FormReportingConstant.EXCEL_CONFIG.COLUMN_WIDTH);
                    }
                }).build();
        try {
            for (FormReportStrategy formReportStrategy : strategy) {
                WriteSheet sheet = EasyExcel.writerSheet(i++, formReportStrategy.getExcelName(reportRequest)).head(formReportStrategy.getExcelEntityClass()).build();
                excelWriter.write(formReportStrategy.getFormReportData(reportRequest), sheet);
            }
        } finally {
            if (excelWriter != null) excelWriter.finish();
        }
    }
}


