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.dao.ComTalentAssignDAO;
import com.yiboshi.science.entity.*;
import com.yiboshi.science.enumeration.CommonEnum;
import com.yiboshi.science.param.dto.ComTalentAssignDTO;
import com.yiboshi.science.param.dto.ComTalentGroupDTO;
import com.yiboshi.science.param.query.ComTalentAssignQueryVO;
import com.yiboshi.science.service.*;
import lombok.AllArgsConstructor;
import org.apache.poi.hpsf.Decimal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 人才专家分配明细表 Service 实现类
 *
 * @author xujun
 * @version 2025-07-23
 */

@Service
@AllArgsConstructor
public class ComTalentAssignServiceImpl extends BaseServiceImpl<ComTalentAssignDAO, ComTalentAssignQueryVO, ComTalentAssignDTO, ComTalentAssign> implements ComTalentAssignService {

    @Autowired
    private ComTalentAssignDAO comTalentAssignDAO;
    @Autowired
    private ComBatchService comBatchService;

    @Autowired
    private ComTalentApplyService comTalentApplyService;

    @Autowired
    private ComEvaluationValueService comEvaluationValueService;

    @Autowired
    private ComExpertSpecService comExpertSpecService;

    @Autowired
    private SystemParameterService systemParameterService;

    @Override
    protected void setCriteriaForQuery(ComTalentAssignQueryVO vo, QueryWrapper<ComTalentAssignQueryVO> criteria) {
        if (Objects.nonNull(vo.getExpertId())) {
            criteria.eq("a.expert_id", vo.getExpertId());
        }
        if (Objects.nonNull(vo.getTalentId())) {
            criteria.eq("a.talent_id", vo.getTalentId());
        }
        if (Objects.nonNull(vo.getAssignYear())) {
            criteria.eq("a.assign_year", vo.getAssignYear());
        }
        if (Objects.nonNull(vo.getAuditState())) {
            criteria.eq("a.audit_state", vo.getAuditState());
        }
        if (Objects.nonNull(vo.getCertId())) {
            criteria.like("f.cert_id", vo.getCertId());
        }
        if (Objects.nonNull(vo.getPersonName())) {
            criteria.like("f.person_name", vo.getPersonName());
        }
        if (Objects.nonNull(vo.getExpertName())) {
            criteria.like("c.person_name", vo.getExpertName());
        }
        if (Objects.nonNull(vo.getSex())) {
            criteria.eq("f.sex", vo.getSex());
        }
        if (Objects.nonNull(vo.getAppUnitName())) {
            criteria.like("g.unit_name", vo.getAppUnitName());
        }
        if (Objects.nonNull(vo.getGroupId())) {
            criteria.eq("i.id", vo.getGroupId());
        }
    }

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

    @Transactional
    public String assignTalent(Map<String, Object> map) {
        List<String> talents = null;
        List<String> experts = null;
        if (!map.containsKey("type"))
            throw new BusinessException("参数错误");
        if (!map.containsKey("talents"))
            throw new BusinessException("参数错误");
        if (!map.containsKey("systemType"))
            throw new BusinessException("参数错误");
        Integer systemType = CommonEnum.systemType.num.getCode();
        if (map.containsKey("systemType")) {
            systemType = (int) map.get("systemType");
        }
        experts = (List<String>) map.get("experts");
        talents = (List<String>) map.get("talents");
        Integer reportYear = comBatchService.getReportYear(systemType, null);
        if (null == talents || talents.size() == 0 || null == experts || experts.size() == 0)
            throw new BusinessException("参数错误");
        return this.assignTalent(reportYear, talents, experts);
    }

    public String assignTalent(Integer year, List<String> talents, List<String> experts) {
        AtomicInteger allCount = new AtomicInteger(0);
        talents.forEach(e -> {
            AtomicInteger assignCount = new AtomicInteger(0);
            experts.forEach(f -> {
                if (!isDistribute(e, f)) {
                    ComTalentAssign assign = new ComTalentAssign();
                    assign.setTalentId(e);
                    assign.setExpertId(f);
                    //assign.setExpertType(comExpertSpecService.getExpertTypeByExpertId(f));
                    assign.setAssignYear(year);
                    this.insert(assign);
                    assignCount.incrementAndGet();
                    allCount.incrementAndGet();
                }
            });
            if (assignCount.get() > 0)
                updateAssignState(e);
        });
        if (allCount.get() == 0)
            throw new BusinessException("人才分配失败或专家已分配，请检查！");
        return allCount.getAndIncrement() + "";
    }

