package cn.com.capcloud.api.action.service;

import cn.com.capcloud.api.action.service.util.ImportExportUtil;
import cn.com.capcloud.ccui.core.common.json.JackJSONArray;
import cn.com.capcloud.ccui.core.common.json.JackJSONObject;
import cn.com.capcloud.ccui.core.common.utils.StringUtil;
import cn.com.capcloud.ccui.core.common.utils.UUIDUtils;
import cn.com.capcloud.core.execl.xls.CellForm;
import cn.com.capcloud.core.execl.xls.CellFormat;
import cn.com.capcloud.core.execl.xls.ExeclFileObject;
import cn.com.capcloud.core.execl.xlsx.ExcelUtil;
import cn.com.capcloud.core.noentitydb.BaseService;
import cn.com.capcloud.core.noentitydb.JtPage;
import cn.com.capcloud.core.system.user.User;
import cn.com.capcloud.core.system.user.UserService;
import cn.com.capcloud.core.util.ReadProperty;
import cn.com.capcloud.core.websocket.RedisPublication;
import org.joda.time.DateTime;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ImportExportService {

    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ImportExportService.class);

    @Autowired
    private ApiService apiService;
    @Autowired
    private DictService dictService;
    @Autowired
    private UserService userService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private ReadProperty readProperty;
    @Autowired
    private BaseService baseService;
    @Autowired
    private RedisPublication redisPublication;
    @Autowired
    private FileService fileService;
    @Autowired
    private DataSourceService dsService;

    public Map<String,Object> importExcelData(JackJSONObject retJson, HttpServletRequest request) {
        Map<String,Object>  returnMap=new HashMap<>();
        Map<String,Object> fileInfo=null;
        try {

            Map<String,Object> uploadFile=fileService.uploadToService(retJson,request);
            fileInfo= (Map<String, Object>) uploadFile.get("fileInfo");
            String jsonStr=request.getParameter("data");
            Map<String, Object> dsMap=dsService.findDataSourceByJsonStr(jsonStr);
            List<Map<String, Object>> queryFieldList=dsService.getQueryInfo(jsonStr);
            List<Map<String, Object>> formFieldList=dsService.getFormInfo(jsonStr);
            File file=new File(readProperty.getTempFilePath()+fileInfo.get("diskFileName"));
            //以下是获取excel内的信息 读取信息循环
            InputStream inputStream = new FileInputStream(file);
            String suffix=String.valueOf(fileInfo.get("suffix"));
            if(!"xls".equals(suffix)&&!"xlsx".equals(suffix)){
                retJson.putAll(JackJSONObject.fromObject(apiService.getReturnDataByCode("5040")));
                retJson.put("message",retJson.get("message")+" 你导入的文件格式是："+suffix);
                retJson.put("fileInfo",fileInfo);
                return new HashMap<>();
            }
            String tableName=String.valueOf(dsMap.get("ds_table_name"));
            Map<String,Object> labelNameMap=new HashMap<>();
            for (int i = 0; i < queryFieldList.size(); i++) {
                String key=String.valueOf(queryFieldList.get(i).get("name"));
                labelNameMap.put(key,queryFieldList.get(i).get("label_name"));
            }
            List<Map<String, Object>> dataMaps=new ArrayList<>();
            User user=userService.getUser(request);
            returnMap= ImportExportUtil.importExcelData("",retJson,returnMap,fileInfo,dataMaps,queryFieldList,formFieldList,inputStream,userService,user,jdbcTemplate,redisPublication);
            if(returnMap.size()==0){
                return new HashMap<>();
            }
            JackJSONObject jsonObject = JackJSONObject.fromObject(jsonStr);
            String wsCode=String.valueOf(jsonObject.get("queryCode"));
            Map<String,Object> saveRetMap=baseService.save(tableName,dataMaps);
            if(!"ok".equals(String.valueOf(saveRetMap.get("status")))){
                String message="导入终止,原因是 "+labelNameMap.get(saveRetMap.get("fieldName"))+"("+saveRetMap.get("fieldName")+") 最大长度为："+saveRetMap.get("maxLength")+",导入的长度为："+String.valueOf(saveRetMap.get("fieldValue")).length();
                redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\""+message+"\",\"status\":\"5010\",\"isHideMask\":\"Y\"}",String.valueOf(user.getId()));
                return new HashMap<>();
            }
            redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\""+returnMap.get("importMessage")+"\",\"status\":\"ok\",\"isHideMask\":\"Y\"}",String.valueOf(user.getId()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        returnMap.put("fileInfo",fileInfo);
        return returnMap;
    }
    /**
     * 支持xls和xlsx导入
     */
    @Async("taskExecutor")//导入
    public Map<String,Object> importExcelDataNew(String jsonStr,JackJSONObject retJson,HttpServletRequest request,User user) {
        Map<String,Object>  returnMap=new HashMap<>();
        Map<String,Object> fileInfo=null;
        try {
            JackJSONArray fileArray=JackJSONArray.fromObject(apiService.getJsonValueByKey(jsonStr,retJson,"fileArray"));
            fileInfo=fileArray.getJackJSONObject(0);
            Map<String, Object> dsMap=dsService.findDataSourceByJsonStr(jsonStr);
            List<Map<String, Object>> queryFieldList=dsService.getQueryInfo(jsonStr);
            List<Map<String, Object>> formFieldList=dsService.getFormInfo(jsonStr);
            File file=new File(readProperty.getTempFilePath()+fileInfo.get("diskFileName"));
            //以下是获取excel内的信息 读取信息循环
            InputStream inputStream = new FileInputStream(file);
            String suffix=String.valueOf(fileInfo.get("suffix"));
            if(!"xls".equals(suffix)&&!"xlsx".equals(suffix)){
                retJson.putAll(JackJSONObject.fromObject(apiService.getReturnDataByCode("5040")));
                retJson.put("message",retJson.get("message")+" 你导入的文件格式是："+suffix);
                retJson.put("fileInfo",fileInfo);
                return new HashMap<>();
            }
            String tableName=String.valueOf(dsMap.get("ds_table_name"));
            Map<String,Object> labelNameMap=new HashMap<>();
            for (int i = 0; i < queryFieldList.size(); i++) {
                String key=String.valueOf(queryFieldList.get(i).get("name"));
                labelNameMap.put(key,queryFieldList.get(i).get("label_name"));
            }
            List<Map<String, Object>> dataMaps=new ArrayList<>();
            returnMap= ImportExportUtil.importExcelData(jsonStr,retJson,returnMap,fileInfo,dataMaps,queryFieldList,formFieldList,inputStream,userService,user,jdbcTemplate,redisPublication);
            if(returnMap.size()==0){
                return new HashMap<>();
            }
            Map<String,Object> defaultMap=new HashMap<>();
            if(dataMaps.size()>0){
                if(formFieldList.size()>0){//遍历表单获取默认值
                    for (int i = 0; i < formFieldList.size(); i++) {
                        String defaultValue=String.valueOf(formFieldList.get(i).get("default_value"));
                        if(!defaultValue.equals("null")&&defaultValue.length()>0){
                            String fieldName=String.valueOf(formFieldList.get(i).get("name"));
                            defaultMap.put(fieldName,defaultValue);
                        }
                    }
                    if(defaultMap.size()>0){
                        for (int i = 0; i < dataMaps.size(); i++) {
                            Map<String, Object> currentMap = dataMaps.get(i);

                            for (Map.Entry<String, Object> entry : defaultMap.entrySet()) {
                                String key = entry.getKey();
                                Object defaultValue = entry.getValue();

                                String dataValue=String.valueOf(currentMap.get(key));
                                if (dataValue.equals("null")||dataValue.length()==0) {
                                    currentMap.put(key, defaultValue);
                                }
                            }
                        }
                    }
                }
            }
            JackJSONObject jsonObject = JackJSONObject.fromObject(jsonStr);
            String wsCode=String.valueOf(jsonObject.get("queryCode"));
            long startTime = System.currentTimeMillis();//获取开始时间
            Map<String,Object> saveRetMap=baseService.save(tableName,dataMaps,redisPublication,wsCode,user);
            if(!"ok".equals(String.valueOf(saveRetMap.get("status")))){
                String filedValue=String.valueOf(saveRetMap.get("fieldValue"));
                if(filedValue.length()>500){
                    filedValue = filedValue.substring(0, Math.min(filedValue.length(), 500))+"...";
                }
                filedValue = filedValue.replaceAll("[\n\r]", " ");//打印这个如果有特殊字符会影响json格式
                String message="导入终止，原因是 ("+labelNameMap.get(saveRetMap.get("fieldName"))+"："+saveRetMap.get("fieldName")+") 最大长度为："+saveRetMap.get("maxLength")
                        +"，导入的长度为："+saveRetMap.get("fieldLength");
                redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\""+message+"\",\"status\":\"5010\",\"isHideMask\":\"Y\"}",String.valueOf(user.getId()));
                return new HashMap<>();
            }
            String importMessage=returnMap.get("importMessage")+"，用时："+(System.currentTimeMillis() - startTime)+"毫秒";
            redisPublication.sendMessage("{\"wsCode\":\""+wsCode+"\",\"message\":\""+importMessage+"\",\"status\":\"ok\",\"isHideMask\":\"Y\"}",String.valueOf(user.getId()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        returnMap.put("fileInfo",fileInfo);
        return returnMap;
    }

    public Map<String,Object> exportExcelDataByXlsx(String jsonStr, JackJSONObject retJson, JtPage jtPage) {
        Map<String,Object>  returnMap=new HashMap<>();
        Map<String,Object>  headMap=new HashMap<>();//作用存标题名称
        List<String> headList = new ArrayList<>();//作用标题排序
        List<Map<String,Object>> fieldList=dsService.getQueryInfo(jsonStr);
        Map<String, Object> queryMap=dsService.getQuery(jsonStr);
        String queryName= String.valueOf(queryMap.get("query_name"));
        OutputStream stream = null;
        String suffix = ".xlsx";
        DateTime d=new DateTime();
        String preffix = d.toString("yyyyMM")+"/excel_"+ UUIDUtils.randomUuidWithoutHyphen();
        List<Map<String,Object>> list=new ArrayList<>();
        // 输出表头
        boolean isExpExeclFiled = false;
        for (int i = 0; i < fieldList.size(); i++) {
            String isExportExcel=String.valueOf(fieldList.get(i).get("is_export_excel"));
            if (StringUtil.isNotEmpty(isExportExcel) && isExportExcel.equals("Y")) {
                isExpExeclFiled = true;
            }
        }
        if(!isExpExeclFiled){
            retJson.putAll(JackJSONObject.fromObject(apiService.getReturnDataByCode("5030")));
            return new HashMap<>();
        }
        List<Map<String,Object>> dataList =jtPage.getContent();
        ImportExportUtil.exportExcelDataByXlsx(fieldList,headMap,headList,dataList,list,jdbcTemplate);
        try {
            String fileDir=readProperty.getTempFilePath()+d.toString("yyyyMM");
            File folder = new File(fileDir);
            if (!folder.exists()) {
                folder.mkdirs();
            }
            headMap.put("headList",headList);
            stream=new FileOutputStream(readProperty.getTempFilePath()+preffix+suffix);
            ExcelUtil.exportExcelX(queryName,headMap, JackJSONArray.fromObject(list),10,stream);
            returnMap.put("realFileName", queryName+"_数据导出_"+d.toString("yyyyMMddHHmm")+ suffix);
            returnMap.put("diskFileName", preffix + suffix);
            returnMap.put("suffix",  suffix);
            returnMap.put("exportNum",  "共导出："+list.size()+"条");
        } catch (IOException e) {
        }
        return returnMap;
    }
    public Map<String,Object> exportExcelTemplate(List<Map<String,Object>> fieldList,Map<String, Object> queryMap) {
        Map<String,Object>  returnMap=new HashMap<>();
        DateTime d=new DateTime();
        OutputStream stream = null;
        String suffix = ".xls";
        String preffix = "excel_template_"+UUIDUtils.randomUuidWithoutHyphen();
        try {
            stream = new FileOutputStream(readProperty.getTempFilePath()+preffix+suffix);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        ExeclFileObject efo = new ExeclFileObject(stream);
        List<CellForm> cellFormList = new ArrayList<CellForm>();
        List<CellForm> cellFormListField = new ArrayList<CellForm>();
        List<CellForm> cellFormListCity = new ArrayList<CellForm>();
        CellFormat.init();
        int y = 0;
        int yField = 0;
        int yCity = 0;
        // 输出表头
        boolean isExportExeclTemplate = false;
        for (int i = 0; i < fieldList.size(); i++) {
            String isExportExcelTemplate=String.valueOf(fieldList.get(i).get("is_export_excel_template"));
            if (StringUtil.isNotEmpty(isExportExcelTemplate) && isExportExcelTemplate.equals("Y")) {
                isExportExeclTemplate = true;
            }
        }
        if (!isExportExeclTemplate) {
            logger.info("无导出字段");
        } else {
            for (int i = 0; i < fieldList.size(); i++) {
                String isExportExcelTemplate=String.valueOf(fieldList.get(i).get("is_export_excel_template"));
                if (StringUtil.isNotEmpty(isExportExcelTemplate) && isExportExcelTemplate.equals("Y")) {
                    CellForm cellForm = new CellForm();
                    cellForm.setCol(y);
                    cellForm.setRow(0);
                    cellForm.setType(0);
                    cellForm.setHeaderformat(CellFormat.TITLE_HEADER);
                    cellForm.setCellValue(String.valueOf(fieldList.get(i).get("label_name")).replaceAll("\\*", ""));
                    cellFormList.add(cellForm);
                    y++;
                    if(StringUtil.isNotEmpty(fieldList.get(i).get("dict_code"))){
                        CellForm cellFormFieldTitle = new CellForm();
                        cellFormFieldTitle.setCol(yField);
                        cellFormFieldTitle.setRow(0);
                        cellFormFieldTitle.setType(0);
                        cellFormFieldTitle.setHeaderformat(CellFormat.TITLE_HEADER);
                        cellFormFieldTitle.setCellValue(String.valueOf(fieldList.get(i).get("label_name")).replaceAll("\\*", ""));
                        cellFormListField.add(cellFormFieldTitle);
                        List<Map<String,Object>> dictList=dictService.getDictInfoByDictCodeToList((fieldList.get(i).get("dict_code"))+"");
                        for (int xxx = 0;xxx<dictList.size();xxx++){
                            CellForm cellFormFieldValue = new CellForm();
                            cellFormFieldValue.setCol(yField);
                            cellFormFieldValue.setRow(xxx+1);
                            cellFormFieldValue.setType(0);
                            cellFormFieldValue.setHeaderformat(CellFormat.TITLE_HEADER);
                            cellFormFieldValue.setCellValue(dictList.get(xxx).get("value")+"");
                            cellFormListField.add(cellFormFieldValue);
                        }
                        yField++;
                    }
                }
            }
        }
        try {
            efo.writeSheet(cellFormList, String.valueOf(queryMap.get("query_code")), 0);
            efo.writeSheet(cellFormListField, "内部字典值", 1);
            efo.writeSheet(cellFormListCity, "tree字典（开发中）", 2);
            efo.CloseFile();
            stream.close();
        } catch (Exception e) {
        }
        returnMap.put("realFileName", queryMap.get("query_name")+"数据导入模板_"+ d.toString("yyyyMMddHHmm")+ suffix);
        returnMap.put("diskFileName", preffix + suffix);
        returnMap.put("suffix",  suffix);
        return returnMap;
    }

    //json原始数据导入,excel需要将字典转换，json不需要
    public Map<String,Object> importJsonData(String jsonStr,JackJSONObject retJson,HttpServletRequest request) {
        User user=userService.getUser(request);
        String importJsonStr=apiService.getJsonValueByKey(jsonStr,retJson,"importJsonStr");
        JackJSONArray importJsonData=new JackJSONArray();
        try {
            JackJSONArray importJsonArray=JackJSONArray.fromObject(importJsonStr);
            importJsonData=importJsonArray;
        } catch (Exception e) {
            try {
                JackJSONObject importJson=JackJSONObject.fromObject(importJsonStr);
                importJsonData.add(importJson);
            } catch (Exception exception) {
                retJson.put("status","no_code");
                retJson.put("message","导入失败，格式错误");
                return new HashMap<>();
            }
        }
        JackJSONObject jsonObject = JackJSONObject.fromObject(jsonStr);
        String parentUUID=String.valueOf(jsonObject.get("parentUUID"));
        String idValue=String.valueOf(importJsonData.getJackJSONObject(0).get("id"));
        if(StringUtil.isNotEmpty(idValue)){
            try {
                Integer.valueOf(idValue);
            } catch (Exception e) {
                retJson.put("status","no_code");
                retJson.put("message","导入失败，id字段必须是数值，请检查数据或联系管理员");
                return new HashMap<>();
            }
        }
        for (int i = 0; i < importJsonData.size(); i++) {
            importJsonData.getJackJSONObject(i).put("data_source","json");
            if(StringUtil.isNotEmpty(parentUUID)){
                importJsonData.getJackJSONObject(i).put("page_parent_uuid",parentUUID);
            }
        }
        Map<String, Object> dsMap=dsService.findDataSourceByJsonStr(jsonStr);
        String tableName=String.valueOf(dsMap.get("ds_table_name"));
        Map<String,Object> saveRetMap=baseService.save(tableName,(List)importJsonData,user);
        if(!"ok".equals(String.valueOf(saveRetMap.get("status")))){
            String filedValue=String.valueOf(saveRetMap.get("fieldValue"));
            String message="导入终止，原因是 ("+saveRetMap.get("fieldName")+"："+saveRetMap.get("fieldName")+") 最大长度为："+saveRetMap.get("maxLength")
                    +"，导入的长度为："+filedValue.length()+"，   原文："+filedValue;
            retJson.put("status","no_code");
            retJson.put("message",message);
            return new HashMap<>();
        }
        retJson.put("status","ok");
        retJson.put("message","导入成功");
        return new HashMap<>();
    }

    public Map<String,Object> updateJsonData(String jsonStr,JackJSONObject retJson,HttpServletRequest request) {
        User user=userService.getUser(request);
        String updateJsonStr=apiService.getJsonValueByKey(jsonStr,retJson,"updateJsonStr");
        JackJSONArray updateJsonData=new JackJSONArray();
        try {
            JackJSONArray updateJsonArray=JackJSONArray.fromObject(updateJsonStr);
            updateJsonData=updateJsonArray;
        } catch (Exception e) {
            try {
                JackJSONObject importJson=JackJSONObject.fromObject(updateJsonStr);
                updateJsonData.add(importJson);
            } catch (Exception exception) {
                retJson.put("status","no_code");
                retJson.put("message","更新失败，格式错误");
                return new HashMap<>();
            }
        }
        JackJSONObject jsonObject = JackJSONObject.fromObject(jsonStr);
        String parentUUID=String.valueOf(jsonObject.get("parentUUID"));
        String idValue=String.valueOf(updateJsonData.getJackJSONObject(0).get("id"));
        if(StringUtil.isNotEmpty(idValue)){
            try {
                Integer.valueOf(idValue);
            } catch (Exception e) {
                retJson.put("status","no_code");
                retJson.put("message","更新失败，id字段必须是数值，请检查数据或联系管理员");
                return new HashMap<>();
            }
        }
        for (int i = 0; i < updateJsonData.size(); i++) {
            updateJsonData.getJackJSONObject(i).put("data_source","json");
            if(StringUtil.isNotEmpty(parentUUID)){
                updateJsonData.getJackJSONObject(i).put("page_parent_uuid",parentUUID);
            }
        }
        Map<String, Object> dsMap=dsService.findDataSourceByJsonStr(jsonStr);
        String tableName=String.valueOf(dsMap.get("ds_table_name"));
        baseService.update(tableName,(List)updateJsonData,user);
        retJson.put("status","ok");

        retJson.put("message","更新成功");
        return new HashMap<>();
    }

}

