package com.cslg.ppa.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cslg.ppa.common.core.auth.Response;
import com.cslg.ppa.common.exception.ExceptionEnum;
import com.cslg.ppa.common.exception.XiaoShiException;
import com.cslg.ppa.common.utils.DateUtil;
import com.cslg.ppa.common.utils.FileUtils;
import com.cslg.ppa.dto.*;
import com.cslg.ppa.entity.*;
import com.cslg.ppa.entity.commom.Records;
import com.cslg.ppa.mapper.ArticleInfoMapper;
import com.cslg.ppa.mapper.AssoReportArticleMapper;
import com.cslg.ppa.mapper.ReportMapper;
import com.cslg.ppa.service.commom.FileManagerService;
import com.cslg.ppa.vo.*;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.plugin.toc.TOCRenderPolicy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.ddr.poi.html.HtmlRenderPolicy;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class ReportService extends ServiceImpl<ReportMapper, Report> {

    @Autowired
    private ReportTempleService reportTempleService;
    @Autowired
    private FileUtils fileUtils;
    @Autowired
    private FileManagerService fileManagerService;
    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private AssoReportArticleMapper assoReportArticleMapper;
    @Autowired
    private ArticleInfoMapper articleInfoMapper;

    private static final List<String> SPECIAL_KEYWORDS = Arrays.asList("活动", "研讨", "座谈会", "举办", "举行", "培训",
            "课堂", "论证会", "讨论", "调研", "会议", "召开","招聘","主题","讲座","大会","专利代理师","博览会","资助","参评","年会","参观","学习");

    public String selectReportList(SelectReportListDTO vo) {
        LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(vo.getReportName())) {
            wrapper.eq(Report::getReportName, vo.getReportName());
        }
        wrapper.orderByDesc(Report::getCreateTime);
        Page<Report> page = new Page<>(vo.getPageNum(), vo.getPageSize());
        Page<Report> reportPage = reportMapper.selectPage(page, wrapper);
        List<Report> reports = reportPage.getRecords();
        List<SelectReportListVO> reportList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(reports)) {
            for (Report report : reports) {
                SelectReportListVO reportVO = new SelectReportListVO();
                reportVO.setReportId(report.getId());
                reportVO.setReportName(report.getReportName());
                reportVO.setApprove(report.getApprove());
                reportVO.setCreator(report.getCreator());
                reportVO.setApproveStatus(report.getApproveStatus());
                reportVO.setCreateTime(report.getCreateTime());
                reportVO.setApproveTime(report.getApproveTime());
                reportList.add(reportVO);
            }
        }
        Records records = new Records();
        long total = reportPage.getTotal();
        records.setCurrent(vo.getPageNum());
        records.setTotal(total);
        records.setSize(vo.getPageSize());
        records.setData(reportList);
        return Response.success(records);
    }

    public String selectReportDetail(ReportIdDTO vo) {
        Report report = reportMapper.selectById(vo.getReportId());
        return Response.success(report);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    public Integer addReport(ReportDTO vo) {
        String reportName = vo.getReportName();
        if (StringUtils.isEmpty(reportName)) {
            throw new XiaoShiException(ExceptionEnum.BUSINESS_ERROR, "报告名称不可为空");
        }
        //todo 创建者字段后续再加
        Report report = new Report();
        report.setReportName(vo.getReportName());
        report.insert();
        List<Integer> articleIds = vo.getArticleIds();
        if (!CollectionUtils.isEmpty(articleIds)) {
            for (Integer articleId : articleIds) {
                Long count = assoReportArticleMapper.selectCount(new LambdaQueryWrapper<AssoReportArticle>()
                        .eq(AssoReportArticle::getReportId,report.getId())
                        .eq(AssoReportArticle::getArticleId, articleId)
                        .eq(AssoReportArticle::getIfUse, 1));
                if (count > 1) {
                    continue;
                }
                AssoReportArticle assoReportArticle = new AssoReportArticle();
                assoReportArticle.setReportId(report.getId());
                assoReportArticle.setArticleId(articleId);
                assoReportArticle.insert();
            }
        }
        return report.getId();
    }

    public Integer editReport(ReportDTO vo) {
        Report report = reportMapper.selectById(vo.getReportId());
        report.setReportName(vo.getReportName());
        report.updateById();
        return report.getId();
    }

    public void deleteReport(ReportIdDTO vo) {
        List<Integer> reportIds = vo.getReportIds();
        if (!CollectionUtils.isEmpty(reportIds)) {
            for (Integer reportId : reportIds) {
                //删除关联
                List<AssoReportArticle> assoReportArticles = assoReportArticleMapper.selectList(new LambdaQueryWrapper<AssoReportArticle>()
                        .eq(AssoReportArticle::getReportId, reportId));
                if (!CollectionUtils.isEmpty(assoReportArticles)) {
                    List<Integer> collect = assoReportArticles.stream().map(BaseEntity::getId).collect(Collectors.toList());
                    assoReportArticleMapper.deleteBatchIds(collect);
                }
                //删除报告
                reportMapper.deleteById(reportId);
            }
        }
    }

    public List<SelectAssoReportArticleVO> selectAssoReportArticleList(SelectAssoReportArticleDTO vo) {
        Integer reportId = vo.getReportId();
        List<SelectAssoReportArticleVO> articleVOS = reportMapper.selectAssoReportArticleList(reportId);
        if (CollectionUtils.isEmpty(articleVOS)) {
            articleVOS = new ArrayList<>();
        }
        return articleVOS;
    }

    public Integer addArticleToReport(ReportDTO vo) {
        //todo 创建者字段后续再加
        Integer reportId = vo.getReportId();
        List<Integer> articleIds = vo.getArticleIds();
        if (!CollectionUtils.isEmpty(articleIds)) {
            for (Integer articleId : articleIds) {
                Long count = assoReportArticleMapper.selectCount(new LambdaQueryWrapper<AssoReportArticle>()
                        .eq(AssoReportArticle::getReportId,reportId)
                        .eq(AssoReportArticle::getArticleId, articleId)
                        .eq(AssoReportArticle::getIfUse, 1));
                if (count > 1) {
                    continue;
                }
                AssoReportArticle assoReportArticle = new AssoReportArticle();
                assoReportArticle.setReportId(reportId);
                assoReportArticle.setArticleId(articleId);
                assoReportArticle.insert();
            }
        }
        return reportId;
    }

    public Integer removeAssoArticleReport(AssoReportArticleIdDTO vo) {
        Integer assoId = vo.getAssoId();
        AssoReportArticle assoReportArticle = assoReportArticleMapper.selectById(assoId);
        assoReportArticle.setIfUse(0);
        assoReportArticle.updateById();
        return assoId;
    }

    public String exportReport(Integer reportId) {
        List<SelectAssoReportArticleVO> articleVOS = reportMapper.selectAssoReportArticleList(reportId);
        List<ExportReportVO> reportVOS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(articleVOS)) {
            Map<String, List<SelectAssoReportArticleVO>> map = articleVOS.stream().collect(Collectors.groupingBy(SelectAssoReportArticleVO::getCategoryName));
            if (!CollectionUtils.isEmpty(map)) {
                for (String key : map.keySet()) {
                    ExportReportVO reportVO = new ExportReportVO();
                    reportVO.setCategoryName(key);
                    List<SelectAssoReportArticleVO> reportArticleVOS = map.get(key);
                    List<ExportReportDetailVO> detailVOS = new ArrayList<>();
                    if (!CollectionUtils.isEmpty(reportArticleVOS)) {
                        int i = 1;
                        for (SelectAssoReportArticleVO reportArticleVO : reportArticleVOS) {
                            ExportReportDetailVO detailVO = new ExportReportDetailVO();
                            detailVO.setTitle(i + "、" + reportArticleVO.getTitle());
                            detailVO.setDigest(reportArticleVO.getDigest());
                            String htmlLink = "<a href='" + reportArticleVO.getArticleUrl() + "'>" + reportArticleVO.getArticleUrl() + "</a>";
                            detailVO.setArticle_url(htmlLink);
                            detailVOS.add(detailVO);
                            i++;
                        }
                    }
                    reportVO.setDetailVOS(detailVOS);
                    reportVOS.add(reportVO);
                }
            }
        }

        List<ExportReportDetailVO> list = new ArrayList<>();
        List<ExportReportDetailVO> list1 = new ArrayList<>();
        List<ExportReportDetailVO> list2 = new ArrayList<>();
        List<ExportReportDetailVO> list3 = new ArrayList<>();
        List<ExportReportDetailVO> list4 = new ArrayList<>();
        if (!CollectionUtils.isEmpty(reportVOS)) {
            for (ExportReportVO reportVO : reportVOS) {
                String categoryName = reportVO.getCategoryName();
                if (StringUtils.equals(categoryName, "国家知识产权局")) {
                    list.addAll(reportVO.getDetailVOS());
                } else if (StringUtils.equals(categoryName, "地方相关法律法规")) {
                    list1.addAll(reportVO.getDetailVOS());
                } else if (StringUtils.equals(categoryName, "判例")) {
                    list2.addAll(reportVO.getDetailVOS());
                } else if (StringUtils.equals(categoryName, "国外相关资讯")) {
                    list3.addAll(reportVO.getDetailVOS());
                } else if (StringUtils.equals(categoryName, "行业资讯")) {
                    list4.addAll(reportVO.getDetailVOS());
                }
            }
        }

        Map<String, Object> map = new HashMap<>();
        map.put("country_list", list);
        map.put("local_list", list1);
        map.put("case_list", list2);
        map.put("foreign_list", list3);
        map.put("business_list", list4);
        ReportTemple reportTemplate = reportTempleService.getById(1);
        String templateFilePath = fileUtils.getPath(reportTemplate.getTemplatePath());
        Report report = this.getById(reportId);
        String reportName = report.getReportName();
        //生成文档
        String fileGuid = null;
        try {
            fileGuid = this.generateReportFile(map, templateFilePath, reportName);
            //todo 后续添加导出记录
        } catch (Exception e) {
            throw new XiaoShiException(ExceptionEnum.BUSINESS_ERROR, "导出资讯报告失败");
        }
        return fileGuid;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    public String oneClickExport() {
        OneClickExportDTO vo = new OneClickExportDTO();
        vo.setBeginTime(DateUtil.getFirstDayOfMonthStr());
        vo.setEndTime(DateUtil.getLastDayOfMonthStr());
        List<OneClickExportVO> articleVOS = articleInfoMapper.selectArticleList(vo);
        List<ExportReportVO> reportVOS = new ArrayList<>();
        List<Integer> articleIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(articleVOS)) {
            Map<String, List<OneClickExportVO>> map = articleVOS.stream().collect(Collectors.groupingBy(OneClickExportVO::getCategoryName));
            if (!CollectionUtils.isEmpty(map)) {
                for (String key : map.keySet()) {
                    ExportReportVO reportVO = new ExportReportVO();
                    reportVO.setCategoryName(key);
                    List<OneClickExportVO> reportArticleVOS = map.get(key);
                    List<ExportReportDetailVO> detailVOS = new ArrayList<>();
                    if (!CollectionUtils.isEmpty(reportArticleVOS)) {
                        int i = 1;
                        for (OneClickExportVO reportArticleVO : reportArticleVOS) {
                            Integer categoryId = reportArticleVO.getCategoryId();
                            String title = reportArticleVO.getTitle();
                            if (categoryId == 2 && SPECIAL_KEYWORDS.stream().anyMatch(title::contains)) {
                                continue;
                            }
                            ExportReportDetailVO detailVO = new ExportReportDetailVO();
                            detailVO.setTitle(i + "、" + title);
                            detailVO.setDigest(reportArticleVO.getDigest());
                            String htmlLink = "<a href='" + reportArticleVO.getArticleUrl() + "'>" + reportArticleVO.getArticleUrl() + "</a>";
                            detailVO.setArticle_url(htmlLink);
                            detailVOS.add(detailVO);
                            articleIds.add(reportArticleVO.getArticleId());
                            i++;
                        }
                    }
                    reportVO.setDetailVOS(detailVOS);
                    reportVOS.add(reportVO);
                }
            }
        }

        String nowDateStr = DateUtil.getNowDateStr();
        String year = nowDateStr.substring(0, 4);
        String month = nowDateStr.substring(4, 6);
        String reportName = nowDateStr + "-知识产权相关法律法规资讯整理（威世博" + year + "年第" + month + "月）-v1r00";
        //添加报告
        ReportDTO reportDTO = new ReportDTO();
        reportDTO.setReportName(reportName);
        reportDTO.setArticleIds(articleIds);
        System.out.println(articleIds.size());
        this.addReport(reportDTO);

        List<ExportReportDetailVO> list = new ArrayList<>();
        List<ExportReportDetailVO> list1 = new ArrayList<>();
        List<ExportReportDetailVO> list2 = new ArrayList<>();
        List<ExportReportDetailVO> list3 = new ArrayList<>();
        List<ExportReportDetailVO> list4 = new ArrayList<>();
        if (!CollectionUtils.isEmpty(reportVOS)) {
            for (ExportReportVO reportVO : reportVOS) {
                String categoryName = reportVO.getCategoryName();
                if (StringUtils.equals(categoryName, "国家知识产权局")) {
                    list.addAll(reportVO.getDetailVOS());
                } else if (StringUtils.equals(categoryName, "地方相关法律法规")) {
                    list1.addAll(reportVO.getDetailVOS());
                } else if (StringUtils.equals(categoryName, "判例")) {
                    list2.addAll(reportVO.getDetailVOS());
                } else if (StringUtils.equals(categoryName, "国外相关资讯")) {
                    list3.addAll(reportVO.getDetailVOS());
                } else if (StringUtils.equals(categoryName, "行业资讯")) {
                    list4.addAll(reportVO.getDetailVOS());
                }
            }
        }

        Map<String, Object> map = new HashMap<>();
        map.put("country_list", list);
        map.put("local_list", list1);
        map.put("case_list", list2);
        map.put("foreign_list", list3);
        map.put("business_list", list4);
        ReportTemple reportTemplate = reportTempleService.getById(1);
        String templateFilePath = fileUtils.getPath(reportTemplate.getTemplatePath());
        //生成文档
        String fileGuid = null;
        try {
            fileGuid = this.generateReportFile(map, templateFilePath, reportName);
            //todo 后续添加导出记录
        } catch (Exception e) {
            throw new XiaoShiException(ExceptionEnum.BUSINESS_ERROR, "导出资讯报告失败");
        }
        return fileGuid;
    }

    public String generateReportFile(Map<String, Object> map, String templateFilePath, String name) throws Exception {
        XWPFTemplate xwpfTemplate = this.getHtmlTemplate(map, templateFilePath);
        String fileName = name + ".docx";
        String directoryName = fileUtils.createDirectory();
        String outPath = fileUtils.getSavePath(directoryName) + fileName;
        File file = new File(outPath);
        // 生成word保存在指定目录
        xwpfTemplate.writeToFile(outPath);
        xwpfTemplate.close();
        List<String> ids = fileManagerService.uploadFileGetGuid2(Collections.singletonList(file));
        if (CollectionUtils.isEmpty(ids)) {
            throw new XiaoShiException("保存记录失败");
        }
        return ids.get(0);
    }

    private XWPFTemplate getHtmlTemplate(Map<String, Object> map, String filePath) {
        XWPFTemplate template = null;
        try {
            HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
            ConfigureBuilder configureBuilder = Configure.builder().useSpringEL(false);
            configureBuilder.bind("article_url", htmlRenderPolicy);
            Configure configure = configureBuilder.build();
            template = XWPFTemplate.compile(filePath, configure).render(map);
        } catch (Exception e) {
            e.printStackTrace();
            throw new XiaoShiException(ExceptionEnum.BUSINESS_ERROR, "未匹配到模版文件");
        }
        return template;
    }

}
