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.ComTalentApply;
import com.yiboshi.science.entity.SystemParameter;
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 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;

    @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.projState.draft.getCode(),
                            CommonEnum.projState.waitSubmit.getCode());
                    break;
                case 2:
                    criteria.eq("talent_state", CommonEnum.projState.returnModify.getCode());
                    break;
                case 3:
                    criteria.in("talent_state",
                            CommonEnum.projState.toAudit.getCode(),
                            CommonEnum.projState.failed.getCode(),
                            CommonEnum.projState.pass.getCode(),
                            CommonEnum.projState.report.getCode(),
                            CommonEnum.projState.conclusion.getCode());
                    break;
                case 4:
                    break;
                case 5:
                    criteria.ge("talent_state", CommonEnum.projState.pass.getCode());
                    break;
                case 6:
                    criteria.ge("talent_state", CommonEnum.projState.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.projState.draft.getCode());
        dto.setAppPersonId(SecurityUserHolder.getPersonId());
        dto.setAppUnitId(SecurityUserHolder.getUnitId());

        return dto;
    }

    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));

        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.setSpec(comPersonDTO.getSpec());
        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);
    }
}