/**
 * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xiaoniu.subsystem.business.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoniu.common.core.constant.Constants;
import com.xiaoniu.common.core.exception.ServiceException;
import com.xiaoniu.common.core.utils.DateUtils;
import com.xiaoniu.common.core.utils.StringUtils;
import com.xiaoniu.common.core.utils.bean.BeanValidators;
import com.xiaoniu.subsystem.business.domain.Project;
import com.xiaoniu.subsystem.business.domain.ProjectPersonnelInfo;
import com.xiaoniu.subsystem.business.domain.WaitDone;
import com.xiaoniu.subsystem.business.domain.dto.AddWaitDoneDTO;
import com.xiaoniu.subsystem.business.domain.dto.ProjectUserExamineDTO;
import com.xiaoniu.subsystem.business.domain.vo.ProjectPersonnelInfoVO;
import com.xiaoniu.subsystem.business.mapper.FlightMapper;
import com.xiaoniu.subsystem.business.mapper.ProjectMapper;
import com.xiaoniu.subsystem.business.mapper.ProjectPersonnelInfoMapper;
import com.xiaoniu.subsystem.business.service.IProjectPersonnelInfoService;
import com.xiaoniu.subsystem.business.service.IWaitDoneService;
import com.xiaoniu.subsystem.system.domain.Unit;
import com.xiaoniu.subsystem.system.mapper.UnitMapper;
import com.xiaoniu.subsystem.system.utils.IdCardCheckUtils;
import com.xiaoniu.subsystem.system.utils.MobileNumberValidator;
import jakarta.annotation.Resource;
import jakarta.validation.Validator;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.xiaoniu.common.security.utils.SecurityUtils.getUnitId;

/**
 * 计划人员信息表 服务实现类
 *
 * @author sst
 * @since 2024-11-26
 */
@Service
public class ProjectPersonnelInfoServiceImpl extends ServiceImpl<ProjectPersonnelInfoMapper, ProjectPersonnelInfo> implements IProjectPersonnelInfoService {

    protected final Validator validator;
    @Resource
    private IWaitDoneService waitDoneService;
    @Resource
    private UnitMapper unitMapper;
    @Resource
    private ProjectMapper projectMapper;
    @Resource
    private FlightMapper flightMapper;

    public ProjectPersonnelInfoServiceImpl(Validator validator) {
        this.validator = validator;
    }

    @Override
    public IPage<ProjectPersonnelInfoVO> selectProjectPersonnelInfoPage(IPage<ProjectPersonnelInfoVO> page,
                                                                        ProjectPersonnelInfoVO projectPersonnelInfo) {
        return page.setRecords(baseMapper.selectProjectPersonnelInfoPage(page, projectPersonnelInfo));
    }


