package com.mortals.xhx.module.matter.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.plugin.table.MultipleRowTableRenderPolicy;
import com.deepoove.poi.template.MetaTemplate;
import com.deepoove.poi.util.RegexUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mortals.framework.model.PageInfo;
import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.base.system.param.service.ParamService;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.common.code.ComponentEnum;
import com.mortals.xhx.common.formdesign.*;
import com.mortals.xhx.common.key.ParamKey;
import com.mortals.xhx.common.pdu.gen.component.ComponentCons;
import com.mortals.xhx.common.utils.ExportDocUtil;
import com.mortals.xhx.common.utils.WordUtil;
import com.mortals.xhx.module.matter.dao.MatterDao;
import com.mortals.xhx.module.matter.model.MatterEntity;
import com.mortals.xhx.module.matter.service.MatterService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.xhx.module.matter.dao.MatterDatumDao;
import com.mortals.xhx.module.matter.model.MatterDatumEntity;
import com.mortals.xhx.module.matter.service.MatterDatumService;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
* MatterDatumService
* 事项申请材料 service实现
*
* @author zxfei
* @date 2022-09-27
*/
@Service("matterDatumService")
public class MatterDatumServiceImpl extends AbstractCRUDServiceImpl<MatterDatumDao, MatterDatumEntity, Long> implements MatterDatumService {

    private static int RECOMMEND_COUNT = 5;

    @Value("${upload.path}")
    private String filePath;
    @Value("${upload.url:http://localhost:17215/fsm/file/commonupload?prePath=/file/uploadfile}")
    private String uploadUrl;
    @Autowired
    private UploadService uploadService;
    @Autowired
    private ParamService paramService;
    @Autowired
    private MatterService matterService;

    @Override
    protected MatterDatumEntity findBefore(MatterDatumEntity params, PageInfo pageInfo, Context context) throws AppException {
        if(com.mortals.xhx.common.utils.StringUtils.isNotEmpty(params.getMaterialName())){
            params.setMaterialName("%".concat(params.getMaterialName()).concat("%"));
        }
        return params;
    }

    @Override
    protected void findAfter(MatterDatumEntity params, PageInfo pageInfo, Context context, List<MatterDatumEntity> list) throws AppException {
        if(CollectionUtils.isNotEmpty(list)){
            for (MatterDatumEntity entity:list){
                MatterEntity matter = matterService.get(entity.getMatterId());
                if(matter!=null){
                    entity.setMatterName(matter.getMatterName());
                    entity.setMatterNo(matter.getMatterNo());
                    entity.setDeptName(matter.getDeptName());
                }

            }
        }
    }

    @Override
    protected void saveBefore(MatterDatumEntity entity, Context context) throws AppException {
        if(StringUtils.isEmpty(entity.getFileUrl())){
            throw new AppException("填单附件不能为空");
        }
        if(StringUtils.isEmpty(entity.getSamplePath())){
            throw new AppException("样表地址不能为空");
        }
        if(StringUtils.isEmpty(entity.getTemplatePath())){
            throw new AppException("样表模板地址不能为空");
        }
        entity.setTotal(0);
        entity.setSort(0);
        entity.setIsRecommend(0);
        //生成样表预览图片
        String rootPath = this.filePath.endsWith("/") ? this.filePath : this.filePath + "/";
        String samplePath = rootPath + entity.getSamplePath();
        String prePath = "/preview/";
        String filePath = rootPath + prePath ;
        File pathDir = new File(filePath);
        if (!pathDir.exists()) {
            pathDir.mkdirs();
        }

        String newName = RandomUtil.randomNumbers(12) + ".jpg";
        String filePathAll = filePath + newName;
        WordUtil.convertWordToJPEG(samplePath, filePathAll);

        entity.setPreViewPath(prePath + newName);
        //校验模板变量正确性 todo
        if (!ObjectUtils.isEmpty(entity.getTemplatePath())) {
            parseDocxToJson(entity);
        }

        super.saveBefore(entity, context);
    }

