package com.foreverwin.mesnac.common.aspect;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.foreverwin.mesnac.common.export.ColumnConvert;
import com.foreverwin.mesnac.common.model.ExportTemplate;
import com.foreverwin.mesnac.common.service.ExportTemplateService;
import com.foreverwin.mesnac.common.util.StringUtil;
import com.foreverwin.modular.core.exception.BusinessException;
import com.foreverwin.modular.core.util.CommonMethods;
import com.foreverwin.modular.core.util.FrontPage;
import com.foreverwin.modular.core.util.SpringUtil;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

@Aspect
@Configuration
public class ExportAspect {

    //切点表达式（*代表所有，第一个*表示返回类型为所有类型，第二个*表示包名，第三个*表示方法名）
    @Pointcut("execution(public * com.foreverwin.mesnac.*.controller..*(..))")
    public void export() {

    }

    @Around("export()")
    public Object doExport(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Enumeration<String> paramtes = request.getParameterNames();
        boolean export = false;
        String exportCode = "";
        //-------------------------------------------------------------------------------------------------------------------
        if (paramtes == null || args == null || args.length == 0) return joinPoint.proceed();
        Boolean isDuoDuo = (args != null && (args.length == 1 && args[0] != null && args[0].getClass() != String.class)) ? false : true;
        //-------------------------------------------------------------------------------------------------------------------
        request.setCharacterEncoding("UTF-8");
        //-------------------------------------------------------------------------------------------------------------------
        if (isDuoDuo) {
            while (paramtes.hasMoreElements()) {
                String param = paramtes.nextElement();
                String value = request.getParameter(param);
                if (param != null && param.equals("export")) export = true;
                if (param != null && param.equals("exportCode")) exportCode = value;

                if (export && StringUtil.notEmpty(exportCode)) break;
            }//while
        } else {
            Map<String, Object> paramMap = new HashMap<>();
            while (paramtes.hasMoreElements()) {
                String param = paramtes.nextElement();
                String value = request.getParameter(param);
                if (param != null && param.equals("export")) {
                    export = true;
                }
                if (param != null && param.equals("exportCode")) {
                    exportCode = value;
                }
                paramMap.put(param, value);
            }//while
            args[0] = paramMap;
        }
        //-------------------------------------------------------------------------------------------------------------------
        if (export == false || StringUtil.isEmpty(exportCode)) return joinPoint.proceed();
        //-------------------------------------------------------------------------------------------------------------------
        for (Object arg : args) {
            if (arg instanceof FrontPage) {
                ((FrontPage)arg).setRows(20000);
            }
        }//for
        //-------------------------------------------------------------------------------------------------------------------
        Object result = joinPoint.proceed(args);
        JSONObject resultJson = JSON.parseObject(JSON.toJSONStringWithDateFormat(result, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat));
        switch (exportCode) {
            case "SfcDispatch":
                resultJson = JSON.parseObject(JSON.toJSONString(result));
                break;
            default:
                break;
        }
        if (resultJson.get("data") instanceof List) {
            List dataList = (List)resultJson.get("data");
            exportData(exportCode, dataList, request, attributes.getResponse());
        }
        //-------------------------------------------------------------------------------------------------------------------

        return result;
    }