    public String deleteAssignExpert(String id) {
        ComTalentAssign comTalentAssign = this.getById(id);
        if (null == comTalentAssign)
            throw new BusinessException("分配记录已删除！");
        if (Objects.nonNull(comTalentAssign.getAuditState()) || !comTalentAssign.getAuditState().equals(0))
            throw new BusinessException("专家已评审，不允许删除！");
        this.deleteById(id);
        this.updateAssignState(comTalentAssign.getTalentId());
        comEvaluationValueService.deleteListByAssignId(id);
        return id;
    }

    public boolean isAssignByExpertId(String expertId) {
        ComTalentAssign model = new ComTalentAssign();
        model.setExpertId(expertId);
        List<ComTalentAssign> list = this.entityList(model);
        if (null != list && list.size() > 0) {
            return true;
        } else
            return false;
    }

    @Transactional
    public String expertEvaluation(ComTalentAssignDTO dto) {
        ComTalentAssign comTalentAssign = this.getById(dto.getId());
        if (null == comTalentAssign)
            throw new BusinessException("分配记录不存在或已删除！");
        ComTalentAssign entity = convert2Entity(dto);
        BigDecimal totalScore = comEvaluationValueService.insertListByAssignId(dto.getScoreList(), dto.getId());
        entity.setTotalScore(totalScore);
        this.update(entity);
        if (Objects.nonNull(dto.getAuditState())) {
            this.updateAssignState(entity.getTalentId());
        }
        return entity.getId();
    }

    public ComTalentAssignDTO getAssignExpertById(String id) {
        ComTalentAssignDTO dto = comTalentAssignDAO.getAssignExpertById(id);
//        if (null != dto) {
//            dto.setSpecList(comExpertSpecService.getListByExpertId(dto.getExpertId()));
//        }
        dto.setScoreList(comEvaluationValueService.getListByAssignId(id));
        return dto;
    }

    public List<AssignCount> getAssignCount(String expertId) {
        return comTalentAssignDAO.getAssignCount(expertId);
    }

    public List<ComTalentAssignDTO> getAssignExpertList(String talentId) {
        return comTalentAssignDAO.getAssignExpertList(talentId);
    }

    private boolean isDistribute(String talentId, String expertId) {
        ComTalentAssign comTalentAssign = new ComTalentAssign();
        comTalentAssign.setTalentId(talentId);
        comTalentAssign.setExpertId(expertId);
        comTalentAssign = this.getEntity(comTalentAssign);
        if (comTalentAssign != null)
            return true;
        else
            return false;
    }

    public void updateAssignState(String talentId) {
        Integer assignState;
        Integer completed;
        BigDecimal totalScore = new BigDecimal(0);
        BigDecimal averageScore = new BigDecimal(0);
        List<ComTalentAssignDTO> list = this.getAssignExpertList(talentId);
        if (null == list || list.size() == 0) {
            completed = 0;
            assignState = 0;
        } else {
            int personCount = 0;
            for (ComTalentAssignDTO obj : list) {
                if (Objects.nonNull(obj.getAuditState()) && obj.getAuditState().equals(2)) {
                    personCount++;
                }
                totalScore = totalScore.add(obj.getTotalScore());
            }
            if (personCount != 0) {
                BigDecimal personCountBD = BigDecimal.valueOf(personCount);
                averageScore = totalScore.divide(personCountBD, 2, RoundingMode.HALF_UP);
            }
            if (list.size() > personCount)
                completed = 0;
            else
                completed = 1;
            assignState = 1;
        }
        this.updateAssignState(talentId, assignState, completed, totalScore, averageScore);
    }


    public void updateAssignState(String talentId, Integer assignState, Integer completed, BigDecimal totalScore, BigDecimal averageScore) {
        ComTalentApply comTalentApply = new ComTalentApply();
        comTalentApply.setId(talentId);
        comTalentApply.setAssignState(assignState);
        comTalentApply.setCompleted(completed);
        comTalentApply.setTotalScore(totalScore);
        comTalentApply.setAverageScore(averageScore);
        comTalentApplyService.update(comTalentApply);
    }

    public List<ComTalentGroupDTO> getTalentGroupAssignById(String id, String expertId) {
        return comTalentAssignDAO.getTalentGroupAssignById(id, expertId);
    }
}
