package com.yiboshi.science.service.impl;

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.ComTalentApplyDAO;
import com.yiboshi.science.entity.*;
import com.yiboshi.science.enumeration.CommonEnum;
import com.yiboshi.science.param.dto.*;
import com.yiboshi.science.param.query.ComTalentApplyQueryVO;
import com.yiboshi.science.service.*;
import com.yiboshi.science.utils.StringUtil;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 人才申请表 Service 实现类
 *
 * @author xujun
 * @version 2025-03-12
 */

@Service
@AllArgsConstructor
public class ComTalentApplyServiceImpl extends BaseServiceImpl<ComTalentApplyDAO, ComTalentApplyQueryVO, ComTalentApplyDTO, ComTalentApply> implements ComTalentApplyService {

    @Autowired
    private ComTalentApplyDAO comTalentApplyDAO;

    @Autowired
    private ComPersonService comPersonService;

    @Autowired
    private ComPersonResumeService comPersonResumeService;

    @Autowired
    private ComPersonScientificGainService comPersonScientificGainService;

    @Autowired
    private ComTalentMembersService comTalentMembersService;

    @Autowired
    private ComTalentBudgetService comTalentBudgetService;

    @Autowired
    private SystemParameterService systemParameterService;

    @Autowired
    private ComFileService comFileService;

    @Autowired
    private ComBatchService comBatchService;

    @Autowired
    private ComProjectAuditService comProjectAuditService;

    @Autowired
    private ComProjectAuditNoteService comProjectAuditNoteService;

    @Autowired
    private ComUnitService comUnitService;

    @Override
    protected void setCriteriaForQuery(ComTalentApplyQueryVO vo, QueryWrapper<ComTalentApplyQueryVO> criteria) {
        if (Objects.nonNull(vo.getCertId())) {
            criteria.like("b.cert_id", vo.getCertId());
        }
        if (Objects.nonNull(vo.getPersonName())) {
            criteria.like("b.person_name", vo.getPersonName());
        }
        if (Objects.nonNull(vo.getSex())) {
            criteria.eq("b.sex", vo.getSex());
        }
        if (Objects.nonNull(vo.getBirthday())) {
            criteria.eq("b.birthday", vo.getBirthday());
        }
        if (Objects.nonNull(vo.getTalentState())) {
            switch (vo.getTalentState()) {
                case 1:
                    criteria.in("talent_state",
                            CommonEnum.talentState.draft.getCode(),
                            CommonEnum.talentState.waitSubmit.getCode());
                    break;
                case 2:
                    criteria.eq("talent_state", CommonEnum.talentState.returnModify.getCode());
                    break;
                case 3:
                    criteria.in("talent_state",
                            CommonEnum.talentState.toAudit.getCode(),
                            CommonEnum.talentState.failed.getCode(),
                            CommonEnum.talentState.pass.getCode());
                    //CommonEnum.talentState.report.getCode(),
                    //CommonEnum.talentState.conclusion.getCode());
                    break;
                case 4:
                    break;
                case 5:
                    criteria.ge("talent_state", CommonEnum.talentState.pass.getCode());
                    break;
//                case 6:
//                    criteria.ge("talent_state", CommonEnum.talentState.report.getCode());
//                    break;
                default:
                    criteria.eq("talent_state", vo.getTalentState());
                    break;
            }
        }
        if (Objects.nonNull(vo.getAppUnitId())) {
            criteria.eq("a.app_unit_id", vo.getAppUnitId());
        }
        if (Objects.nonNull(vo.getAppPersonId())) {
            criteria.eq("a.app_person_id", vo.getAppPersonId());
        }
    }

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

    public DataStatisticsDTO getCount(ComTalentApply e) {
        QueryWrapper criteria = new QueryWrapper();
        this.notNullField(e, criteria);
        return comTalentApplyDAO.getCount(criteria);
    }

    private ComFileDTO configureFile(String FileExplain, int showIndex, Boolean isRequired, Boolean isTitle) {
        ComFileDTO file = new ComFileDTO();
        file.setFileType(CommonEnum.fileType.talentApply.getCode());
        file.setFileExplain(FileExplain);
        file.setShowIndex(showIndex);
        file.setRequired(true);
        file.setIsTitle(isTitle);
        if (!isRequired.equals(null))
            file.setIsRequired(isRequired);
        else
            file.setIsRequired(false);
        return file;
    }