    @Override
    protected void updateBefore(MatterDatumEntity entity, Context context) throws AppException {
        entity.setIsRecommend(null);
        this.validData(entity, context);
    }

    @Override
    protected void removeBefore(Long[] ids, Context context) throws AppException {
        List<MatterDatumEntity> queryList = this.get(ids,context);
        if(CollectionUtils.isNotEmpty(queryList)){
            int recommendCount = paramService.getParamIntValue(ParamKey.MATTER_DATUM_RECOMMEND_COUNT);
            for(MatterDatumEntity matterEntity:queryList){
                if(matterEntity.getIsRecommend()==1){
                    recommendCount--;
                }
            }
            paramService.setValueByKey(ParamKey.MATTER_DATUM_RECOMMEND_COUNT,String.valueOf(recommendCount));
        }
    }

    private void parseDocxToJson(MatterDatumEntity entity) {
        String rootPath = this.filePath.endsWith("/") ? this.filePath : this.filePath + "/";
        String filepath = rootPath + entity.getTemplatePath();
        ConfigureBuilder builder = Configure.builder();

        builder.setValidErrorHandler(new Configure.DiscardHandler());
        builder.useDefaultEL(false);
        builder.buildGrammerRegex(RegexUtils.createGeneral("{{", "}}"));
        //builder.buildGramer("[","]");
        XWPFTemplate template = XWPFTemplate.compile(filepath, builder.build());
        FormDesignRoot root = new FormDesignRoot();
        FormDesignConfig config = new FormDesignConfig();
        config.initAttribute();
        root.setConfig(config);
        List<ListItem> collect = new ArrayList<>();
        for (MetaTemplate item : template.getElementTemplates()) {
            //识别简单输入
            String val = StrUtil.strip(item.variable(), "{{", "}}");
            List<String> keys = StrSplitter.split(val, "_", true, true);
            //切分分隔符后动态 创建组件  i_1_姓名（第一个代表类型，第二个如果是多个累加，第三个显示label）
            if (keys.size() > 2) {
                String label = keys.get(2);
                String type = keys.get(0);
                ComponentCons cons = new ComponentCons();
                cons.setLabel(label);
                cons.setVal(val);
                cons.setEl(item.variable());
                cons.setUploadFileUrl(uploadUrl);

                if (type.equalsIgnoreCase(ComponentEnum.DYNAMIC_TABLE.getValue())) {
                    List<TableColItem> colList = new ArrayList<>();
                    //表格 结构化绑定数据
                    ConfigureBuilder builderTable = Configure.builder();
                    builderTable.setValidErrorHandler(new Configure.DiscardHandler());
                    builderTable.useDefaultEL(false);
                    builderTable.buildGramer("[", "]");
                    XWPFTemplate templateTable = XWPFTemplate.compile(filepath, builderTable.build());

                    for (MetaTemplate col : templateTable.getElementTemplates()) {
                        String colVal = StrUtil.strip(col.variable(), "[", "]");
                        if (!StrUtil.startWith(colVal, label)) {
                            continue;
                        }
                        List<String> colKeys = StrSplitter.split(colVal, "_", true, true);
                        //提取当前table中的列元素
                        if (colKeys.size() > 3) {
                            String colLabel = colKeys.get(3);
                            String colType = colKeys.get(1);
                            TableColItem tableColItem = new TableColItem();
                            tableColItem.setLabel(colLabel);
                            tableColItem.setColType(colType);
                            tableColItem.setVal(colVal);
                            colList.add(tableColItem);
                            //System.out.println("列元素" + col.variable());
                        }
                    }
                    cons.setColList(colList);
                    DesignComponent designComponent = DesignComponent.createType(type);
                    ListItem listItem = designComponent.buildDefaultComponent(cons);
                    collect.add(listItem);
                    continue;
                }
                DesignComponent designComponent = DesignComponent.createType(type);
                ListItem listItem = designComponent.buildDefaultComponent(cons);
                collect.add(listItem);
            }
        }
        root.setList(collect);
        entity.setFormContent(JSON.toJSONString(root));
    }


//    public static void main(String[] arg){
//        String filepath = "D:\\mortals\\app\\data\\file\\uploadfile\\1665472289712.docx";
//        ConfigureBuilder builder = Configure.builder();
//        builder.setValidErrorHandler(new Configure.DiscardHandler());
//        builder.useDefaultEL(false);
//        builder.buildGrammerRegex(RegexUtils.createGeneral("{{", "}}"));
//        //builder.buildGramer("[","]");
//        XWPFTemplate template = XWPFTemplate.compile(filepath, builder.build());
//        System.out.println(template.getElementTemplates().toString());
//        FormDesignRoot root = new FormDesignRoot();
//        FormDesignConfig config = new FormDesignConfig();
//        config.initAttribute();
//        root.setConfig(config);
//        List<ListItem> collect = new ArrayList<>();
//        for (MetaTemplate item : template.getElementTemplates()) {
//            //识别简单输入
//            String val = StrUtil.strip(item.variable(), "{{", "}}");
//            List<String> keys = StrSplitter.split(val, "_", true, true);
//            //切分分隔符后动态 创建组件  i_1_姓名（第一个代表类型，第二个如果是多个累加，第三个显示label）
//            if (keys.size() > 2) {
//                String label = keys.get(2);
//                String type = keys.get(0);
//                ComponentCons cons = new ComponentCons();
//                cons.setLabel(label);
//                cons.setVal(val);
//                cons.setEl(item.variable());
//                cons.setUploadFileUrl("");
//
//                if (type.equalsIgnoreCase(ComponentEnum.DYNAMIC_TABLE.getValue())) {
//                    List<TableColItem> colList = new ArrayList<>();
//                    //表格 结构化绑定数据
//                    ConfigureBuilder builderTable = Configure.builder();
//                    builderTable.setValidErrorHandler(new Configure.DiscardHandler());
//                    builderTable.useDefaultEL(false);
//                    builderTable.buildGramer("[", "]");
//                    XWPFTemplate templateTable = XWPFTemplate.compile(filepath, builderTable.build());
//
//                    for (MetaTemplate col : templateTable.getElementTemplates()) {
//                        String colVal = StrUtil.strip(col.variable(), "[", "]");
//                        if (!StrUtil.startWith(colVal, label)) {
//                            continue;
//                        }
//                        List<String> colKeys = StrSplitter.split(colVal, "_", true, true);
//                        //提取当前table中的列元素
//                        if (colKeys.size() > 3) {
//                            String colLabel = colKeys.get(3);
//                            String colType = colKeys.get(1);
//                            TableColItem tableColItem = new TableColItem();
//                            tableColItem.setLabel(colLabel);
//                            tableColItem.setColType(colType);
//                            tableColItem.setVal(colVal);
//                            colList.add(tableColItem);
//                            //System.out.println("列元素" + col.variable());
//                        }
//                    }
//                    cons.setColList(colList);
//                    DesignComponent designComponent = DesignComponent.createType(type);
//                    ListItem listItem = designComponent.buildDefaultComponent(cons);
//                    collect.add(listItem);
//                    continue;
//                }
//                DesignComponent designComponent = DesignComponent.createType(type);
//                ListItem listItem = designComponent.buildDefaultComponent(cons);
//                collect.add(listItem);
//            }
//        }
//        root.setList(collect);
//        System.out.println(JSON.toJSONString(root));
//    }

