package com.jwipc.sys.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.jwipc.dto.ZTreeDTO;
import com.jwipc.dto.ZTreeDataDTO;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.sys.constant.OrgStatus;
import com.jwipc.sys.constant.TreeState;
import com.jwipc.sys.convert.OrgConvert;
import com.jwipc.sys.dto.OrgAddOrEditDTO;
import com.jwipc.sys.dto.OrgTreeDTO;
import com.jwipc.sys.entity.Org;
import com.jwipc.sys.entity.UserOrg;
import com.jwipc.sys.logic.OrgLogic;
import com.jwipc.sys.service.IOrgService;
import com.jwipc.sys.service.IUserOrgService;
import com.jwipc.util.ZTreeUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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


/**
 * <p> </p>
 *
 * @author BOGON
 * @version 1.0
 * @since JDK 1.8
 */
@Service
@RequiredArgsConstructor
public class OrgLogicImpl implements OrgLogic {
    private final IOrgService orgService;
    private final OrgConvert orgConvert;
    private final IUserOrgService userOrgService;

    @Override
    public PageView findForTreegridByParentId(String parentId) {
        final LambdaQueryWrapper<Org> orgLambdaQueryWrapper = new LambdaQueryWrapper<Org>().eq(Org::getState,
                        OrgStatus.ENABLE.getStatus())
                .eq(Org::getParentId, parentId);
        final List<Org> list = orgService.list(orgLambdaQueryWrapper);
        List<OrgTreeDTO> orgTreeDTOS = orgConvert.entities2TreeDTOs(list);
        for (OrgTreeDTO orgTreeDTO : orgTreeDTOS) {
            final LambdaQueryWrapper<Org> wrapper = new LambdaQueryWrapper<Org>().eq(Org::getState,
                    OrgStatus.ENABLE.getStatus());
            final String id = orgTreeDTO.getId();
            final long count = orgService.count(wrapper.eq(Org::getParentId, id));
            if (count > 0) {
                orgTreeDTO.setState(TreeState.CLOSE.getState());
            }
        }
        return PageUtil.getPV(orgTreeDTOS, (long) orgTreeDTOS.size());
    }

    @Override
    public List<ZTreeDTO<ZTreeDataDTO>> getAllOrgTree(String searchName, Long userId) {
        final LambdaQueryWrapper<Org> orgLambdaQueryWrapper = new LambdaQueryWrapper<Org>().like(
                StrUtil.isNotEmpty(searchName),
                Org::getName, searchName);
        final List<Org> list = orgService.list(orgLambdaQueryWrapper);
        if (CollUtil.isEmpty(list)) {
            return CollUtil.newArrayList();
        }
        List<ZTreeDataDTO> dataDTOS = Lists.newArrayList();
        final LambdaQueryWrapper<UserOrg> userOrgLambdaQueryWrapper = new LambdaQueryWrapper<UserOrg>().eq(
                UserOrg::getUserId, userId);
        final List<UserOrg> userOrgs = userOrgService.list(userOrgLambdaQueryWrapper);
        final List<String> userOrgIds = userOrgs.stream().map(UserOrg::getOrgId).map(String::valueOf)
                .collect(Collectors.toList());
        final List<ZTreeDTO<ZTreeDataDTO>> zTreeDTOS = ZTreeUtil.listToZtree(dataDTOS);
        for (ZTreeDTO<ZTreeDataDTO> zTreeDTO : zTreeDTOS) {
            zTreeDTO.setChecked(userOrgIds.contains(zTreeDTO.getId()));
        }

        final ZTreeDTO<ZTreeDataDTO> parentZtree = ZTreeDTO.<ZTreeDataDTO>builder()
                .id("-1").name("组织机构树").open(true).pid("0")
                .nocheck(true)
                .build();
        List<ZTreeDTO<ZTreeDataDTO>> parents = Lists.newArrayList();

        parents.add(parentZtree);
        parents.addAll(zTreeDTOS);
        return parents;
    }

    @Override
    public OrgAddOrEditDTO getForEdit(Long id, Long parentId) {
        final Org byId = orgService.getById(id);
        OrgAddOrEditDTO orgAddOrEditDTO;
        if (Objects.nonNull(byId)) {
            orgAddOrEditDTO = orgConvert.entity2EditDTO(byId);
        } else {
            orgAddOrEditDTO = new OrgAddOrEditDTO();
            orgAddOrEditDTO.setParentId(parentId);
        }
        return orgAddOrEditDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(OrgAddOrEditDTO orgAddOrEditDTO) {
        Org org = orgConvert.editDTO2Entity(orgAddOrEditDTO);
        final Long parentId = org.getParentId();
        final Org byId = orgService.getById(parentId);
        Long level = 1L;
        if (Objects.nonNull(byId)) {
            level = byId.getLevel() + 1;
        }

        org.setLevel(level);
        org.setState(OrgStatus.ENABLE.getStatus());
        //判断编码是否存在
        final LambdaQueryWrapper<Org> queryWrapper = new LambdaQueryWrapper<Org>().eq(Org::getCode,
                org.getCode());
        queryWrapper.ne(Objects.nonNull(org.getId()), Org::getId, org.getId());
        final long count = orgService.count(queryWrapper);
        if (count > 0) {
            throw new DaoException("组织机构编码重复");
        }
        orgService.saveOrUpdate(org);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Long id) {
        final Org byId = orgService.getById(id);
        if (Objects.isNull(byId)) {
            throw new DaoException("组织机构未找到!");
        }
        final long count = orgService.count(new LambdaQueryWrapper<Org>().eq(Org::getParentId, byId.getId()));
        if (count > 0) {
            throw new DaoException("组织机构有子组织无法删除!");
        }
        orgService.removeById(byId);
    }
}