    private List<ComFileDTO> configureFileList() {
        List<SystemParameter> parameterList = systemParameterService.getListByType(22);
        List<ComFileDTO> fileList = new ArrayList<>();
        parameterList.forEach(e -> {
            Boolean isTitle = false;
            if (e.getCode().equals("0"))
                isTitle = true;
            fileList.add(configureFile(e.getName(), e.getDisplayOrder(), e.getIsRequired(), isTitle));
        });
        return fileList;
    }

    public List<ComFileDTO> checkNecessaryAttachmentFile(List<ComFileDTO> fileList) {
        List<SystemParameter> parameterList = systemParameterService.getListByType(22);

        AtomicInteger allCount = new AtomicInteger(parameterList.size() + 1);
        fileList.forEach(e -> {
            AtomicInteger num = new AtomicInteger(1);
            int i = num.get();
            parameterList.forEach(p -> {
                if (null != e.getFileExplain() && e.getFileExplain().equals(p.getName())) {
                    e.setShowIndex(p.getDisplayOrder());
                    e.setRequired(p.getIsRequired());
                    if (p.getCode().equals("0"))
                        e.setIsTitle(true);
                    else
                        e.setIsTitle(false);
                    num.incrementAndGet();
                }
            });
            if (i == num.get()) {
                e.setShowIndex(allCount.get());
                e.setRequired(false);
                allCount.incrementAndGet();
            }
        });

        parameterList.forEach(p -> {
            List<ComFileDTO> findList = fileList.stream().filter(e -> null != e.getFileExplain() && e.getFileExplain().equals(p.getName())).collect(Collectors.toList());
            if (findList.size() == 0) {
                Boolean isTitle = false;
                if (p.getCode().equals("0"))
                    isTitle = true;
                ComFileDTO fileDTO = configureFile(p.getName(), p.getDisplayOrder(), p.getIsRequired(), isTitle);
                fileList.add(fileDTO);
            }
        });

        fileList.sort(Comparator.comparingInt(ComFileDTO::getShowIndex));

        return fileList;
    }

    public ComTalentApplyDTO getNewTalentApply() {
        ComTalentApplyDTO dto = new ComTalentApplyDTO();

        List<ComTalentBudgetDTO> bugetList = comTalentBudgetService.getList();
        dto.setBudgetList(bugetList);

        // 附件
        List<ComFileDTO> fileList = configureFileList();
        dto.setFileList(fileList);

        dto.setApplyFund(new BigDecimal(0.00));
        dto.setOtherFund(new BigDecimal(0.00));
        dto.setTotalFund(new BigDecimal(0.00));
        dto.setReportYear(comBatchService.getReportYear(null, CommonEnum.timeType.talentApply.getCode()));
        dto.setCompleteStatus("0,0,0,0,0,0");
        dto.setTalentState(CommonEnum.talentState.draft.getCode());
        dto.setAppPersonId(SecurityUserHolder.getPersonId());
        dto.setAppUnitId(SecurityUserHolder.getUnitId());

        ComPersonDTO comPersonDTO = comPersonService.getPersonById(SecurityUserHolder.getPersonId());

        dto.setPersonId(comPersonDTO.getId());
        dto.setCertId(comPersonDTO.getCertId());
        dto.setPersonName(comPersonDTO.getPersonName());
        dto.setProfession(comPersonDTO.getProfession());
        dto.setNation(comPersonDTO.getNation());
        dto.setBirthday(comPersonDTO.getBirthday());
        dto.setDegree(comPersonDTO.getDegree());
        dto.setDegreeTime(comPersonDTO.getDegreeTime());
        dto.setDegreeUnit(comPersonDTO.getDegreeUnit());
        dto.setGraduateTeacher(comPersonDTO.getGraduateTeacher());
        dto.setTitle(comPersonDTO.getTitle());
        dto.setSpec(comPersonDTO.getSpec());
        dto.setMobile(comPersonDTO.getMobile());
        dto.setEmail(comPersonDTO.getEmail());
        dto.setFax(comPersonDTO.getFax());

        return dto;
    }

