package com.srs.dormitory.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.srs.common.core.domain.entity.SysDept;
import com.srs.comprehensive.domain.SrsGrade;
import com.srs.comprehensive.service.ISrsGradeService;
import com.srs.dormitory.domain.DmsDeptGrade;
import com.srs.dormitory.mapper.DmsDeptGradeMapper;
import com.srs.dormitory.service.IDmsDeptGradeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.srs.dormitory.utils.BeanCopyUtils;
import com.srs.system.service.ISysDeptService;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 猪油骨
 * @since 2023-09-02
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class IDmsDeptGradeServiceImpl extends ServiceImpl<DmsDeptGradeMapper, DmsDeptGrade> implements IDmsDeptGradeService {
    private final ISysDeptService deptService;
    private final ISrsGradeService gradeService;

    /**
     * 关联年级和部门
     */
    /**
     * 检查并更新部门年级关联数据
     * 1. 获取所有部门和年级的ID列表。
     * 2. 如果已存在部门年级关联数据，将新的部门年级关联数据与已存在的数据比较，
     * 保留不同的数据作为待保存的部门年级关联数据。
     * 3. 如果有待保存的部门年级关联数据，将其保存到数据库中。
     *
     * @throws RuntimeException 操作失败时抛出异常
     */
    @Override
    @Transactional
    public void departmentBoundGrades() {
        // 获取已存在的部门年级关联数据
        List<DmsDeptGrade> dmsDeptGrades = list()
                .stream()
                .peek(deptGrade -> deptGrade.setId(null))
                .collect(Collectors.toList());

        // 获取所有部门和年级的ID列表
        List<Long> depts = deptService
                .lambdaQuery()
                .select(SysDept::getDeptId)
                .list()
                .stream()
                .map(SysDept::getDeptId)
                .collect(Collectors.toList());

        List<Long> grades = gradeService
                .lambdaQuery()
                .select(SrsGrade::getGradeId)
                .list()
                .stream()
                .map(SrsGrade::getGradeId)
                .collect(Collectors.toList());

        List<DmsDeptGrade> deptGrades = depts
                .stream()
                .flatMap(dept -> grades
                        .stream()
                        .map(grade -> {
                            DmsDeptGrade deptGrade = new DmsDeptGrade();
                            deptGrade.setDeptId(dept);
                            deptGrade.setGradeId(grade);
                            return deptGrade;
                        })
                ).collect(Collectors.toList());


        if (!dmsDeptGrades.isEmpty()) {
            deptGrades = deptGrades
                    .stream()
                    .filter(deptGrade -> !dmsDeptGrades.contains(deptGrade))
                    .collect(Collectors.toList());
            if (deptGrades.isEmpty()) return;
        }


        // 如果有待保存的部门年级关联数据，保存到数据库中
        boolean saveBatch = saveBatch(deptGrades);
        if (!saveBatch) {
            throw new RuntimeException("操作失败");
        }
        log.info("已保存关联列表");
    }


    /*
       解绑部门和年级关联关系
      */
    @Override
    @Transactional
    public void unbind() {
        log.info("开始检查需要删除的元素");
        List<DmsDeptGrade> deptGrades = list();

        if (!deptGrades.isEmpty()) {
            // 获取所有部门的 ID 列表
            List<Long> depts = deptGrades
                    .stream()
                    .map(DmsDeptGrade::getDeptId)
                    .collect(Collectors.toList());

            // 查询数据库中存在的部门 ID 列表
            List<Long> deptIds = deptService
                    .lambdaQuery()
                    .select(SysDept::getDeptId)
                    .in(SysDept::getDeptId, depts)
                    .list()
                    .stream()
                    .map(SysDept::getDeptId)
                    .collect(Collectors.toList());

            // 从 depts 中移除数据库中已存在的部门 ID
            depts.removeAll(deptIds);

            if (!depts.isEmpty()) {
                // 删除未在数据库中存在的部门和年级关联关系
                boolean removeDept = remove(
                        new LambdaQueryWrapper<DmsDeptGrade>()
                                .in(DmsDeptGrade::getDeptId, depts)
                );
                // 如果删除失败，抛出异常
                if (!removeDept) throw new RuntimeException("解绑部门操作失败");
            }


            // 使用 Stream 过滤并删除已删除的部门关联关系
            deptGrades = deptGrades
                    .stream()
                    .filter(deptGrade -> !depts.contains(deptGrade.getDeptId()))
                    .collect(Collectors.toList());

            // 获取所有年级的 ID 列表
            List<Long> grades = deptGrades
                    .stream()
                    .map(DmsDeptGrade::getGradeId)
                    .collect(Collectors.toList());

            // 查询数据库中存在的年级 ID 列表
            List<Long> gradeIds = gradeService
                    .lambdaQuery()
                    .select(SrsGrade::getGradeId)
                    .in(SrsGrade::getGradeId, grades)
                    .list()
                    .stream()
                    .map(SrsGrade::getGradeId)
                    .collect(Collectors.toList());
            // 从 grades 中移除数据库中已存在的年级 ID
            grades.removeAll(gradeIds);

            if (grades.isEmpty()) return;

            log.info("开始删除元素");
            // 删除未在数据库中存在的年级和部门关联关系
            boolean removeGrade = remove(
                    new LambdaQueryWrapper<DmsDeptGrade>()
                            .in(DmsDeptGrade::getGradeId, grades)
            );

            // 如果删除失败，抛出异常
            if (!removeGrade) throw new RuntimeException("解绑年级操作失败");
            log.info("删除成功");
        }
    }

}
