package com.artfess.sysConfig.aspect;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.artfess.base.constants.SystemConstants;
import com.artfess.base.exception.ApplicationException;
import com.artfess.base.exception.BaseException;
import com.artfess.base.id.IdGenerator;
import com.artfess.base.model.CommonResult;
import com.artfess.base.query.PageList;
import com.artfess.base.util.AppUtil;
import com.artfess.base.util.AuthenticationUtil;
import com.artfess.base.util.StringUtil;
import com.artfess.poi.reader.TableHeaderDef;
import com.artfess.poi.util.ExcelUtil;
import com.artfess.sysConfig.model.ExcelTemp;
import com.artfess.sysConfig.model.ExcelTempFields;
import com.artfess.sysConfig.persistence.manager.ExcelTempManager;
import com.artfess.sysConfig.vo.ExcelTempVo;
import com.artfess.uc.api.impl.util.ContextUtil;
import com.artfess.uc.api.model.IUser;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.sql.Types;
import java.util.*;

/**
 * @Description:
 * @Author: wh

 */
@Aspect
@Component
@Slf4j
public class ExportAspect {

    @Resource
    ExcelTempManager excelTempManager;

    // 定义切点Pointcut
    //@Pointcut("execution(public * com.sysplat.sys.modules.*.*Controller.*(..))")
    @Pointcut("execution(public * com.artfess..*.*Controller.*(..))")
    public void excudeService() {
    }

    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

        //生成excel文件
        //String file=getCreateExcel(result,templateName);
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        String export=request.getParameter("export");