    public Boolean isTalentExist() {
        ComTalentApply talent = new ComTalentApply();
        talent.setReportYear(comBatchService.getReportYear(null, CommonEnum.timeType.talentApply.getCode()));
        talent.setPersonId(SecurityUserHolder.getPersonId());
        talent = this.getEntity(talent);
        return talent == null ? false : true;
    }

    public ComTalentApplyDTO getTalentApplyById(String id) {
        ComTalentApplyDTO dto = comTalentApplyDAO.getById(id);
        if (null == dto)
            throw new BusinessException("人才申报记录不存在或已删除！");

        // 申报人才
        ComPersonDTO comPersonDTO = comPersonService.getPersonById(dto.getPersonId());
        if (null != comPersonDTO) {
            loadPersonInfo(dto, comPersonDTO);
        }

        List<ComTalentMembersDTO> memList = comTalentMembersService.getListByTalentId(dto.getId());
        dto.setMembersList(memList);

        List<ComTalentBudgetDTO> bugetList = comTalentBudgetService.getListByTalentId(dto.getId());
        if (null != bugetList && bugetList.size() > 0)
            dto.setBudgetList(bugetList);
        else {
            bugetList = comTalentBudgetService.getList();
            dto.setBudgetList(bugetList);
        }

        List<ComPersonResumeDTO> resumeList = comPersonResumeService.getListByTalentId(dto.getId());
        dto.setResumeList(resumeList);

        List<ComPersonScientificGainDTO> scientificList = comPersonScientificGainService.getListByTalentId(dto.getId());
        dto.setScientificList(scientificList);

        //附件列表
        List<ComFileDTO> fileList = comFileService.getListByObjectId(dto.getId(), CommonEnum.fileType.talentApply.getCode());
        if (null == fileList || fileList.size() == 0)
            fileList = configureFileList();
        else
            fileList = checkNecessaryAttachmentFile(fileList);
        dto.setFileList(fileList);

        if (Objects.isNull(dto.getApplyFund()))
            dto.setApplyFund(new BigDecimal(0.00));
        if (Objects.isNull(dto.getOtherFund()))
            dto.setOtherFund(new BigDecimal(0.00));
        if (Objects.isNull(dto.getTotalFund()))
            dto.setTotalFund(new BigDecimal(0.00));

        //审核记录列表
        List<ComProjectAuditNoteDTO> auditList = comProjectAuditNoteService.getListByObjectId(dto.getId());
        if (!StringUtil.isContainsRole(SecurityUserHolder.getRoles(), CommonEnum.systemRole.topGov.getCode().toString())) {
            List<ComProjectAuditNoteDTO> filterList = auditList.stream().filter(e -> !e.getUnitLevel().equals(1) || (e.getUnitLevel().equals(1) && e.getAuditResult().equals(CommonEnum.auditResult.returnModify.getCode()))).collect(Collectors.toList());
            dto.setAuditList(filterList);
            return dto;
        }
        dto.setAuditList(auditList);
        return dto;
    }

    private void loadPersonInfo(ComTalentApplyDTO dto, ComPersonDTO comPersonDTO) {
        dto.setPersonName(comPersonDTO.getPersonName());
        dto.setCertId(comPersonDTO.getCertId());
        dto.setSex(comPersonDTO.getSex());
        dto.setBirthday(comPersonDTO.getBirthday());
        dto.setNation(comPersonDTO.getNation());
        dto.setDegree(comPersonDTO.getDegree());
        dto.setDegreeTime(comPersonDTO.getDegreeTime());
        dto.setDegreeUnit(comPersonDTO.getDegreeUnit());
        dto.setGraduateTeacher(comPersonDTO.getGraduateTeacher());
        dto.setPoliticalParty(comPersonDTO.getPoliticalParty());
        //dto.setNationName(comPersonDTO.getNationName());
        //dto.setDegreeName(comPersonDTO.getDegreeName());
        dto.setTitle(comPersonDTO.getTitle());
        dto.setDuty(comPersonDTO.getDuty());
        dto.setProfession(comPersonDTO.getProfession());
        dto.setMobile(comPersonDTO.getMobile());
        dto.setFax(comPersonDTO.getFax());
        dto.setEmail(comPersonDTO.getEmail());
    }

