package com.qmth.sop.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.sop.business.bean.result.SysDingGroupResult;
import com.qmth.sop.business.bean.result.SysDingGroupRoleResult;
import com.qmth.sop.business.entity.*;
import com.qmth.sop.business.mapper.SysDingGroupMapper;
import com.qmth.sop.business.service.*;
import com.qmth.sop.common.base.BaseEntity;
import com.qmth.sop.common.enums.DingObjTypeEnum;
import com.qmth.sop.common.enums.ExceptionResultEnum;
import com.qmth.sop.common.enums.ServiceStatusEnum;
import com.qmth.sop.common.util.ServletUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 考勤组表 服务实现.
 *
 * @author: shudonghui
 * @date: 2023-08-02 14:21:11
 * @version: 1.0
 * @email: shudonghui@qmth.com.cn
 * @Company: www.qmth.com.cn
 */
@Service
public class SysDingGroupServiceImpl extends ServiceImpl<SysDingGroupMapper, SysDingGroup> implements SysDingGroupService {

    @Resource
    SysDingObjService sysDingObjService;
    @Resource
    TBServiceService tbServiceService;
    @Resource
    SysSupplierService sysSupplierService;
    @Resource
    SysRoleService sysRoleService;

    /**
     * 查询列表
     *
     * @param iPage
     * @return
     */
    @Override
    public IPage<SysDingGroupResult> query(IPage<Map> iPage, Long serviceId, ServiceStatusEnum status, Long[] supplierIds, Long[] dingRoleIds, Long[] approveRoleIds, Boolean faceOpen, Long createStartTime, Long createEndTime) {
        IPage<SysDingGroupResult> dingGroupResultIPage = this.baseMapper.query(iPage, serviceId, status, supplierIds, dingRoleIds, approveRoleIds, faceOpen, createStartTime, createEndTime);
        dingGroupResultIPage.getRecords().forEach(e -> {
            e.setDingObjs(sysDingObjService.getList(e.getId()));
        });
        return dingGroupResultIPage;
    }

    /**
     * 新增考勤组表
     *
     * @param sysDingGroup
     */
    @Override
    @Transactional
    public void add(SysDingGroupResult sysDingGroup) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();

