/**
 * 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.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.Demand;
import com.xiaoniu.subsystem.business.domain.DemandSignUp;
import com.xiaoniu.subsystem.business.domain.DemandTotal;
import com.xiaoniu.subsystem.business.domain.Flight;
import com.xiaoniu.subsystem.business.domain.vo.DemandVO;
import com.xiaoniu.subsystem.business.domain.vo.ProjectUnitVO;
import com.xiaoniu.subsystem.business.mapper.DemandMapper;
import com.xiaoniu.subsystem.business.service.IDemandService;
import com.xiaoniu.subsystem.business.service.IDemandSignUpService;
import com.xiaoniu.subsystem.business.service.IDemandTotalService;
import com.xiaoniu.subsystem.business.service.IFlightService;
import com.xiaoniu.subsystem.system.domain.Unit;
import com.xiaoniu.subsystem.system.service.ISysDictDataService;
import com.xiaoniu.subsystem.system.service.ISysUserService;
import com.xiaoniu.subsystem.system.service.IUnitService;
import jakarta.validation.Validator;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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

/**
 * 培训需求管理表 服务实现类
 *
 * @author sst
 * @since 2024-11-26
 */
@Service
public class DemandServiceImpl extends ServiceImpl<DemandMapper, Demand> implements IDemandService {

    protected final Validator validator;
    protected final IUnitService unitService;
    protected final ISysUserService sysUserService;
    protected final IDemandSignUpService demandSignUpService;
    protected final IDemandTotalService demandTotalService;
    protected final IFlightService flightService;
    protected final ISysDictDataService dictDataService;

    public DemandServiceImpl(Validator validator, IUnitService unitService,
                             ISysUserService sysUserService, IDemandSignUpService demandSignUpService,
                             IDemandTotalService demandTotalService, IFlightService flightService, ISysDictDataService dictDataService) {
        this.validator = validator;
        this.unitService = unitService;
        this.sysUserService = sysUserService;
        this.demandSignUpService = demandSignUpService;
        this.demandTotalService = demandTotalService;
        this.flightService = flightService;
        this.dictDataService = dictDataService;
    }

    @Override
    public IPage<DemandVO> selectDemandPage(IPage<DemandVO> page, DemandVO demand) {
        return page.setRecords(baseMapper.selectDemandPage(page, demand));
    }

