package com.yiboshi.science.service.impl;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.URLUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yiboshi.arch.exception.BusinessException;
import com.yiboshi.science.base.BaseServiceImpl;
import com.yiboshi.science.base.Pagination;
import com.yiboshi.science.config.security.SecurityUserHolder;
import com.yiboshi.science.dao.ComProjectConclusionDAO;
import com.yiboshi.science.entity.*;
import com.yiboshi.science.enumeration.CommonEnum;
import com.yiboshi.science.param.dto.*;
import com.yiboshi.science.param.query.ComProjectConclusionQueryVO;
import com.yiboshi.science.service.*;
import com.yiboshi.science.utils.DateUtils;
import com.yiboshi.science.utils.PdfUtil;
import org.apache.velocity.VelocityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * 结题信息表 Service 实现类
 *
 * @author lkl
 * @version 2021-08-26
 */
@Service
public class ComProjectConclusionServiceImpl extends BaseServiceImpl<ComProjectConclusionDAO, ComProjectConclusionQueryVO, ComProjectConclusionDTO, ComProjectConclusion> implements ComProjectConclusionService {

    @Autowired
    private ComProjectConclusionDAO comProjectConclusionDAO;
    @Autowired
    private ComConclusionThesisService comConclusionThesisService;
    @Autowired
    private ComConclusionResearchersService comConclusionResearchersService;
    @Autowired
    private ComConclusionFundsService comConclusionFundsService;
    @Autowired
    private ComConclusionCatalogService comConclusionCatalogService;
    @Autowired
    private ComFileService comFileService;

    @Autowired
    private ComProjectService comProjectService;

    @Autowired
    private ComProjectAuditService comProjectAuditService;

    @Autowired
    private ComProjectAuditNoteService comProjectAuditNoteService;