    public String save(ComTalentApplyDTO dto) {
        String id = "";
        switch (dto.getStep()) {
            case 0://申报人基本情况
                id = talentSaveStep0(dto);
                break;
            case 1://申报人简历
                id = talentSaveStep1(dto);
                break;
            case 2://申报人科研成绩
                id = talentSaveStep2(dto);
                break;
            case 3://团队人员名单
                id = talentSaveStep3(dto);
                break;
            case 4://经费预算及培养计划和目标
                id = talentSaveStep4(dto);
                break;
            case 5://附件
                id = talentSaveStep5(dto);
                break;
        }
        return id;
    }

    private String talentSaveStep0(ComTalentApplyDTO dto) {
        String id = "";
        if (Objects.isNull(dto.getId()))
            id = InsertTalentBaseInfo(dto);
        else {
            ComTalentApply apply = this.entityById(dto.getId());
            if (null == apply) {
                id = InsertTalentBaseInfo(dto);
            } else
                id = UpdateProjectBaseInfo(dto);
        }
        return id;
    }

    @Transactional
    public String talentSaveStep1(ComTalentApplyDTO dto) {
        ComTalentApply comTalentApply = convert2Entity(dto);
        this.update(comTalentApply);

        List<ComPersonResumeDTO> ResumeList = dto.getResumeList();

        List<SystemParameter> ParameterList = systemParameterService.getListByType(18);

        for (SystemParameter p : ParameterList) {
            List<ComPersonResumeDTO> FindList = ResumeList.stream().filter(e -> p.getId().equals(e.getResumeType())).collect(Collectors.toList());
            if (null != FindList && FindList.size() > 0) {
                comPersonResumeService.insertList(FindList, dto.getId(), p.getId());
            }
        }

        return dto.getId();
    }

    @Transactional
    public String talentSaveStep2(ComTalentApplyDTO dto) {
        ComTalentApply comTalentApply = convert2Entity(dto);
        this.update(comTalentApply);

        List<ComPersonScientificGainDTO> ScientificGainList = dto.getScientificList();

        List<SystemParameter> ParameterList = systemParameterService.getListByType(19);

        for (SystemParameter p : ParameterList) {
            List<ComPersonScientificGainDTO> FindList = ScientificGainList.stream().filter(e -> p.getId().equals(e.getGainType())).collect(Collectors.toList());
            if (null != FindList && FindList.size() > 0) {
                comPersonScientificGainService.insertList(FindList, dto.getId(), p.getId());
            }
        }

        return dto.getId();
    }

    @Transactional
    public String talentSaveStep3(ComTalentApplyDTO dto) {
        ComTalentApply comTalentApply = convert2Entity(dto);
        this.update(comTalentApply);

        List<ComTalentMembersDTO> MemberList = dto.getMembersList();

        comTalentMembersService.insertList(MemberList, dto.getId());

        return dto.getId();
    }

    @Transactional
    public String talentSaveStep4(ComTalentApplyDTO dto) {
        ComTalentApply comTalentApply = convert2Entity(dto);
        this.update(comTalentApply);

        List<ComTalentBudgetDTO> BudgetList = dto.getBudgetList();

        comTalentBudgetService.insertList(BudgetList, dto.getId());

        return dto.getId();
    }

    @Transactional
    public String talentSaveStep5(ComTalentApplyDTO dto) {
        ComTalentApply comTalentApply = convert2Entity(dto);
        this.update(comTalentApply);
        // 附件
        comFileService.insertList(dto.getFileList(), dto.getId(), CommonEnum.fileType.talentApply.getCode());
        return dto.getId();
    }

    private String InsertTalentBaseInfo(ComTalentApplyDTO dto) {

        String PersonID = comPersonService.insertOrUpdate(dto);
        ComTalentApply apply = convert2Entity(dto);
        apply.setPersonId(PersonID);
        String id = this.insert(apply);
        return id;
    }

    private String UpdateProjectBaseInfo(ComTalentApplyDTO dto) {
        comPersonService.insertOrUpdate(dto);
        ComTalentApply apply = convert2Entity(dto);
        return this.update(apply);
    }