    @Override
    public String mergeFormToDoc(MatterDatumEntity docFormVo, Context context) {
        String rootPath = this.filePath.endsWith("/") ? this.filePath : this.filePath + "/";
        //转换表单参数为map集合
        ObjectMapper mapper = new ObjectMapper();
        ConfigureBuilder builder = Configure.builder();
        builder.buildGrammerRegex(RegexUtils.createGeneral("{{", "}}"));
        try {
            Map<String, Object> data = mapper.readValue(docFormVo.getFormContent(), Map.class);
            //遍历查看是否有图片数据，多选框
            data.entrySet().stream().forEach(entry -> {
                if (entry.getKey().indexOf("@image") != -1) {
                    //获取值 读取本地图片
                    String imagepath = uploadService.getFilePath(entry.getValue().toString());
                    log.info("Image path: " + imagepath);
                    try {
                        PictureRenderData pictureRenderData = Pictures.ofStream(new FileInputStream(imagepath), PictureType.JPEG)
                                .size(100, 120).create();
                        data.put(StrUtil.removePrefixIgnoreCase(entry.getKey(),"@"),pictureRenderData);
                        //entry.setValue(pictureRenderData);
                    } catch (FileNotFoundException e) {
                        log.error("error", e);
                    }
                }
                //构建填充复选框值
                if (entry.getKey().indexOf("ck_") != -1 && entry.getKey().indexOf("<") != -1) {
                    //获取复选框选项，并渲染值
                    String ckStr = StringUtils.substringBetween(entry.getKey(), "<", ">");
                    //获取所有选项
                    List<String> checkboxs = StrUtil.splitTrim(ckStr, "-", -1);
                    //选中的项
                    List<String> ckList = Convert.toList(String.class, entry.getValue());
                    //合并
                    String ckStrs = checkboxs.stream().map(item -> {
                        for (String checked : ckList) {
                            if (checked.equals(item)) {
                                Map<Boolean, String> map = new HashMap<>();
                                map.put(true, item);
                                return map;
                            }
                        }
                        Map<Boolean, String> map = new HashMap<>();
                        map.put(false, item);
                        return map;
                    }).map(m -> m.entrySet().stream().map(m1 -> ExportDocUtil.createCheckBoxStrOther(m1.getKey(), m1.getValue())).findFirst().orElseGet(() -> "")
                    ).collect(Collectors.joining(""));
                    entry.setValue(ckStrs);
                }
                //TODO 单选
                //绑定动态表单
                if (entry.getKey().indexOf("dt_") != -1) {
                    builder.bind(entry.getKey(), new MultipleRowTableRenderPolicy());
                }
            });
            //查询是否有多选框，
            //获取模板文件地址
            MatterDatumEntity docTemplateEntity = this.get(docFormVo.getId(),context);
            if (!ObjectUtils.isEmpty(docTemplateEntity)) {
                String path = rootPath + docTemplateEntity.getTemplatePath();
                String templateName = FileUtil.getName(path);
                Configure config = builder.build();
                XWPFTemplate template = null;
                ByteArrayOutputStream byteArrayOutputStream = null;
                try {
                    template = XWPFTemplate.compile(path, config).render(data);
                    byteArrayOutputStream = new ByteArrayOutputStream();
                    template.write(byteArrayOutputStream);

                    MultipartFile multipartFile = new MockMultipartFile(templateName, templateName,
                            ContentType.APPLICATION_OCTET_STREAM.toString(), byteArrayOutputStream.toByteArray());
                    String mergedocPath = uploadService.saveFileUpload(multipartFile, "/mergedoc", context.getUser());
                    log.info("mergedocPath:" + mergedocPath);
                    String mergedoc = rootPath + mergedocPath;
                    //转换预览图片
                    String fileName = RandomUtil.randomNumbers(12) + ".jpg";
                    String preView = this.filePath + "/preview/" + fileName;
                    WordUtil.convertWordToJPEG(mergedoc, preView);
                    log.info("preView:" + mergedocPath);
                    //下载地址拼装
                    String returnStr = mergedocPath + ";" + "/preview/" + fileName;
                    return returnStr;
                } catch (Exception e) {
                    log.error("渲染模板失败：", e);
                } finally {
                    try {
                        template.close();
                        byteArrayOutputStream.close();
                    } catch (IOException e) {
                        log.error("ioEx：", e);
                    }
                }
            }
        } catch (JsonProcessingException e) {
            log.error("转换异常", e);
            throw new AppException("表单参数转换异常:" + e.getMessage());
        }
        return "";
    }