        Object result = pjp.proceed();
        if("export".equals(export)) {
            long start=System.currentTimeMillis();
            //导出
            this.parseText(result,response,request);
            long end=System.currentTimeMillis();
            log.debug("封装excel数据  耗时"+(end-start)+"ms");
            //下载模板
        }else if("template".equals(export)){
            this.parseTemplate(result,response,request);
        }else if("import".equals(export)){
            this.parseImport(pjp,response,request);
        }
        return result;
    }

    private void parseTemplate(Object result,HttpServletResponse response,HttpServletRequest request) {
        String tempId=request.getParameter("tempId");
        if(tempId.isEmpty()){
            throw new BaseException("模板ID不能为空");
        }
        ExcelTempVo vo=excelTempManager.getExcelTempByCode(tempId,2);
        if(null==vo){
            throw new BaseException("模板参数错误");
        }
        List dataList = new ArrayList<>();
        ExcelTemp temp=vo.getExcelTemp();

        String fileName = temp.getTempFiles();
        List<ExcelTempFields> fields=vo.getFields();

        List<TableHeaderDef> headerDefList = new ArrayList<>();
        TableHeaderDef def = null;
        for (ExcelTempFields field : fields) {
            def = new TableHeaderDef();
            def.setKey(field.getFieldName());
            def.setName(field.getFieldComments());
            def.setComment(field.getFieldComments());
            headerDefList.add(def);
        }

        try {
            HSSFWorkbook book = ExcelUtil.exportExcel("sheet1", 28, headerDefList, dataList);
            ExcelUtil.saveExcel(book, fileName, SystemConstants.TEMP_DATA_EXCEL);
//            ExcelUtil.downloadExcel(book, fileName, response);
            String file = SystemConstants.TEMP_DATA_EXCEL + File.separator + fileName + ".xls";
            InputStream is = new FileInputStream(new File(file));

            int len = 0;
            byte[] buffer = new byte[1024];
            OutputStream out = response.getOutputStream();
            //response.reset();
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + new String(file.getBytes(), "iso-8859-1"));
            response.setContentType("application/octet-stream");
            while ((len = is.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
            is.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void parseText(Object result,HttpServletResponse response,HttpServletRequest request) {
        IdGenerator id = new IdGenerator(0,1);
        String tempId=request.getParameter("tempId");
        if(tempId.isEmpty()){
            throw new BaseException("模板ID不能为空");
        }
        //1：导出  2：导入
        ExcelTempVo vo=excelTempManager.getExcelTempByCode(tempId,1);
        if(null==vo){
            throw new BaseException("模板参数错误");
        }

        ExcelTemp temp=vo.getExcelTemp();
        Integer type=temp.getType();
        List<ExcelTempFields> fields=vo.getFields();

        //导出
        if(type == 1) {

            List dataList = new ArrayList<>();
        /*if (result instanceof CommonResult) {
            Object object=((CommonResult) result).getValue();
            if (object instanceof IPage) {
                dataList=((IPage) ((CommonResult) result).getValue()).getRecords();
            }else if(object instanceof ArrayList){
                dataList= (List) object;
            }
        }else*/
            //分页列表
            if (result instanceof PageList) {
                //返回的是List<Map<String,Object>>
                ObjectMapper mapper = new ObjectMapper();
                String json = "{}";
                try {
                    //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
                    json = mapper.writeValueAsString(((PageList) result).getRows());
                } catch (JsonProcessingException e) {
                    log.error("json解析失败" + e.getMessage(), e);
                }

                JSONArray array = JSONArray.parseArray(json);
                arr:for (int i=0;i<array.size();i++) {
                    try {
                        JSONObject item = array.getJSONObject(i);
                        Map<String,Object> objectList=new HashMap<>();
                        for (ExcelTempFields key : fields) {
                            String fileName=key.getFieldName();
                            String value = item.getString(underlineToHump(fileName));
                            //处理字典json
                            String jsonStr = key.getFieldDataJson();
                            if(!StringUtils.isEmpty(jsonStr)){
                                objectList.put(key.getFieldComments(),translateDictValue(jsonStr,value));
                            }else {
                                objectList.put(key.getFieldComments(),value);
                            }
                        }
                        dataList.add(objectList);
                    }catch (Exception e){}

                }

                //dataList = (List) array;
                //不分页列表
            } else if (result instanceof ArrayList) {
                //返回的是List<Map<String,Object>>
                ObjectMapper mapper = new ObjectMapper();
                String json = "{}";
                try {
                    //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
                    json = mapper.writeValueAsString(result);
                } catch (JsonProcessingException e) {
                    log.error("json解析失败" + e.getMessage(), e);
                }

                JSONArray array = JSONArray.parseArray(json);
                arr:for (int i=0;i<array.size();i++) {
                    try {
                        JSONObject item = array.getJSONObject(i);
                        Map<String,Object> objectList=new HashMap<>();
                        for (ExcelTempFields key : fields) {
                            String fileName=key.getFieldName();
                            String value = item.getString(underlineToHump(fileName));
                            //处理字典json
                            String jsonStr = key.getFieldDataJson();
                            if(!StringUtils.isEmpty(jsonStr)){
                                objectList.put(key.getFieldComments(),translateDictValue(jsonStr,value));
                            }else {
                                objectList.put(key.getFieldComments(),value);
                            }
                        }
                        dataList.add(objectList);
                    }catch (Exception e){
                        e.printStackTrace();
                    }

                }
                //dataList = (List) array;
            }
            //ExcelUtil.writeBySimple("D:/321.xlsx",dataList,Arrays.asList("姓名","年级"));
//        HSSFWorkbook book = ExcelUtil.exportExcel(queryView.getName(), 24, exportMaps, pageList.getRows());
//        ExcelUtil.downloadExcel(book, queryView.getName(), response);

            String fileName = vo.getExcelTemp().getTempFiles();

            List<TableHeaderDef> headerDefList = new ArrayList<>();
            TableHeaderDef def = null;
            for (ExcelTempFields field : fields) {
                def = new TableHeaderDef();
                def.setKey(field.getFieldComments());
                def.setName(field.getFieldComments());
                def.setComment(field.getFieldComments());
                headerDefList.add(def);
            }

            try {
                HSSFWorkbook book = ExcelUtil.exportExcel("sheet1", 28, headerDefList, dataList);
                ExcelUtil.saveExcel(book, fileName, SystemConstants.TEMP_DATA_EXCEL);
//            ExcelUtil.downloadExcel(book, fileName, response);
                String file = SystemConstants.TEMP_DATA_EXCEL + File.separator + fileName + ".xls";
                InputStream is = new FileInputStream(new File(file));

                int len = 0;
                byte[] buffer = new byte[1024];
                OutputStream out = response.getOutputStream();
                //response.reset();
                response.addHeader("Content-Disposition",
                        "attachment;filename=" + new String(file.getBytes(), "iso-8859-1"));
                response.setContentType("application/octet-stream");
                while ((len = is.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
                is.close();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void parseImport(ProceedingJoinPoint pjp,HttpServletResponse response,HttpServletRequest request) {

        //用户iD
        String userId=AuthenticationUtil.getCurrentUserId();

        //获取当前用户的账号信息
        String userName=AuthenticationUtil.getCurrentUsername();
        //获取当前用户所有组织
        String orgId=AuthenticationUtil.getCurrentUserOrgIds();
        //获取当前用户的主组织
        String mainOrgId=AuthenticationUtil.getCurrentUserMainOrgId();


        IUser currentUser = ContextUtil.getCurrentUser();
        //租户ID
        String tenantId=currentUser.getTenantId();

        IdGenerator id = new IdGenerator(0,1);
        Map<String,String> fieldMap=new HashMap<>();
        String tempId=request.getParameter("tempId");
        if(tempId.isEmpty()){
            throw new BaseException("模板ID不能为空");
        }
        ExcelTempVo vo=excelTempManager.getExcelTempByCode(tempId,2);
        if(null==vo){
            throw new BaseException("模板参数错误");
        }

        ExcelTemp temp=vo.getExcelTemp();
        Integer type=temp.getType();
        List<ExcelTempFields> fields=vo.getFields();
        for(ExcelTempFields field : fields){
            fieldMap.put(field.getFieldComments(),field.getFieldName());
//            fields.add(field.getColumnName());
        }
//        MultipartFile multipartFile=getFile(request);
        if(type==2){
            MultipartFile multipartFile=null;
            Object[] obj=pjp.getArgs();
            for(Object o :obj){
                String typeClass=o.getClass().toString();
                if(typeClass.indexOf("MultipartFile")!=-1){
//                    StandardMultipartHttpServletRequest sms= (StandardMultipartHttpServletRequest) o;
//                    multipartFile=sms.getFile("file");
                    multipartFile=(MultipartFile) o;

                }
            }
            if(null==multipartFile){
                return;
            }
//            CREATE_BY_           VARCHAR(66) COMMENT '创建人ID',
//            CREATE_ORG_NAME_     VARCHAR(66) COMMENT '创建人组织名称',
//            CREATE_COMPANY_ID_   VARCHAR(66) COMMENT '创建人单位ID',
//            CREATE_COMPANY_NAME_ VARCHAR(66) COMMENT '创建人单位名称',
//            CREATE_NAME_         VARCHAR(50) COMMENT '创建人姓名',
//            CREATE_ORG_ID_       VARCHAR(66) COMMENT '创建人组织ID',
//            CREATE_TIME_         TIMESTAMP   COMMENT '创建时间',
//
//            UPDATE_BY_           VARCHAR(66) COMMENT '更新人ID',
//            UPDATE_NAME_         VARCHAR(50) COMMENT '更新人姓名',
//            UPDATE_COMPANY_NAME_ VARCHAR(100) COMMENT '更新人单位名称',
//            UPDATE_COMPANY_ID_   VARCHAR(50) COMMENT '更新人单位ID',
//            UPDATE_ORG_ID_       VARCHAR(66) COMMENT '更新人组织ID',
//            UPDATE_ORG_NAME_     VARCHAR(66) COMMENT '更新人组织名称',
//            UPDATE_TIME_         TIMESTAMP   COMMENT '更新时间',
//
//            TENANT_ID_           VARCHAR(66) COMMENT '租户ID',
            List<Map<String,String>> list=ExcelUtil.ImportDate(multipartFile);
            StringBuffer insertField=new StringBuffer("id_,CREATE_BY_,CREATE_ORG_NAME_,CREATE_ORG_ID_,CREATE_COMPANY_NAME_,CREATE_COMPANY_ID_,CREATE_NAME_,CREATE_TIME_,TENANT_ID_,");
            StringBuffer valueField=new StringBuffer("?,'"+userId+"','"+ContextUtil.getCurrentOrgName()+"','"+ContextUtil.getCurrentOrgId()+"','"+ContextUtil.getCurrentDeptName()+"','"+ContextUtil.getCurrentDeptId()+"','"+userName+"',now(),'"+tenantId+"',");

            for (int i=0;i<fields.size();i++) {
                ExcelTempFields f=fields.get(i);
                String tableField= StringUtil.humpToUnderline(fieldMap.get(f.getFieldComments()));
                if(i<fields.size()-1) {
                    insertField.append(f.getFieldName()).append(",");
                    valueField.append("?,");
                }else{
                    insertField.append(f.getFieldName());
                    valueField.append("?");
                }
            }
            String insertSql="insert into "+temp.getDbTable()+"("+insertField+") values("+valueField+")";
            LinkedList<Object[]> data=new LinkedList<>();
            for(Map<String,String> map : list){
                Object[] row=new Object[fields.size()+1];
                row[0]=id.nextId();
                for (int i=0;i<fields.size();i++) {
                    ExcelTempFields field=fields.get(i);
                    //读取时第一列位列名
                    String key=field.getFieldComments();
                    String val=map.get(key);
                    if(StringUtils.isEmpty(val)){
                        row[i + 1] = null;
                        continue;
                    }
                    try{
                        Integer v= Integer.parseInt(val);
                        row[i + 1] = v;
                    }catch (Exception e){
                        row[i + 1] = val;
                    }
                }
                data.add(row);
            }
            try {
                JdbcTemplate jdbcTemplate = AppUtil.getBean(JdbcTemplate.class);
                jdbcTemplate.batchUpdate(insertSql, data);
            }catch (Exception e){
                e.printStackTrace();
                throw new ApplicationException(e.getMessage());
            }
            //导出
        }
    }

    /**
     * 从HttpServletRequest中获取文件MultipartFile
     * @param request
     */
    public MultipartFile getFile(HttpServletRequest request){
        try {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            MultipartFile pic = multipartRequest.getFile("file");
            return pic;
        }catch (ClassCastException e){
            log.info("没有附件");
        }
        return null;
    }

    /**
     *  翻译字典文本 根据lable获取value
     *  [{"value":"1","label":"1"}]
     * @return
     */
    private String translateDictValue(String JsonStr, String key) {
        if(StringUtils.isEmpty(key)) {
            return null;
        }
        JSONArray jsonArray=JSONArray.parseArray(JsonStr);
        for(int i=0;i<jsonArray.size();i++){
            JSONObject jsonObject=jsonArray.getJSONObject(i);
            if(key.equals(jsonObject.getString("value"))){
                String value = jsonObject.getString("label");
                return value;
            }
        }

        return "";
    }

    /***
     * 下划线命名转为驼峰命名
     * @param para 下划线命名的字符串
     */
    public static String underlineToHump(String para){
        StringBuilder result=new StringBuilder();
        String a[]=para.split("_");
        for(String s:a){
            if(result.length()==0){
                result.append(s.toLowerCase());
            }else{
                result.append(s.substring(0, 1).toUpperCase());
                result.append(s.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }
}