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.ap.GlobalSysInfo;
import com.mortals.framework.common.Rest;
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.code.MatterSourceEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.formdesign.*;
import com.mortals.xhx.common.key.Constant;
import com.mortals.xhx.common.key.ParamKey;
import com.mortals.xhx.common.pdu.gen.component.ComponentCons;
import com.mortals.xhx.common.utils.BeanUtil;
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.MatterDatumQuery;
import com.mortals.xhx.module.matter.model.MatterEntity;
import com.mortals.xhx.module.matter.model.MatterQuery;
import com.mortals.xhx.module.matter.service.MatterService;
import com.mortals.xhx.module.pubdatum.model.PubdatumEntity;
import com.mortals.xhx.module.pubdatum.service.PubdatumService;
import com.mortals.xhx.module.sheet.model.SheetMatterEntity;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.http.entity.ContentType;
import org.springframework.beans.BeanUtils;
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.concurrent.TimeUnit;
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 {

    @Value("${upload.path}")
    private String filePath;
    @Autowired
    private MatterService matterService;
    @Autowired
    private PubdatumService pubdatumService;

    public static String word[] = {"doc", "dot", "wps", "wpt", "docx", "dotx", "docm", "dotm"};

    public static String imgs[] = {"jpg", "png", "jpeg", "gif"};
    public static String pdf[] = {"pdf"};

    @Override
    protected MatterDatumEntity findBefore(MatterDatumEntity params, PageInfo pageInfo, Context context) throws AppException {
        if (!ObjectUtils.isEmpty(params.getMaterialName())) {
            params.setMaterialName("%".concat(params.getMaterialName()).concat("%"));
        }
        return params;
    }

    @Override
    protected void saveAfter(MatterDatumEntity entity, Context context) throws AppException {
        statDatumCount(entity, context);
        addPubdatum(entity, context);
        super.saveAfter(entity, context);
    }

    @Override
    protected void updateAfter(MatterDatumEntity entity, Context context) throws AppException {
        addPubdatum(entity, context);
        super.updateAfter(entity, context);
    }

    private void addPubdatum(MatterDatumEntity entity, Context context) {
        if (!ObjectUtils.isEmpty(entity.getPub()) && entity.getPub() == YesNoEnum.YES.getValue()) {
            //添加到公共库
            PubdatumEntity pubdatumEntity = new PubdatumEntity();
            pubdatumEntity.initAttrValue();
            BeanUtils.copyProperties(entity, pubdatumEntity, new String[]{"id"});
            pubdatumEntity.setCreateTime(new Date());
            pubdatumEntity.setCreateUserId(getContextUserId(context));
            pubdatumService.save(pubdatumEntity, context);
        }
    }


    @Override
    public int remove(Long id, Context context) throws AppException {
        this.removeBefore(id, context);
        MatterDatumEntity matterDatumEntity = this.get(id, context);
        int iRet = this.dao.delete(id);
        this.removeAfter(id, context, iRet);
        statDatumCount(matterDatumEntity, context);
        return iRet;
    }

    @Override
    public int remove(Long[] ids, Context context) throws AppException {
        this.removeBefore(ids, context);
        if (ids == null || ids.length == 0) return 0;
        MatterDatumEntity matterDatumEntity = this.get(ids[0], context);
        int iRet = this.dao.delete(ids);
        this.removeAfter(ids, context, iRet);
        statDatumCount(matterDatumEntity, context);
        return iRet;
    }

    private void statDatumCount(MatterDatumEntity matterDatumEntity, Context context) {
        int count = this.count(new MatterDatumQuery().matterId(matterDatumEntity.getMatterId()), context);
        MatterEntity matterEntity = matterService.get(matterDatumEntity.getMatterId(), context);
        if (!ObjectUtils.isEmpty(matterEntity)) {
            matterEntity.setDatumCount(count);
            matterService.update(matterEntity, context);
        }
    }

    @Override
    protected void saveBefore(MatterDatumEntity entity, Context context) throws AppException {
        if (StringUtils.isEmpty(entity.getSamplePath())) {
            throw new AppException("样表地址不能为空");
        }
        //生成样表预览图片
        String rootPath = this.filePath.endsWith("/") ? this.filePath : this.filePath + "/";
        String prePath = "file/preview/";
        String newName = genPreviewPath(rootPath, prePath, entity.getSamplePath());
        entity.setPreViewPath(prePath + newName);
        int sort = this.count(new MatterDatumQuery(), context);
        entity.setSort(sort);

        super.saveBefore(entity, context);
    }

    private String genPreviewPath(String rootPath, String prePath, String tempPath) {
        //生成样表预览图片
        String samplePath = rootPath + tempPath;

        //todo 由于分布式 生成预览图片 需判断当前文件是否已经同步到本节点上
        boolean exist = FileUtil.exist(samplePath);
        int count = 0;
        if (!exist) {
            while (true) {
                try {
                    Thread.sleep(2000);
                    boolean bool = FileUtil.exist(samplePath);
                    if (bool) {
                        break;
                    }
                } catch (InterruptedException e) {
                    log.error("中断异常！");
                }
                count++;
                if (count > 3) {
                    break;
                }
            }
        }


        String filePath = rootPath + prePath;
        File pathDir = new File(filePath);
        if (!pathDir.exists()) {
            pathDir.mkdirs();
        }
        String newName = RandomUtil.randomNumbers(12) + ".jpg";
        String filePathAll = filePath + newName;
        //判断文件类型是否为doc pdf jpg png 等
        String extName = FileUtil.getSuffix(samplePath);
        if (this.isExsitArry(extName, word)) {
            WordUtil.convertWordToJPEG(samplePath, filePathAll);
        } else if (this.isExsitArry(extName, pdf)) {
            WordUtil.pdfToImages(samplePath, filePathAll);
        } else if (this.isExsitArry(extName, imgs)) {
            try {
                com.mortals.framework.util.FileUtil.copyFile(samplePath, filePathAll);
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
        return newName;
    }

    public boolean isExsitArry(String chex, String arry[]) {
        for (String ex : arry) {
            if (chex.equalsIgnoreCase(ex)) {
                return true;
            }
        }
        return false;
    }


    @Override
    public Rest<String> addPubdatum(Long[] pubIds, Long matterId, Long siteId, Context context) {
        if (ObjectUtils.isEmpty(pubIds)) {
            throw new AppException("公共材料库ids is null");
        }
        int success = 0;
        int fail = 0;
        List<PubdatumEntity> pubdatumEntityList = pubdatumService.get(pubIds, context);
        List<MatterDatumEntity> matterDatumEntities = new ArrayList<>();
        for (PubdatumEntity pubdatumEntity : pubdatumEntityList) {
            MatterDatumEntity matterDatumEntity = updateOrSave(pubdatumEntity, matterId, siteId, context);
            if (!ObjectUtils.isEmpty(matterDatumEntity)) {
                matterDatumEntities.add(matterDatumEntity);
                success++;
            } else {
                fail++;
            }
        }
        if (!ObjectUtils.isEmpty(matterDatumEntities)) {
            this.getDao().insertBatch(matterDatumEntities);
            // this.save(matterDatumEntities, context);
        }
        String msg = "当前加入材料已存在！";
        if (pubIds.length == 1) {
            if (success > 0) {
                msg = "加入材料成功！";
            }
        } else if (pubIds.length > 1) {
            if (success > 0 && fail == 0) {
                msg = String.format("加入材料成功%d条!", success);
            } else if (success > 0 && fail > 0) {
                msg = String.format("加入材料成功%d条，重复加入材料%d条！", success, fail);
            } else if (success == 0 && fail > 0) {
                msg = String.format("重复加入材料%d条！", fail);
            }
        }
        return Rest.ok(msg);
    }


    private MatterDatumEntity updateOrSave(PubdatumEntity pubdatumEntity, Long matterId, Long siteId, Context context) {
        int count = this.count(new MatterDatumQuery().siteId(siteId).matterId(matterId).materialName(pubdatumEntity.getMaterialName()), context);
        if (count == 0) {
            MatterDatumEntity entity = new MatterDatumEntity();
            BeanUtils.copyProperties(pubdatumEntity, entity, new String[]{"id", "matterId"});
            entity.setSiteId(siteId);
            entity.setMatterId(matterId);
            return entity;
        }
        return null;
    }

    @Override
    public Rest<String> recommend(Long id, Long siteId, Context context) {
        MatterDatumEntity matterDatumEntity = this.get(id, context);
        if (matterDatumEntity == null) {
            throw new AppException("数据已更改,请重试");
        }
        String msg = "推荐成功！";
        List<MatterEntity> matterEntities = matterService.find(new MatterQuery().siteId(siteId), context);
        int recommendCount = 0;
        for (MatterEntity matterEntity : matterEntities) {
            recommendCount += this.count(new MatterDatumQuery().matterId(matterEntity.getId()).isRecommend(YesNoEnum.YES.getValue()), context);
        }
        if (matterDatumEntity.getIsRecommend() == YesNoEnum.NO.getValue()) {
            if (recommendCount >= GlobalSysInfo.getParamIntValue(Constant.PARAMS_RECOMMEND_COUNT, 7)) {
                throw new AppException("超过推荐个数!");
            }
            matterDatumEntity.setIsRecommend(YesNoEnum.YES.getValue());
        } else {
            matterDatumEntity.setIsRecommend(YesNoEnum.NO.getValue());
            msg = "取消推荐成功！";
        }
        this.update(matterDatumEntity, context);
        return Rest.ok(msg);
    }

    @Override
    protected void findAfter(MatterDatumEntity params, PageInfo pageInfo, Context context, List<MatterDatumEntity> list) throws AppException {
        list.stream().forEach(entity -> {
            MatterEntity matterEntity = matterService.get(entity.getMatterId(), context);
            if (!ObjectUtils.isEmpty(matterEntity)) {
                entity.setMatterNo(matterEntity.getMatterNo());
                entity.setMatterName(matterEntity.getMatterName());
            }
        });
        super.findAfter(params, pageInfo, context, list);
    }

}