        // 新增校验
        Long serviceUnitId = sysDingGroup.getServiceId();
        List<Long> supplierIdList = sysDingGroup.getSupplierIdList();
        if (!CollectionUtils.isEmpty(supplierIdList)) {
            List<SysDingGroupRoleResult> sysDingGroupRoleResultList = sysDingGroup.getDingObjs();
            List<Long> roleIdList = sysDingGroupRoleResultList.stream()
                    .filter(e -> DingObjTypeEnum.DING.equals(e.getType()))
                    .map(SysDingObj::getRoleId).distinct()
                    .collect(Collectors.toList());

            for (Long supplierId : supplierIdList) {
                List<Long> sysDingGroupIdList = this.list(new QueryWrapper<SysDingGroup>().lambda()
                                .eq(SysDingGroup::getServiceId, serviceUnitId)
                                .eq(SysDingGroup::getSupplierId, supplierId))
                        .stream()
                        .map(BaseEntity::getId)
                        .collect(Collectors.toList());

                if (!CollectionUtils.isEmpty(sysDingGroupIdList)) {
                    List<Long> dbRoleIdList = sysDingObjService.list(new QueryWrapper<SysDingObj>()
                                    .lambda()
                                    .eq(SysDingObj::getType, DingObjTypeEnum.DING)
                                    .in(SysDingObj::getDingGroupId, sysDingGroupIdList))
                            .stream()
                            .map(SysDingObj::getRoleId).distinct().collect(Collectors.toList());


                    List<Long> alreadyRoleIdList = roleIdList.stream().filter(dbRoleIdList::contains).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(alreadyRoleIdList)) {
                        // 已存在的角色id集合
                        SysSupplier sysSupplier = sysSupplierService.getById(supplierId);
                        if (Objects.isNull(sysSupplier)) {
                            throw ExceptionResultEnum.ERROR.exception("供应商不存在");
                        }
                        TBService tbServiceUnit = tbServiceService.getById(serviceUnitId);
                        if (Objects.isNull(tbServiceUnit)) {
                            throw ExceptionResultEnum.ERROR.exception("服务单元不存在");
                        }
                        String supplierName = sysSupplier.getName();
                        String serviceUnitName = tbServiceUnit.getName();

                        String roleNames = sysRoleService.listByIds(alreadyRoleIdList)
                                .stream()
                                .map(SysRole::getName)
                                .collect(Collectors.joining(","));

                        String error = String.format("新增失败,服务单元[%s],供应商[%s],适用考勤对象为[%s] 的考勤组设置已经存在", serviceUnitName, supplierName, roleNames);
                        throw ExceptionResultEnum.ERROR.exception(error);
                    }
                }
                SysDingGroup sysDingGroupEntity = new SysDingGroup();
                BeanUtils.copyProperties(sysDingGroup, sysDingGroupEntity);
                sysDingGroupEntity.setSupplierId(supplierId);

                sysDingGroupEntity.setCreateId(sysUser.getId());
                sysDingGroupEntity.setCreateTime(System.currentTimeMillis());
                sysDingGroupEntity.setEnable(true);
                this.saveOrUpdate(sysDingGroupEntity);
                sysDingGroupRoleResultList.forEach(e -> {
                    // 重置数组id
                    e.setId(null);
                    e.setDingGroupId(sysDingGroupEntity.getId());
                    sysDingObjService.save(e);
                });
            }
        }
    }

    /**
     * 修改考勤组表
     *
     * @param sysDingGroup
     */
    @Override
    @Transactional
    public void update(SysDingGroupResult sysDingGroup) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long supplierId = sysDingGroup.getSupplierId();
        Long serviceUnitId = sysDingGroup.getServiceId();

        // 编辑校验
        List<Long> sysDingGroupIdList = this.list(new QueryWrapper<SysDingGroup>().lambda()
                        .eq(SysDingGroup::getServiceId, serviceUnitId)
                        .eq(SysDingGroup::getSupplierId, supplierId)
                        .ne(SysDingGroup::getId, sysDingGroup.getId()))
                .stream()
                .map(BaseEntity::getId)
                .collect(Collectors.toList());
        List<Long> roleIdList = sysDingGroup.getDingObjs().stream()
                .filter(e -> DingObjTypeEnum.DING.equals(e.getType()))
                .map(SysDingObj::getRoleId).distinct()
                .collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(sysDingGroupIdList)) {
            List<Long> dbRoleIdList = sysDingObjService.list(new QueryWrapper<SysDingObj>()
                            .lambda()
                            .eq(SysDingObj::getType, DingObjTypeEnum.DING)
                            .in(SysDingObj::getDingGroupId, sysDingGroupIdList))
                    .stream()
                    .map(SysDingObj::getRoleId).distinct().collect(Collectors.toList());

            List<Long> alreadyRoleIdList = roleIdList.stream().filter(dbRoleIdList::contains).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(alreadyRoleIdList)) {
                // 已存在的角色id集合
                SysSupplier sysSupplier = sysSupplierService.getById(supplierId);
                if (Objects.isNull(sysSupplier)) {
                    throw ExceptionResultEnum.ERROR.exception("供应商不存在");
                }
                TBService tbServiceUnit = tbServiceService.getById(serviceUnitId);
                if (Objects.isNull(tbServiceUnit)) {
                    throw ExceptionResultEnum.ERROR.exception("服务单元不存在");
                }
                String supplierName = sysSupplier.getName();
                String serviceUnitName = tbServiceUnit.getName();

                String roleNames = sysRoleService.listByIds(alreadyRoleIdList)
                        .stream()
                        .map(SysRole::getName)
                        .collect(Collectors.joining(","));

                String error = String.format("编辑失败,服务单元[%s],供应商[%s],适用考勤对象为[%s] 的考勤组设置已经存在", serviceUnitName, supplierName, roleNames);
                throw ExceptionResultEnum.ERROR.exception(error);
            }
        }

        sysDingGroup.setUpdateId(sysUser.getId());
        sysDingGroup.setUpdateTime(System.currentTimeMillis());
        this.saveOrUpdate(sysDingGroup);
        sysDingObjService.remove(new QueryWrapper<SysDingObj>().lambda().eq(SysDingObj::getDingGroupId, sysDingGroup.getId()));
        sysDingGroup.getDingObjs().forEach(e -> {
            e.setDingGroupId(sysDingGroup.getId());
            sysDingObjService.save(e);
        });
    }

    /**
     * 删除考勤组表
     *
     * @param id
     */
    @Override
    @Transactional
    public void delete(Long id) {
        SysDingGroup sysDingGroup = this.getById(id);
        if (Objects.nonNull(sysDingGroup)) {
            Long serviceId = sysDingGroup.getServiceId();
            if (Objects.nonNull(serviceId)) {
                TBService tbService = tbServiceService.getById(serviceId);
                if (Objects.nonNull(tbService)) {
                    ServiceStatusEnum serviceStatus = tbService.getStatus();
                    if (!ServiceStatusEnum.NEW.equals(serviceStatus)) {
                        throw ExceptionResultEnum.ERROR.exception("只有[" + ServiceStatusEnum.NEW.getTitle() + "]状态的服务单元可以删除考勤组");
                    }
                    sysDingObjService.remove(new QueryWrapper<SysDingObj>().lambda().eq(SysDingObj::getDingGroupId, id));
                    this.removeById(id);
                }
            }
        }
    }
}