    /**
     * 删除人才申报信息
     *
     * @return
     */
    public String delete(String id) {
        ComTalentApply comTalentApply = this.entityById(id);
        if (null == comTalentApply)
            throw new BusinessException("人员申报信息不存在");
        if (comTalentApply.getTalentState() > CommonEnum.talentState.waitSubmit.getCode())
            throw new BusinessException("当前人员申报信息状态不能删除");

        // 人员申报参加人员
        comTalentMembersService.deleteByObjectId(id);
        // 培养经费
        comTalentBudgetService.deleteByObjectId(id);
        // 人才简历
        comPersonResumeService.deleteByObjectId(id);
        // 申报人才科研学术成绩表
        comPersonScientificGainService.deleteByObjectId(id);
        // 附件
        comFileService.deleteByObjectId(id);

        this.deleteById(id);
        return id;
    }

    public void report(ComProjectAudit model, String unitId, String treeCode) {
        ComTalentApply comTalentApply = this.entityById(model.getAuditObjectId());
        if (null == comTalentApply)
            throw new BusinessException("人才申报记录不存在或已删除！");
        if (!comTalentApply.getTalentState().equals(CommonEnum.talentState.waitSubmit.getCode()) && !comTalentApply.getTalentState().equals(CommonEnum.talentState.returnModify.getCode()))
            throw new BusinessException("人才申报记录已上报！");
        comProjectAuditService.report(comTalentApply.getReportYear(), model.getAuditObjectId(), model.getAuditType(), null, unitId, treeCode);

        // 更新人才申报记录状态
        comTalentApply.setTalentState(CommonEnum.projState.toAudit.getCode());
        this.update(comTalentApply);
    }

    @Transactional
    public void audit(ComProjectAuditDTO dto, String auditUnitId, String auditTreeCode) {
        if (Objects.isNull(dto.getAuditObjectId()))
            throw new BusinessException("参数缺失！");
        this.talentAudit(dto, auditUnitId, auditTreeCode);
    }

    @Transactional
    public void batchAudit(ComProjectAuditDTO dto, String auditUnitId, String auditTreeCode) {
        if (null != dto.getIdList() && dto.getIdList().size() > 0) {
            dto.getIdList().forEach((f) -> {
                dto.setId(f);
                this.talentAudit(dto, auditUnitId, auditTreeCode);
            });
        } else {
            throw new BusinessException("未选择项目！");
        }
    }

    @Transactional
    public void talentAudit(ComProjectAuditDTO dto, String auditUnitId, String auditTreeCode) {
        ComProjectAudit audit = comProjectAuditService.getById(dto.getId());
        if (null == audit)
            throw new BusinessException("审核记录不存在！");
        if (!audit.getAuditResult().equals(CommonEnum.auditResult.waitAudit.getCode()))
            throw new BusinessException("所选人才申报记录已审核，请刷新列表后重新选择！");
        ComTalentApply model = this.getById(audit.getAuditObjectId());

        if (null == model)
            throw new BusinessException("审核对象不存在！");
        ComUnit appUnit = comUnitService.getById(model.getAppUnitId());
        if (null == appUnit)
            throw new BusinessException("申报单位不存在,或已删除！");
        audit.setAuditResult(dto.getAuditResult());
        audit.setAuditContent(dto.getAuditContent());
        //  返回上级或下级单位Id, 最高级或个人返回 null
        String unitId = comProjectAuditService.audit(audit, appUnit.getTreeCode(), auditTreeCode);
        // 处理项目状态
        Integer talentState = null;
        String projNo = null;
        if (audit.getAuditResult().equals(CommonEnum.auditResult.pass.getCode())) {
            if (unitId == null) {
                talentState = CommonEnum.talentState.pass.getCode();
            }
        } else if (audit.getAuditResult().equals(CommonEnum.auditResult.returnModify.getCode())) {
            if (unitId == null)
                talentState = CommonEnum.talentState.returnModify.getCode();
        } else {
            talentState = CommonEnum.talentState.failed.getCode();
        }

        // 更新人才申报记录状态
        model.setTalentState(talentState);
        this.update(model);
    }

}