    private void exportData(String exportCode, List dataList, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String site = CommonMethods.getSite();
        Locale locale = LocaleContextHolder.getLocale();
        ExportTemplateService exportTemplateService = SpringUtil.getBean(ExportTemplateService.class);
        List<ExportTemplate> exportTemplateList = exportTemplateService.selectListBySiteCodeLanguage(site, exportCode, locale.getLanguage());
        if (exportTemplateList == null || exportTemplateList.size() == 0) throw BusinessException.build("common.export.noTemplate.error", site, exportCode);
        //-------------------------------------------------------------------------------------------------------------------------
        String fileName = getFileName(request, exportTemplateList.get(0).getFileName());
        //-------------------------------------------------------------------------------------------------------------------------
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet();
        sheet.setDefaultColumnWidth(20);
        HSSFRow row = sheet.createRow(0);
        //--------------------------------------------------------------------------------------------------------------------------
        HSSFCellStyle headerStyle = getHeaderStyle(workbook);// 获取列头样式对象
        //--------------------------------------------------------------------------------------------------------------------------
        for (int i = 0 ; i < exportTemplateList.size(); i++) {
            ExportTemplate header = exportTemplateList.get(i);
            HSSFCell cell = row.createCell(i);
            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
            HSSFRichTextString text = new HSSFRichTextString(header.getColumnLabel());
            cell.setCellValue(text);
            cell.setCellStyle(headerStyle); // 设置列头单元格样式
        }//for
        //--------------------------------------------------------------------------------------------------------------------------
        HSSFCellStyle rowStyle = getRowStyle(workbook);// 获取列头样式对象
        for (int rowNum = 0; rowNum < dataList.size(); rowNum++) {
            JSONObject item = JSON.parseObject(JSON.toJSONString(dataList.get(rowNum)));
            HSSFRow child = sheet.createRow(rowNum+1);
            for (int i = 0 ; i < exportTemplateList.size(); i++) {
                ExportTemplate header = exportTemplateList.get(i);
                String val = item.getString(header.getColumnName());
                //--------------------------------------------------------------------------------------------------------------------------
                if (!StrUtil.isBlank(header.getConvertClass())) {
                    try {
                        Object object = Class.forName(header.getConvertClass()).newInstance();
                        if (object instanceof ColumnConvert) {
                            val = ((ColumnConvert)object).convert(item, header.getColumnName(), val);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }//try
                //--------------------------------------------------------------------------------------------------------------------------
                HSSFCell cell = child.createCell(i);
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                HSSFRichTextString text = new HSSFRichTextString(val);
                cell.setCellValue(text);
                cell.setCellStyle(rowStyle);
            }
        }//for
        //--------------------------------------------------------------------------------------------------------------------------
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        response.flushBuffer();
        workbook.write(response.getOutputStream());
    }

    /*
     * 列头单元格样式
     */
    public static HSSFCellStyle getHeaderStyle(HSSFWorkbook workbook) {
        // 设置字体
        HSSFFont font = workbook.createFont();
        // 设置字体大小
        font.setFontHeightInPoints((short) 11);
        // 字体加粗
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        // 设置字体名字
        font.setFontName("Courier New");
        // 设置样式;
        HSSFCellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(HSSFColor.GREY_40_PERCENT.index);
        style.setFillPattern((short)1);
        // 设置底边框;
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        // 设置底边框颜色;
        style.setBottomBorderColor(HSSFColor.BLACK.index);
        // 设置左边框;
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        // 设置左边框颜色;
        style.setLeftBorderColor(HSSFColor.BLACK.index);
        // 设置右边框;
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        // 设置右边框颜色;
        style.setRightBorderColor(HSSFColor.BLACK.index);
        // 设置顶边框;
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        // 设置顶边框颜色;
        style.setTopBorderColor(HSSFColor.BLACK.index);
        // 在样式用应用设置的字体;
        style.setFont(font);
        // 设置自动换行;
        style.setWrapText(false);
        // 设置水平对齐的样式为居中对齐;
        style.setAlignment(HSSFCellStyle.ALIGN_LEFT);
        // 设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        //-----------------------------------------------------------------------------------------------------------
        return style;
    }

    public static HSSFCellStyle getRowStyle(HSSFWorkbook workbook) {
        // 设置字体
        HSSFFont font = workbook.createFont();
        // 设置字体大小
        // font.setFontHeightInPoints((short)10);
        // 字体加粗
        // font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        // 设置字体名字
        font.setFontName("Courier New");
        // 设置样式;
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置底边框;
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        // 设置底边框颜色;
        style.setBottomBorderColor(HSSFColor.BLACK.index);
        // 设置左边框;
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        // 设置左边框颜色;
        style.setLeftBorderColor(HSSFColor.BLACK.index);
        // 设置右边框;
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        // 设置右边框颜色;
        style.setRightBorderColor(HSSFColor.BLACK.index);
        // 设置顶边框;
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        // 设置顶边框颜色;
        style.setTopBorderColor(HSSFColor.BLACK.index);
        // 在样式用应用设置的字体;
        style.setFont(font);
        // 设置自动换行;
        style.setWrapText(false);
        // 设置水平对齐的样式为居中对齐;
        style.setAlignment(HSSFCellStyle.ALIGN_LEFT);
        // 设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

        HSSFDataFormat format = workbook.createDataFormat();
        style.setDataFormat(format.getFormat("@"));
        //-----------------------------------------------------------------------------------------------------------
        return style;
    }

    public String getFileName(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
    {
        String agent = request.getHeader("USER-AGENT");
        //-----------------------------------------------------------------------------------------------------------
        String filename = fileName;
        if (agent.contains("MSIE")) {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        } else if (agent.contains("Firefox")) {
            // 火狐浏览器
            filename = new String(fileName.getBytes(), "ISO8859-1");
        } else if (agent.contains("Chrome")) {
            // google浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        } else {
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }//if
        //-----------------------------------------------------------------------------------------------------------
        return filename;
    }
}
