package cn.cslg.pas.service;

import cn.cslg.pas.common.core.base.DocFlag;
import cn.cslg.pas.common.model.dto.report.KeyWordModel;
import cn.cslg.pas.common.utils.SecurityUtils.LoginUtils;
import cn.cslg.pas.domain.ReportTemplate;
import cn.cslg.pas.domain.ReportTemplateLabel;
import cn.cslg.pas.common.model.vo.TemplateConditionVO;
import cn.cslg.pas.common.model.vo.TemplateVO;
import cn.cslg.pas.common.utils.FileUtils;
import cn.cslg.pas.common.utils.JsonUtils;
import cn.cslg.pas.common.utils.Response;
import cn.cslg.pas.mapper.ReportTemplateMapper;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * 模板表 服务类
 * </p>
 *
 * @author 王岩
 * @since 2022-03-31
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class ReportTemplateService extends ServiceImpl<ReportTemplateMapper, ReportTemplate> {

    private final ReportTemplateLabelService reportTemplateLabelService;
    private final FileUtils fileUtils;
    private final LoginUtils loginUtils;

    public IPage<ReportTemplate> getPageList(TemplateConditionVO params) {
        IPage<ReportTemplate> pageList = baseMapper.getPageList(new Page<>(params.getCurrent(), params.getSize()), params);
        List<Integer> templateIds = pageList.getRecords().stream().map(ReportTemplate::getId).collect(Collectors.toList());
        List<ReportTemplateLabel> reportTemplateLabelList = reportTemplateLabelService.getTemplateLabelByTemplateIds(templateIds);
        pageList.getRecords().forEach(template -> {
            template.setLabel(reportTemplateLabelList.stream().filter(item -> item.getTemplateId().equals(template.getId())).collect(Collectors.toList()));
        });
        return pageList;
    }

    public ReportTemplate getTemplateById(Integer id) {
        ReportTemplate reportTemplate = this.getById(id);
        reportTemplate.setLabel(reportTemplateLabelService.getTemplateLabelByTemplateIds(Collections.singletonList(id)));
        return reportTemplate;
    }

    public ReportTemplate getTemplateByName(String name, Integer projectId) {
        LambdaQueryWrapper<ReportTemplate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ReportTemplate::getName, name);
        if (projectId != null) {
            queryWrapper.eq(ReportTemplate::getProjectId, projectId);
        }
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    public String add(MultipartFile file, ReportTemplate reportTemplate) {
        reportTemplate.setProjectId(reportTemplate.getPermissions().equals(2) ? null : reportTemplate.getProjectId());
        ReportTemplate temp = this.getTemplateByName(reportTemplate.getName(), reportTemplate.getProjectId());
        if (temp != null) {
            return Response.error("模板名称已存在");
        }
        try {
            KeyWordModel keyWordModel = this.searchKeyWordFromDoc(file);
            if (keyWordModel != null) {
                reportTemplate.setPath(keyWordModel.getFileUrl());
                reportTemplate.setCreateBy(loginUtils.getId());
                reportTemplate.setCreateTime(new Date());
                reportTemplate.insert();
                List<TemplateVO> labelList = keyWordModel.getList();
                if (labelList == null || labelList.size() == 0) {
                    return Response.error();
                }
                List<ReportTemplateLabel> reportTemplateLabelList = new ArrayList<>();
                for (TemplateVO vo : labelList) {
                    ReportTemplateLabel reportTemplateLabel = new ReportTemplateLabel();
                    reportTemplateLabel.setCreateBy(loginUtils.getId());
                    reportTemplateLabel.setCreateTime(new Date());
                    reportTemplateLabel.setTemplateId(reportTemplate.getId());
                    reportTemplateLabel.setLabel(vo.getKey());
                    reportTemplateLabel.setName(vo.getText());
                    reportTemplateLabelList.add(reportTemplateLabel);
                }
                reportTemplateLabelService.saveOrUpdateBatch(reportTemplateLabelList);
                return Response.success(reportTemplate.getId());
            }
            return Response.error();
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.error();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public String edit(MultipartFile file, ReportTemplate reportTemplate) {
        reportTemplate.setProjectId(reportTemplate.getPermissions().equals(2) ? null : reportTemplate.getProjectId());
        ReportTemplate temp = this.getTemplateByName(reportTemplate.getName(), reportTemplate.getProjectId());
        if (temp != null && !temp.getId().equals(reportTemplate.getId())) {
            return Response.error("模板名称已存在");
        }
        try {
            if (file != null) {
                KeyWordModel templateWordDTO = this.searchKeyWordFromDoc(file);
                if (templateWordDTO != null) {
                    reportTemplate.setPath(templateWordDTO.getFileUrl());
                    List<TemplateVO> labelList = templateWordDTO.getList();
                    if (labelList != null && labelList.size() != 0) {
                        List<ReportTemplateLabel> reportTemplateLabelList = new ArrayList<>();
                        for (TemplateVO vo : labelList) {
                            ReportTemplateLabel reportTemplateLabel = new ReportTemplateLabel();
                            reportTemplateLabel.setCreateBy(loginUtils.getId());
                            reportTemplateLabel.setCreateTime(new Date());
                            reportTemplateLabel.setTemplateId(reportTemplate.getId());
                            reportTemplateLabel.setLabel(vo.getKey());
                            reportTemplateLabel.setName(vo.getText());
                            reportTemplateLabelList.add(reportTemplateLabel);
                        }
                        reportTemplate.setLabel(reportTemplateLabelList);
                    }
                }
            } else {
                reportTemplate.setLabel(JsonUtils.jsonToList(reportTemplate.getLabelConfig(), ReportTemplateLabel.class));
            }
            reportTemplateLabelService.deleteTemplateLabelByTemplateId(reportTemplate.getId());
            reportTemplateLabelService.saveOrUpdateBatch(reportTemplate.getLabel());
            reportTemplate.updateById();
            return Response.success(true);
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.error();
        }
    }

    @Transactional
    public String delete(Integer id) {
        this.removeById(id);
        reportTemplateLabelService.deleteTemplateLabelByTemplateId(id);
        return Response.success(true);
    }

    private KeyWordModel searchKeyWordFromDoc(MultipartFile file) throws IOException {
        //获取XWPFRun对象输出整个文本内容
        StringBuffer tempText = new StringBuffer();
        //解析docx模板并获取document对象
//        XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(fileUrl));
        XWPFDocument document = new XWPFDocument(file.getInputStream());
        //查找分类标签
        Pattern pattern = Pattern.compile(DocFlag.classify);
        //获取整个文本对象
        List<XWPFParagraph> allParagraph = document.getParagraphs();
        List<TemplateVO> classify = new ArrayList<>();
        for (XWPFParagraph xwpfParagraph : allParagraph) {
            List<XWPFRun> runList = xwpfParagraph.getRuns();
            for (XWPFRun xwpfRun : runList) {
                tempText.append(xwpfRun.toString());
            }
            if (tempText.length() > 0) {
                String text = tempText.toString();
                Matcher matcher = pattern.matcher(text);
                //发现匹配的字符串,存入set中
                boolean isFind = false;
                while (matcher.find()) {
                    String t = matcher.group();
                    TemplateVO tmp = new TemplateVO();
                    String indexStr = t.substring(t.indexOf("-") + 1, t.indexOf(":"));
                    tmp.setInd(Integer.parseInt(indexStr));
                    tmp.setKey("classify-" + indexStr);
                    tmp.setText(t.substring(t.indexOf(":") + 1, t.lastIndexOf("@")));
                    classify.add(tmp);
                    isFind = true;
                }
                if (isFind) {
                    for (int ii = runList.size() - 1; ii >= 0; ii--) {
                        xwpfParagraph.removeRun(ii);
                    }
                }
                tempText.setLength(0);
            } else {
                continue;
            }
        }
        if (classify.size() > 0) {
            String directoryName = fileUtils.createDirectory();
            String savePath = fileUtils.getSavePath(directoryName);
            String fileName = IdUtil.simpleUUID() + ".docx";
            FileOutputStream fos = new FileOutputStream(savePath + fileName);
            document.write(fos);
            fos.close();
            document.close();
            return new KeyWordModel(classify, fileUtils.getDirectory2(directoryName) + fileName);
        } else {
            System.out.println("未找到任何");
        }
        return null;
    }
}