    @Override
    public String importData(List<ProjectPersonnelInfo> list, Boolean isUpdateSupport, Long userId, Integer type) {
        if (CollectionUtils.isEmpty(list)) {
            throw new ServiceException("导入计划培训人员信息数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        List<Unit> unitList = unitMapper.selectList();
        Map<String, List<Unit>> collect = unitList.stream().collect(Collectors.groupingBy(Unit::getType));
        List<Unit> units = collect.get("0");
        if (CollectionUtils.isEmpty(units)) {
            throw new ServiceException("未查询到机关单位信息，请核对");
        }
        Map<String, Long> map = units.stream().collect(Collectors.toMap(Unit::getUnitName, Unit::getUnitId));
        List<Unit> units1 = collect.get("1");
        if (CollectionUtils.isEmpty(units)) {
            throw new ServiceException("未查询到承训单位信息，请核对");
        }
        Map<String, Long> map1 = units1.stream().collect(Collectors.toMap(Unit::getUnitName, Unit::getUnitId));
        for (ProjectPersonnelInfo d : list) {
            try {
                if (StringUtils.isBlank(d.getIdCard()) || StringUtils.isBlank(d.getUserName())) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、学员:" + d.getUserName() + " 导入失败：";
                    failureMsg.append(msg + "数据身份证号或者姓名为空，请核对");
                    continue;
                }
                if (null == map.get(d.getSendingUnitName())) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、学员:" + d.getUserName() + " 导入失败：";
                    failureMsg.append(msg + "未查询到机关单位:" + d.getSendingUnitName() + "，请核对");
                    continue;
                }
                if (0 == type && !Objects.equals(getUnitId(), map.get(d.getSendingUnitName()))) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、学员:" + d.getUserName() + " 导入失败：";
                    failureMsg.append(msg + "送训单位:" + d.getSendingUnitName() + "不是当前登录人单位，请核对");
                    continue;
                }
                if (null == map1.get(d.getTrainingUnitName())) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、学员:" + d.getUserName() + " 导入失败：";
                    failureMsg.append(msg + "未查询到承训单位:" + d.getTrainingUnitName() + "，请核对");
                    continue;
                }
                if (!IdCardCheckUtils.idCardNumberCheck(d.getIdCard())) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、学员:" + d.getUserName() + " 导入失败：";
                    failureMsg.append(msg + "身份证号有误:" + d.getIdCard() + "，请核对");
                    continue;
                }
                if (!MobileNumberValidator.isValidPhoneNumber(d.getPhonenumber())) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、学员:" + d.getUserName() + " 导入失败：";
                    failureMsg.append(msg + "电话号码有误:" + d.getPhonenumber() + "，请核对");
                    continue;
                }
                Project project = projectMapper.selectOne(new LambdaQueryWrapper<Project>()
                        .eq(Project::getFlightName, d.getFlightName())
                        .eq(Project::getTrainingTime, d.getTrainingTime())
                        .eq(Project::getYear, StringUtils.isBlank(d.getYear()) ?
                                DateUtils.parseDateToStr("yyyy", d.getTrainingTime()) : d.getYear())
                        .in(Project::getIsDistribution, 0, 1, 2)
                        .eq(Project::getCreateDept, map.get(d.getSendingUnitName())));
                if (null == project) {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、送训单位：" + d.getSendingUnitName()
                            + ",未查询到年度：" + (StringUtils.isBlank(d.getYear()) ?
                            DateUtils.parseDateToStr("yyyy", d.getTrainingTime()) : d.getYear()) +
                            "年,开训时间：" + DateUtils.dateTime(d.getTrainingTime()) +
                            ",专业（班次）名称：" + d.getFlightName() + " 的计划,或者计划状态为：已培训/作废,导入失败");
                    continue;
                }
                // 验证是否存在这个数据
                ProjectPersonnelInfo u = baseMapper.selectOne(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                        .eq(ProjectPersonnelInfo::getFlightName, d.getFlightName())
                        .eq(ProjectPersonnelInfo::getYear, StringUtils.isBlank(d.getYear()) ?
                                DateUtils.parseDateToStr("yyyy", d.getTrainingTime()) : d.getYear())
                        .eq(ProjectPersonnelInfo::getTrainingTime, d.getTrainingTime())
                        .eq(ProjectPersonnelInfo::getIdCard, d.getIdCard()));
                if (StringUtils.isNull(u)) {
                    BeanValidators.validateWithException(validator, d);
                    d.setYear(StringUtils.isBlank(d.getYear()) ?
                            DateUtils.parseDateToStr("yyyy", d.getTrainingTime()) : d.getYear());
                    d.setSendingUnitId(map.get(d.getSendingUnitName()));
                    d.setTrainingUnitId(map1.get(d.getTrainingUnitName()));
                    d.setFlightId(project.getFlightId());
                    d.setProjectId(project.getProjectId());
                    d.setIsAttend(StringUtils.isNotBlank(d.getIsAttend()) ? d.getIsAttend() : "0");
                    d.setIsFinishSchool(StringUtils.isNotBlank(d.getIsFinishSchool()) ? d.getIsFinishSchool() : "0");
                    d.setIsReport(type.toString());
                    d.setStatus(1);
                    d.setCreateUser(userId);
                    this.save(d);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、学员:" + d.getUserName() + "导入成功");
                } else if (isUpdateSupport) {
                    if (!Objects.equals(getUnitId(), map.get(d.getSendingUnitName()))){
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、年度：" + (StringUtils.isBlank(d.getYear()) ?
                                DateUtils.parseDateToStr("yyyy", d.getTrainingTime()) : d.getYear()) +
                                "年,开训时间：" + DateUtils.dateTime(d.getTrainingTime()) +
                                ",专业（班次）名称：" + d.getFlightName()+",计划下已存在学员:" + d.getUserName() +
                                "，导入失败：该学员已在:" + d.getSendingUnitName() + ",单位上报，请核对");
                        continue;
                    }
                    BeanValidators.validateWithException(validator, d);
                    d.setYear(StringUtils.isBlank(d.getYear()) ?
                            DateUtils.parseDateToStr("yyyy", d.getTrainingTime()) : d.getYear());
                    d.setSendingUnitId(map.get(d.getSendingUnitName()));
                    d.setTrainingUnitId(map1.get(d.getTrainingUnitName()));
                    d.setFlightId(project.getFlightId());
                    d.setProjectId(project.getProjectId());
                    d.setIsReport(type.toString());
                    d.setIsAttend(StringUtils.isNotBlank(d.getIsAttend()) ? d.getIsAttend() : u.getIsAttend());
                    d.setIsFinishSchool(StringUtils.isNotBlank(d.getIsFinishSchool()) ? d.getIsFinishSchool() : u.getIsFinishSchool());
                    d.setStatus(1);
                    d.setUpdateUser(userId);
                    d.setUserId(u.getUserId());
                    this.updateById(d);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、学员:" + d.getUserName() + "更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、学员:" + d.getUserName() + "已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、学员:" + d.getUserName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            if (10 < successNum) {
                successMsg = new StringBuilder();
                successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条.");
            } else {
                successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
            }
        }
        return successMsg.toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reportingAuthority(Long projectId) {
        if (baseMapper.selectCount(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                .eq(ProjectPersonnelInfo::getProjectId, projectId)) == 0) {
            throw new ServiceException("当前计划下无报名人数");
        }
        LambdaUpdateWrapper<ProjectPersonnelInfo> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(ProjectPersonnelInfo::getProjectId, projectId);
        // wrapper.eq(ProjectPersonnelInfo::getIsDeleted, Constants.ZERO);
        wrapper.set(ProjectPersonnelInfo::getIsReport, Constants.ONE);
        int count = baseMapper.update(wrapper);
        Unit unit = unitMapper.selectById(getUnitId());
        if (StringUtils.isNotNull(unit)) {
            // 查询班次信息
            Project project = projectMapper.selectById(projectId);
            if (null != project) {
                projectMapper.updateById(project.setStatus(1));
                Project one = projectMapper.selectOne(new LambdaQueryWrapper<Project>()
                        .eq(Project::getFlightId, project.getFlightId())
                        .eq(Project::getTrainingTime, project.getTrainingTime())
                        .eq(Project::getYear, project.getYear())
                        .eq(Project::getFlightName, project.getFlightName())
                        .eq(Project::getParentId, 0)
                        .eq(Project::getMainUnitId, project.getMainUnitId()));
                waitDoneService.insertWaitDone(new AddWaitDoneDTO()
                        .setFlightId(project.getFlightId())
                        .setFlightName(project.getFlightName())
                        .setFlightCode(project.getFlightCode())
                        .setWaitDoneUnit(project.getMainUnitId())
                        .setBusinessId(one.getProjectId())
                        .setWaitDoneMessage("计划上报代办，点击查看详情")
                        .setType("3")
                        .setArgument("")
                        // 添加代办信息
                        .setSkip(""));
            }
        }
        return count > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean examine(ProjectUserExamineDTO dto) {
        ProjectPersonnelInfo projectPersonnelInfo = baseMapper.selectById(dto.getUserId());
        if (StringUtils.isNull(projectPersonnelInfo)) {
            throw new ServiceException("当前信息不存在");
        }
        projectPersonnelInfo.setStatus(dto.getStatus());
        projectPersonnelInfo.setReason(dto.getReason());
        int count = baseMapper.updateById(projectPersonnelInfo);
        // 添加代办信息
        AddWaitDoneDTO addWaitDoneDTO = new AddWaitDoneDTO();
        addWaitDoneDTO.setWaitDoneUnit(projectPersonnelInfo.getSendingUnitId());
        addWaitDoneDTO.setBusinessId(projectPersonnelInfo.getProjectId());
        addWaitDoneDTO.setWaitDoneUser(dto.getUserId());
        addWaitDoneDTO.setWaitDoneMessage("人员审核代办，点击查看详情");
        addWaitDoneDTO.setType("4");
        addWaitDoneDTO.setArgument("");
        addWaitDoneDTO.setFlightId(projectPersonnelInfo.getFlightId());
        addWaitDoneDTO.setFlightName(projectPersonnelInfo.getFlightName());
        addWaitDoneDTO.setSkip("");
        waitDoneService.insertWaitDone(addWaitDoneDTO);

        // 判断是否审核全部人员
        Long num = baseMapper.selectCount(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                .eq(ProjectPersonnelInfo::getProjectId, projectPersonnelInfo.getProjectId())
                .eq(ProjectPersonnelInfo::getIsDeleted, Constants.ZERO)
                .ne(ProjectPersonnelInfo::getStatus, Constants.ONE));
        if (0L == num) {
            waitDoneService.update(new LambdaUpdateWrapper<WaitDone>()
                    .eq(WaitDone::getType, Constants.THREE)
                    .set(WaitDone::getStatus, Constants.ONE));
        }
        return count > 0;
    }
}