    @Override
    public void recommend(Long id) {
        MatterDatumEntity matterDatumEntity = this.dao.get(id);
        if(matterDatumEntity==null){
            throw new AppException("数据已更改,请重试");
        }
        int recommendCount = paramService.getParamIntValue(ParamKey.MATTER_DATUM_RECOMMEND_COUNT);
        Map<String,Object> data = new HashMap<>();
        Map<String,Object> condition = new HashMap<>();
        condition.put("id",id);
        if(matterDatumEntity.getIsRecommend()==0){
            if(recommendCount >= RECOMMEND_COUNT){
                throw new AppException("超过推荐个数");
            }
            recommendCount++;
            data.put("isRecommend",1);
        }else {
            recommendCount--;
            data.put("isRecommend",0);
        }
        this.dao.update(data,condition);
        paramService.setValueByKey(ParamKey.MATTER_DATUM_RECOMMEND_COUNT,String.valueOf(recommendCount));
    }


//    public static void main(String[] args){
//        String filePath ="D:\\mortals\\app\\data\\file\\uploadfile\\1663917302157.docx";
//        String formContent = "{\n" +
//                "    \"i_1_班级\": \"432432\",\n" +
//                "    \"i_2_姓名\": \"324\",\n" +
//                "    \"i_3_监护人\": \"234\",\n" +
//                "    \"i_4_电话\": \"324\",\n" +
//                "    \"dt_1_汇报\": [\n" +
//                "        {\n" +
//                "            \"汇报_date_1_日期\": \"2022-09-06\",\n" +
//                "            \"汇报_i_4_有无出现呕吐\": \"543\",\n" +
//                "            \"汇报_i_5_有无其他\": \"435\",\n" +
//                "            \"汇报_i_6_有无接触\": \"345\",\n" +
//                "            \"index\": 0\n" +
//                "        },\n" +
//                "        {\n" +
//                "            \"汇报_date_1_日期\": \"\",\n" +
//                "            \"汇报_i_4_有无出现呕吐\": \"\",\n" +
//                "            \"汇报_i_5_有无其他\": \"\",\n" +
//                "            \"汇报_i_6_有无接触\": \"\",\n" +
//                "            \"index\": 1\n" +
//                "        },\n" +
//                "        {\n" +
//                "            \"汇报_date_1_日期\": null,\n" +
//                "            \"汇报_i_4_有无出现呕吐\": \"\",\n" +
//                "            \"汇报_i_5_有无其他\": \"\",\n" +
//                "            \"汇报_i_6_有无接触\": \"\",\n" +
//                "            \"index\": 2\n" +
//                "        }\n" +
//                "    ],\n" +
//                "    \"i_5_誉抄\": \"435\",\n" +
//                "    \"date_1_填表年月日\": \"2022年09月07日\"\n" +
//                "}";
//        //转换表单参数为map集合
//        ObjectMapper mapper = new ObjectMapper();
//        ConfigureBuilder builder = Configure.builder();
//        builder.buildGrammerRegex(RegexUtils.createGeneral("{{", "}}"));
//        try {
//            Map<String, Object> data = mapper.readValue(formContent, Map.class);
//            //遍历查看是否有图片数据，多选框
//            data.entrySet().stream().forEach(entry -> {
////                if (entry.getKey().indexOf("@image") != -1) {
////                    //获取值 读取本地图片
////                    String imagepath = uploadService.getFilePath(entry.getValue().toString());
////                    log.info("Image path: " + imagepath);
////                    try {
////                        PictureRenderData pictureRenderData = Pictures.ofStream(new FileInputStream(imagepath), PictureType.JPEG)
////                                .size(100, 120).create();
////                        data.put(StrUtil.removePrefixIgnoreCase(entry.getKey(),"@"),pictureRenderData);
////                        //entry.setValue(pictureRenderData);
////                    } catch (FileNotFoundException e) {
////                        log.error("error", e);
////                    }
////                }
//                //构建填充复选框值
//                if (entry.getKey().indexOf("ck_") != -1 && entry.getKey().indexOf("<") != -1) {
//                    //获取复选框选项，并渲染值
//                    String ckStr = StringUtils.substringBetween(entry.getKey(), "<", ">");
//                    //获取所有选项
//                    List<String> checkboxs = StrUtil.splitTrim(ckStr, "-", -1);
//                    //选中的项
//                    List<String> ckList = Convert.toList(String.class, entry.getValue());
//                    //合并
//                    String ckStrs = checkboxs.stream().map(item -> {
//                        for (String checked : ckList) {
//                            if (checked.equals(item)) {
//                                Map<Boolean, String> map = new HashMap<>();
//                                map.put(true, item);
//                                return map;
//                            }
//                        }
//                        Map<Boolean, String> map = new HashMap<>();
//                        map.put(false, item);
//                        return map;
//                    }).map(m -> m.entrySet().stream().map(m1 -> ExportDocUtil.createCheckBoxStrOther(m1.getKey(), m1.getValue())).findFirst().orElseGet(() -> "")
//                    ).collect(Collectors.joining(""));
//                    entry.setValue(ckStrs);
//                }
//                //TODO 单选
//                //绑定动态表单
//                if (entry.getKey().indexOf("dt_") != -1) {
//                    builder.bind(entry.getKey(), new MultipleRowTableRenderPolicy());
//                }
//            });
//            //查询是否有多选框，
//
//            String path = filePath ;
//            String templateName = FileUtil.getName(path);
//            Configure config = builder.build();
//            XWPFTemplate template = null;
//            ByteArrayOutputStream byteArrayOutputStream = null;
//            try {
//                template = XWPFTemplate.compile(path, config).render(data);
//                byteArrayOutputStream = new ByteArrayOutputStream();
//                template.write(byteArrayOutputStream);
//
//                MultipartFile multipartFile = new MockMultipartFile(templateName, templateName,
//                        ContentType.APPLICATION_OCTET_STREAM.toString(), byteArrayOutputStream.toByteArray());
//
//                //String mergedocPath = uploadService.saveFileUpload(multipartFile, "/mergedoc", context.getUser());
//                File pathDir = new File(filePath);
//                if (!pathDir.exists()) {
//                    pathDir.mkdirs();
//                }
//                String fileName = multipartFile.getOriginalFilename();
//                String extension = FilenameUtils.getExtension(fileName);
//                String newName = new Date().getTime() + "." + extension;
//                //String newName = IdUtil.fastSimpleUUID() + "." + extension;
//                String filePathAll = "D:\\mortals\\app\\data\\file\\uploadfile\\" + newName;
//
//                File uploadFile = new File(filePathAll);
//                try {
//                    multipartFile.transferTo(uploadFile);
//                } catch (Exception e) {
//                    throw new AppException(e.getMessage());
//                }
//
//
//                //转换预览图片
//                String fileName1 = RandomUtil.randomNumbers(12) + ".jpg";
//                String preView = "D:\\mortals\\app\\data\\preview\\" + fileName1;
//                WordUtil.convertWordToJPEG(filePathAll, preView);
//
//
//                System.out.println("returnStr:");
//            } catch (Exception e) {
//
//                System.out.println("渲染模板失败：" + e.getMessage());
//                e.printStackTrace();
//            } finally {
//                try {
//                    template.close();
//                    byteArrayOutputStream.close();
//                } catch (IOException e) {
//
//                }
//            }
//        } catch (JsonProcessingException e) {
//            System.out.println("表单参数转换异常:" + e.getMessage());
//        }
//    }
}