    @Override
    protected void setCriteriaForQuery(ComProjectConclusionQueryVO vo, QueryWrapper<ComProjectConclusionQueryVO> criteria) {
        if (Objects.nonNull(vo.getAppUnitId())) {
            criteria.eq("c.id", vo.getAppUnitId());
        }
        if (Objects.nonNull(vo.getAppPersonId())) {
            criteria.eq("d.id", vo.getAppPersonId());
        }
        if (Objects.nonNull(vo.getState())) {
            switch (vo.getState()) {
                case 1:
                    criteria.and(qw -> qw.in("a.state",
                                    CommonEnum.conclusionState.unFilled.getCode(),
                                    CommonEnum.conclusionState.draft.getCode(),
                                    CommonEnum.conclusionState.waitSubmit.getCode())
                            .or().isNull("a.state"));
                    break;
                case 2:
                    criteria.eq("a.state", CommonEnum.conclusionState.returnModify.getCode());
                    break;
                case 3:
                    criteria.in("a.state",
                            CommonEnum.conclusionState.report.getCode(),
                            CommonEnum.conclusionState.failed.getCode(),
                            CommonEnum.conclusionState.pass.getCode());
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public Pagination<ComProjectConclusionDTO> getListByPage(ComProjectConclusionQueryVO vo) {
        QueryWrapper criteria = new QueryWrapper();
        setCriteriaForQuery(vo, criteria);
        Page<ComProjectConclusionQueryVO> page = new Page<>(vo.getPageIndex(), vo.getPageSize());
        List<ComProjectConclusionDTO> dtoList = comProjectConclusionDAO.getListByPage(page, criteria).getRecords();
        return new Pagination<>(dtoList, page.getTotal(), vo.getPageSize());
    }

    public DataStatisticsDTO getCount(ComProjectConclusionDTO vo) {
        QueryWrapper criteria = new QueryWrapper();
        criteria.eq("b.app_person_id", vo.getAppPersonId());
        return comProjectConclusionDAO.getCount(criteria);
    }


    public ComProjectConclusionDTO getByProjId(String projId) {
        ComProjectConclusionDTO dto = comProjectConclusionDAO.getConclusionByProjId(projId);
        List<ComConclusionThesisDTO> thesisList = new ArrayList<>();
        List<ComConclusionResearchersDTO> researchersList = new ArrayList<>();
        List<ComConclusionFundsDTO> grant = new ArrayList<>();
        List<ComConclusionFundsDTO> finance = new ArrayList<>();
        List<ComConclusionFundsDTO> spending = new ArrayList<>();
        List<ComFileDTO> fileList = new ArrayList<>();
        List<ComConclusionCatalogDTO> catalogList = new ArrayList<>();
        // 附件列表
        if (null != dto && null != dto.getId()) {
            thesisList = comConclusionThesisService.getListByObjectId(dto.getId());
            if (null == thesisList || thesisList.size() == 0) {
                thesisList.add(new ComConclusionThesisDTO());
            }
            researchersList = comConclusionResearchersService.getListByObjectId(dto.getId());
            if (null == researchersList || researchersList.size() == 0) {
                researchersList.add(new ComConclusionResearchersDTO());
            }
            catalogList = comConclusionCatalogService.getListByObjectId(dto.getId());
            if (null == catalogList || catalogList.size() == 0) {
                catalogList.add(new ComConclusionCatalogDTO());
            }
            grant = comConclusionFundsService.getListByObjectId(dto.getId(), 1);
            finance = comConclusionFundsService.getListByObjectId(dto.getId(), 2);
            spending = comConclusionFundsService.getListByObjectId(dto.getId(), 3);
            fileList = comFileService.getListByObjectId(dto.getId(), CommonEnum.fileType.Conclusion.getCode());
        } else {
            thesisList.add(new ComConclusionThesisDTO());
            researchersList.add(new ComConclusionResearchersDTO());
            catalogList.add(new ComConclusionCatalogDTO());
        }
        dto.setThesisList(thesisList);
        dto.setResearchersList(researchersList);
        dto.setGrant(grant);
        dto.setFinance(finance);
        dto.setSpending(spending);
        dto.setFileList(fileList);
        dto.setCatalogList(catalogList);
        //审核记录列表
        List<ComProjectAuditNoteDTO> auditList = comProjectAuditNoteService.getListByObjectId(dto.getId());
        dto.setAuditList(auditList);
        return dto;
    }

    @Transactional
    public String save(ComProjectConclusionDTO dto) {
        if (Objects.nonNull(dto.getState()) && dto.getState().equals(CommonEnum.conclusionState.unFilled.getCode())) {
            dto.setState(CommonEnum.conclusionState.draft.getCode());
        }
        ComProjectConclusion conclusion = new ComProjectConclusion();
        conclusion.setProjId(dto.getProjId());
        conclusion = this.getEntity(conclusion);
        if (null != conclusion && conclusion.getState().equals(CommonEnum.conclusionState.report.getCode()))
            throw new BusinessException("结题信息已上报,不允许修改！");
        String id = "";
        if (null == conclusion) {
            conclusion = convert2Entity(dto);
            id = this.insert(conclusion);
        } else {
            conclusion = convert2Entity(dto);
            id = this.update(conclusion);
        }
        comConclusionThesisService.insertList(dto.getThesisList(), id);
        comConclusionResearchersService.insertList(dto.getResearchersList(), id);
        comConclusionFundsService.insertList(dto.getGrant(), id, 1);
        comConclusionFundsService.insertList(dto.getFinance(), id, 2);
        comConclusionFundsService.insertList(dto.getSpending(), id, 3);
        comFileService.insertList(dto.getFileList(), id, CommonEnum.fileType.Conclusion.getCode());
        comConclusionCatalogService.insertList(dto.getCatalogList(), id);
        return id;
    }

    @Transactional
    public String report(String projId, String auditUnitId, String treeCode) {
        ComProjectConclusion conclusion = new ComProjectConclusion();
        conclusion.setProjId(projId);
        conclusion = this.getEntity(conclusion);
        if (null == conclusion)
            throw new BusinessException("结题信息不存在！");
        if (!conclusion.getState().equals(CommonEnum.conclusionState.waitSubmit.getCode()) && !conclusion.getState().equals(CommonEnum.conclusionState.returnModify.getCode()))
            throw new BusinessException("当前状态不允许上报！");
        ComProjectConclusion modal = new ComProjectConclusion();
        modal.setId(conclusion.getId());
        modal.setState(CommonEnum.conclusionState.report.getCode());
        modal.setThesisState(CommonEnum.thesisState.pass.getCode());
        comProjectService.updateState(conclusion.getProjId(), CommonEnum.projState.report.getCode(), null);
        comProjectAuditService.report(DateUtils.getYear(), conclusion.getId(), 4, auditUnitId, treeCode);
        return this.update(modal);
    }

    @Transactional
    public String conclusionAudit(ComProjectAudit e) {
        if (Objects.isNull(e.getAuditObjectId()))
            throw new BusinessException("参数缺失！");
        ComProjectConclusion model = this.getById(e.getAuditObjectId());
        if (null == model)
            throw new BusinessException("审核对象不存在！");
        comProjectAuditService.audit(e);
        // 处理项目状态
        Integer state = null;
        if (e.getAuditResult().equals(CommonEnum.auditResult.pass.getCode())) {
            state = CommonEnum.conclusionState.pass.getCode();
            comProjectService.updateState(model.getProjId(), CommonEnum.projState.conclusion.getCode(), null);
        } else if (e.getAuditResult().equals(CommonEnum.auditResult.returnModify.getCode())) {
            state = CommonEnum.conclusionState.returnModify.getCode();
        } else {
            state = CommonEnum.conclusionState.failed.getCode();
        }
        ComProjectConclusion modal = new ComProjectConclusion();
        modal.setId(e.getAuditObjectId());
        modal.setState(state);
        return this.update(modal);
    }

    @Transactional
    public String thesisAudit(ComProjectAudit e) {
        if (Objects.isNull(e.getAuditObjectId()))
            throw new BusinessException("参数缺失！");
        ComProjectConclusion model = this.getById(e.getAuditObjectId());
        if (null == model)
            throw new BusinessException("审核对象不存在！");
        if (!model.getThesisState().equals(CommonEnum.thesisState.waitAudit.getCode()) && !model.getThesisState().equals(CommonEnum.thesisState.returnModify.getCode()))
            throw new BusinessException("已审核，请勿重复操作！");
        comProjectAuditService.audit(e);
        // 处理项目状态
        Integer state = null;
        if (e.getAuditResult().equals(CommonEnum.auditResult.pass.getCode())) {
            state = CommonEnum.thesisState.pass.getCode();
            comProjectService.updateState(model.getProjId(), CommonEnum.projState.conclusion.getCode(), null);
        } else if (e.getAuditResult().equals(CommonEnum.auditResult.returnModify.getCode())) {
            state = CommonEnum.thesisState.returnModify.getCode();
        } else {
            state = CommonEnum.thesisState.failed.getCode();
        }
        ComProjectConclusion modal = new ComProjectConclusion();
        modal.setId(e.getAuditObjectId());
        modal.setThesisState(state);
        return this.update(modal);
    }

    @Transactional
    public String saveThesis(ComProjectConclusionDTO dto, String auditUnitId) {
        ComProject comProject = comProjectService.entityById(dto.getProjId());
        if (null == comProject)
            throw new BusinessException("项目不存在或已删除！");
        ComProjectConclusion conclusion = new ComProjectConclusion();
        conclusion.setProjId(dto.getProjId());
        conclusion = this.getEntity(conclusion);
        if (null == conclusion)
            throw new BusinessException("项目未结题不允许操作！");
        if (!conclusion.getState().equals(CommonEnum.conclusionState.pass.getCode()))
            throw new BusinessException("项目未结题不允许操作！");
        comConclusionThesisService.insertList(dto.getThesisList(), conclusion.getId());

        int showIndex = 1;
        ComProjectAudit comProjectAudit = comProjectAuditService.getAudit(conclusion.getId(), auditUnitId, 5, CommonEnum.auditMethod.audit.getCode(), null);
        if (comProjectAudit != null) {
            showIndex = comProjectAudit.getShowIndex() + 1;
            comProjectAuditService.updateAudit(comProjectAudit.getId(), CommonEnum.auditResult.waitAudit.getCode(), "", showIndex, SecurityUserHolder.getPersonId(),new Date(),null,null,null,null);
        } else {
            comProjectAuditService.insertAudit(DateUtils.getYear(), 5, conclusion.getId(), CommonEnum.auditMethod.audit.getCode(),
                    auditUnitId, null, CommonEnum.auditResult.pass.getCode(), new Date(), 1, showIndex, SecurityUserHolder.getPersonId());
        }
        comProjectAuditNoteService.insertAuditNote(DateUtils.getYear(), 5, conclusion.getId(), CommonEnum.auditMethod.audit.getCode(),
                auditUnitId, null, CommonEnum.auditResult.waitAudit.getCode(), new Date(), 1, showIndex, SecurityUserHolder.getPersonId());
        ComProjectConclusion c = new ComProjectConclusion();
        c.setId(conclusion.getId());
        c.setThesisState(CommonEnum.thesisState.waitAudit.getCode());
        return this.update(c);
    }

    @Transactional
    public void createConclusionRecord(String projId, String auditUnitId) {
        ComProject comProject = comProjectService.entityById(projId);
        if (null == comProject)
            throw new BusinessException("项目不存在或已删除！");
        if (!comProject.getProjState().equals(CommonEnum.projState.pass.getCode()))
            throw new BusinessException("项目未批转立项或当前状态不允许操作！");
        String id = null;
        ComProjectConclusion conclusion = new ComProjectConclusion();
        conclusion.setProjId(projId);
        conclusion = this.getEntity(conclusion);
        if (null != conclusion && !conclusion.getState().equals(CommonEnum.conclusionState.unFilled.getCode())
                && !conclusion.getState().equals(CommonEnum.conclusionState.draft.getCode())
                && !conclusion.getState().equals(CommonEnum.conclusionState.waitSubmit.getCode()))
            throw new BusinessException("结题信息已上报！");
        if (null == conclusion) {
            conclusion = new ComProjectConclusion();
            conclusion.setProjId(projId);
            conclusion.setState(CommonEnum.conclusionState.pass.getCode());
            conclusion.setThesisState(CommonEnum.thesisState.unFilled.getCode());
            id = this.insert(conclusion);
        } else {
            ComProjectConclusion c = new ComProjectConclusion();
            c.setId(conclusion.getId());
            c.setState(CommonEnum.conclusionState.pass.getCode());
            c.setThesisState(CommonEnum.thesisState.unFilled.getCode());
            this.update(c);
        }
        comProjectService.updateState(projId, CommonEnum.projState.conclusion.getCode(), null);

        comProjectAuditService.insertAudit(comProject.getReportYear(), 4, id, CommonEnum.auditMethod.audit.getCode(),
                auditUnitId, null, CommonEnum.auditResult.pass.getCode(), new Date(), 1, 1, SecurityUserHolder.getPersonId());
        comProjectAuditNoteService.insertAuditNote(comProject.getReportYear(), 4, id, CommonEnum.auditMethod.audit.getCode(),
                auditUnitId, null, CommonEnum.auditResult.pass.getCode(), new Date(), 1, 1, SecurityUserHolder.getPersonId());
    }

    public void exportPdfById(HttpServletResponse response, String id) throws IOException {
        ComProjectAudit comProjectAudit = comProjectAuditService.getByObjIdAndUnitId(id, "ef2123fc-e7c0-4521-be59-244f9052253b");
        if (null == comProjectAudit || !comProjectAudit.getAuditResult().equals(CommonEnum.auditResult.pass.getCode()))
            throw new BusinessException("结题信息不存在或未审核通过！");
        response.reset();
        response.setContentType("application/pdf");
        String filename = System.currentTimeMillis() + ".pdf";
        response.addHeader("Content-Disposition", "inline; filename=" + URLUtil.encode(filename, CharsetUtil.CHARSET_UTF_8));
        VelocityContext context = new VelocityContext();
        if (null == comProjectAudit.getAuditDate())
            throw new BusinessException("结题信息未审核通过！");

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(comProjectAudit.getAuditDate());                    //放入Date类型数据

        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DATE);

        context.put("reportYear", comProjectAudit.getReportYear());
        context.put("year", calendar.get(Calendar.YEAR));
        context.put("month", month >= 10 ? month : "0" + month);
        context.put("day", day >= 10 ? day : "0" + day);

        try (ServletOutputStream outputStream = response.getOutputStream()) {
            PdfUtil.pdfFile(context, "/template/demo.html", outputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
