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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.sop.business.bean.dto.OrgDto;
import com.qmth.sop.business.bean.result.RoleResult;
import com.qmth.sop.business.bean.result.SysUserResult;
import com.qmth.sop.business.entity.SysOrg;
import com.qmth.sop.business.entity.SysUser;
import com.qmth.sop.business.mapper.SysOrgMapper;
import com.qmth.sop.business.service.SysOrgService;
import com.qmth.sop.business.service.SysUserService;
import com.qmth.sop.common.enums.ExceptionResultEnum;
import com.qmth.sop.common.enums.FieldUniqueEnum;
import com.qmth.sop.common.util.ResultUtil;
import com.qmth.sop.common.util.ServletUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 学校组织架构 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2023-07-17
 */
@Service
public class SysOrgServiceImpl extends ServiceImpl<SysOrgMapper, SysOrg> implements SysOrgService {

    @Resource
    SysUserService sysUserService;

    /**
     * 获取机构树
     *
     * @param showUserList
     * @return
     */
    @Override
    public List<OrgDto> listOrgTree(Boolean showUserList) {
        Long orgId = Objects.nonNull(ServletUtil.getRequestHeaderOrgIdNotVaild()) ? Long.valueOf(ServletUtil.getRequestHeaderOrgIdNotVaild().toString()) : null;
        List<SysUserResult> sysUserResultList = null;
        if (Objects.nonNull(showUserList) && showUserList) {
            sysUserResultList = sysUserService.findSysUserResultList(orgId);
            if (!CollectionUtils.isEmpty(sysUserResultList)) {
                sysUserResultList.forEach(e -> {
                    if (Objects.nonNull(e.getRoleIds())) {
                        String[] roldIds = StringUtils.split(e.getRoleIds(), ";");
                        List<RoleResult> roleResultList = new ArrayList<>(roldIds.length);
                        for (int y = 0; y < roldIds.length; y++) {
                            String[] strs = StringUtils.split(roldIds[y], ",");
                            roleResultList.add(new RoleResult(Long.parseLong(strs[0]), strs[1], strs[2]));
                        }
                        e.setRoleResultList(roleResultList);
                        e.setRoleIds(null);
                    }
                });
            }
        }
        List<OrgDto> orgList = this.listOrgAll();
        Map<Long, OrgDto> map = null;
        if (Objects.nonNull(showUserList) && showUserList) {
            List<SysUserResult> finalSysUserResultList = sysUserResultList;
            map = orgList.stream()
                    .peek(e -> {
                        // 加入机构下所有人员查询
                        e.setSysUserList(finalSysUserResultList.stream().filter(f -> Objects.nonNull(f.getOrgId()) && f.getOrgId().equals(e.getId())).collect(Collectors.toList()));
                    })
                    .collect(Collectors.toMap(OrgDto::getId, Function.identity(), (dto1, dto2) -> dto1));
        } else {
            map = orgList.stream().collect(Collectors.toMap(OrgDto::getId, Function.identity(), (dto1, dto2) -> dto1));
        }

        Iterator<Long> iterator = map.keySet().iterator();
        Set<Long> deleteKeys = new HashSet<>();
        while (iterator.hasNext()) {
            Long parentId = iterator.next();
            if (map.get(parentId).getParentId() != null) {
                if (Objects.nonNull(map.get(map.get(parentId).getParentId()))) {
                    map.get(map.get(parentId).getParentId()).getChildren().add(map.get(parentId));
                    deleteKeys.add(parentId);
                }
            }
        }
        for (Long key : deleteKeys) {
            map.remove(key);
        }
        return new ArrayList<>(map.values());
    }

    /**
     * 获取所有机构
     *
     * @return
     */
    @Override
    public List<OrgDto> listOrgAll() {
        return this.baseMapper.listOrgAll();
    }

    /**
     * 保存/修改机构信息
     *
     * @param org
     * @return
     */
    @Override
    @Transactional
    public Boolean saveOrg(SysOrg org) {
        try {
            SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
            if (Objects.isNull(org.getId())) {// 新增
                org.insertInfo(sysUser.getId());
            } else { // 修改
                SysOrg sysOrg = this.getById(org.getId());
                Optional.ofNullable(sysOrg).orElseThrow(() -> ExceptionResultEnum.ORG_NO_DATA.exception());
                org.updateInfo(sysUser.getId());
            }
            return saveOrUpdate(org);
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length()).replaceAll("'", "");
                throw ExceptionResultEnum.SQL_ERROR.exception("[" + FieldUniqueEnum.convertToTitle(columnStr) + "]数据不允许重复插入");
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return null;
    }

    /**
     * 机构禁用
     *
     * @param org
     * @return
     */
    @Override
    @Transactional
    public Boolean enable(SysOrg org) {
        Optional.ofNullable(org).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("参数不能为空"));
        Optional.ofNullable(org.getId()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("id不能为空"));
        Optional.ofNullable(org.getEnable()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("启用/禁用不能为空"));

        // 禁用时，校验机构
        if (!org.getEnable()) {
            // 机构下是否有用户
            List<SysUser> sysUsers = sysUserService.list(new QueryWrapper<SysUser>().lambda().eq(SysUser::getOrgId, org.getId()));
            if (!CollectionUtils.isEmpty(sysUsers)) {
                throw ExceptionResultEnum.ERROR.exception("该机构下有用户，不能禁用");
            }

            // 机构下是否有子机构
            List<SysOrg> sysOrgs = this.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getParentId, org.getId()));
            if (!CollectionUtils.isEmpty(sysOrgs)) {
                throw ExceptionResultEnum.ERROR.exception("该机构下有子机构，不能禁用");
            }
        }
        SysOrg sysOrg = this.getById(org.getId());
        Optional.ofNullable(sysOrg).orElseThrow(() -> ExceptionResultEnum.ORG_NO_DATA.exception());

        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        return this.update(new UpdateWrapper<SysOrg>().lambda().set(SysOrg::getEnable, org.getEnable())
                .eq(SysOrg::getId, org.getId())
                .set(SysOrg::getUpdateId, requestUser.getId())
                .set(SysOrg::getUpdateTime, System.currentTimeMillis()));
    }
}