    @Override
    public String importData(List<Demand> list, Boolean isUpdateSupport) {
        if (CollectionUtils.isEmpty(list)) {
            throw new ServiceException("导入培训需求信息数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        Unit unit = unitService.getById(getUnitId());
        List<Unit> unitList = unitService.list();
        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 (Demand d : list) {
            try {
                if (null == map.get(d.getMainUnitName())) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、单位:" + d.getMainUnitName() +
                            ",开训时间:" + DateUtils.dateTime(d.getTrainingTime()) + "，专业:" + d.getFlightName() + ",导入失败：";
                    failureMsg.append(msg + "未查询到机关单位:" + d.getMainUnitName() + "，请核对");
                    continue;
                }
                if (null == map1.get(d.getTrainingUnitName())) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、单位:" + d.getTrainingUnitName() +
                            ",开训时间:" + DateUtils.dateTime(d.getTrainingTime()) + "，专业:" + d.getFlightName() + ",导入失败：";
                    failureMsg.append(msg + "未查询到承训单位:" + d.getTrainingUnitName() + "，请核对");
                    continue;
                }
                // 验证是否存在这个数据
                Demand u = baseMapper.selectOne(new LambdaQueryWrapper<Demand>()
                        .eq(Demand::getFlightName, d.getFlightName())
                        .eq(Demand::getTrainingTime, d.getTrainingTime())
                        .eq(Demand::getParentId, 0)
                        .eq(Demand::getYear, d.getYear()));
                if (StringUtils.isNull(u)) {
                    BeanValidators.validateWithException(validator, d);
                    d.setIsIssue("0");
                    d.setMainUnitId(StringUtils.isBlank(d.getMainUnitName()) ?
                            unit.getUnitId() : map.get(d.getMainUnitName()));
                    d.setMainUnitName(StringUtils.isBlank(d.getMainUnitName()) ?
                            unit.getUnitName() : d.getMainUnitName());
                    d.setTrainingUnitId(map1.get(d.getTrainingUnitName()));
                    d.setCreateUser(getUserId());
                    d.setCreateDept(unit.getUnitId());
                    d.setCreateTime(new Date());
                    this.save(d);
                    Flight flight = flightService.getOne(new LambdaQueryWrapper<Flight>()
                            .eq(Flight::getFlightName, d.getFlightName())
                            .eq(Flight::getYear, d.getYear()));
                    if (null != flight) {
                        d.setFlightId(flight.getFlightId()).setFlightCode(flight.getFlightCode());
                    } else {
                        Flight flight1 = new Flight()
                                .setFlightName(d.getFlightName())
                                .setFlightCode("ZY" + LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli())
                                .setEducationalSystem(d.getEducationalSystem())
                                .setTrainingTime(d.getTrainingTime())
                                .setMajorType(d.getMajorType())
                                .setYear(d.getYear())
                                .setTissueUnitId(d.getTrainingUnitId())
                                .setTissueUnitName(d.getTrainingUnitName())
                                .setTissueUnitAddress(d.getTrainingSite())
                                .setContactPerson(d.getContactPerson())
                                .setPhonenumber(d.getPhonenumber())
                                .setCreateDept(unit.getUnitId())
                                .setCreateUser(getUserId())
                                .setCreateTime(new Date());
                        flightService.save(flight1);
                        d.setFlightId(flight1.getFlightId()).setFlightCode(flight1.getFlightCode());
                    }
                    this.updateById(d);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、单位:" + d.getTrainingUnitName() +
                            ",开训时间:" + DateUtils.dateTime(d.getTrainingTime()) + "，专业:" + d.getFlightName() + ",导入成功");
                } else if (isUpdateSupport && StringUtils.equals(u.getIsIssue(),"0")) {
                    BeanValidators.validateWithException(validator, d);
                    d.setMainUnitId(StringUtils.isBlank(d.getMainUnitName()) ?
                            unit.getUnitId() : map.get(d.getMainUnitName()));
                    d.setMainUnitName(StringUtils.isBlank(d.getMainUnitName()) ?
                            unit.getUnitName() : d.getMainUnitName());
                    d.setTrainingUnitId(map1.get(d.getTrainingUnitName()));
                    d.setUpdateUser(getUserId());
                    d.setUpdateTime(new Date());
                    d.setDemandId(u.getDemandId());
                    d.setIsIssue("0");
                    this.updateById(d);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、单位:" + d.getTrainingUnitName() +
                            ",开训时间:" + DateUtils.dateTime(d.getTrainingTime()) + "，专业:" + d.getFlightName() + ",更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、单位:" + d.getTrainingUnitName() +
                            ",开训时间:" + DateUtils.dateTime(d.getTrainingTime()) + "，专业:" + d.getFlightName() + "," +
                            "已存在或者不是草稿状态");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、单位:" + d.getTrainingUnitName() +
                        ",开训时间:" + DateUtils.dateTime(d.getTrainingTime()) + "，专业:" + d.getFlightName() + ",导入失败：";
                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
    public List<ProjectUnitVO> getPeopleNum(Demand copy, List<Unit> units) {
        List<ProjectUnitVO> voList = new ArrayList<ProjectUnitVO>();
        for (Unit unit : units) {
            ProjectUnitVO vo = new ProjectUnitVO();
            vo.setUnitId(unit.getUnitId());
            vo.setUnitName(unit.getUnitName());
            if (null != copy) {
                if (StringUtils.equals("1", copy.getIsIssue()) || StringUtils.equals("2", copy.getIsIssue())) {
                    Demand demand = baseMapper.selectOne(new LambdaQueryWrapper<Demand>()
                            .eq(Demand::getCreateDept, unit.getUnitId())
                            .eq(Demand::getParentId, copy.getDemandId()));
                    if (null != demand) {
                        DemandTotal demandTotal = demandTotalService.getOne(new LambdaQueryWrapper<DemandTotal>()
                                .eq(DemandTotal::getDemandId, demand.getDemandId())
                                .eq(DemandTotal::getUnitId, unit.getUnitId()));
                        if (null != demandTotal) {
                            vo.setPeopleNum(demandTotal.getPeopleNum());
                        } else {
                            List<Demand> list1 = baseMapper.selectList(new LambdaQueryWrapper<Demand>()
                                    .eq(Demand::getParentId, demand.getDemandId()));
                            if (CollectionUtils.isNotEmpty(list1)) {
                                List<Demand> list = getList(list1).stream().filter(l ->
                                        org.apache.commons.lang3.StringUtils.equals("1", l.getIsReport()) && 1 == l.getStatus()
                                ).collect(Collectors.toList());
                                if (CollectionUtils.isNotEmpty(list)) {
                                    List<DemandSignUp> demandSignUpList = demandSignUpService.list(new LambdaQueryWrapper<DemandSignUp>()
                                            .eq(DemandSignUp::getStatus, 1)
                                            .in(DemandSignUp::getDemandId,
                                                    list.stream().map(Demand::getDemandId).collect(Collectors.toList())));
                                    if (CollectionUtils.isNotEmpty(demandSignUpList)) {
                                        BigDecimal reduce = demandSignUpList.stream().map(l ->
                                                        BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getForecastAttendance()) ?
                                                                "0" : l.getForecastAttendance())))
                                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                                        vo.setPeopleNum(reduce.intValue());
                                    } else {
                                        vo.setPeopleNum(0);
                                    }
                                } else {
                                    vo.setPeopleNum(0);
                                }
                            } else {
                                vo.setPeopleNum(0);
                            }
                        }
                    } else {
                        vo.setPeopleNum(0);
                    }
                } else {
                    vo.setPeopleNum(0);
                }
            } else {
                vo.setPeopleNum(0);
            }
            voList.add(vo);
        }
        return voList;
    }

    @Override
    public List<Demand> getList(List<Demand> list) {
        List<Demand> list1 = baseMapper.selectList(new LambdaQueryWrapper<Demand>()
                .in(Demand::getParentId,
                        list.stream().map(Demand::getDemandId).collect(Collectors.toList())));
        if (CollectionUtils.isNotEmpty(list1)) {
            return getList(list1);
        }
        return list;
    }
}
