package com.fdkankan.ucenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fdkankan.common.constant.SceneConstant;
import com.fdkankan.common.exception.BusinessException;
import com.fdkankan.ucenter.constant.ErrorConstant;
import com.fdkankan.ucenter.constant.LoginConstant;
import com.fdkankan.ucenter.entity.Folder;
import com.fdkankan.ucenter.entity.FolderScene;
import com.fdkankan.ucenter.entity.User;
import com.fdkankan.ucenter.mapper.IFolderMapper;
import com.fdkankan.ucenter.service.IFolderSceneService;
import com.fdkankan.ucenter.service.IFolderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fdkankan.ucenter.service.IUserService;
import com.fdkankan.ucenter.util.DateUserUtil;
import com.fdkankan.ucenter.util.FolderTree;
import com.fdkankan.ucenter.util.FolderTreeUtil;
import com.fdkankan.ucenter.vo.request.FolderParam;
import com.fdkankan.ucenter.vo.request.SceneParam;
import com.fdkankan.ucenter.vo.response.FolderVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 文件夹表 服务实现类
 * </p>
 *
 * @author 
 * @since 2022-07-07
 */
@Service
public class FolderServiceImpl extends ServiceImpl<IFolderMapper, Folder> implements IFolderService {

    @Autowired
    IUserService userService;
    @Autowired
    IFolderSceneService folderSceneService;

    @Override
    public void add(FolderParam param) {
        User user = userService.getByUserName(param.getUserName());
        List<Folder> list = findByParentIdAndName(param.getParentId(), param.getName(), user.getId(), param.getType());
        if(list != null && list.size() > 0){
            throw new BusinessException(SceneConstant.FAILURE_CODE_5030, SceneConstant.FAILURE_MSG_5030);
        }
        Folder folderEntity = new Folder();
        BeanUtils.copyProperties(param, folderEntity);
        folderEntity.setUserId(user.getId());
        folderEntity.setCreateTime(DateUserUtil.getDate(new Date()));
        folderEntity.setUpdateTime(DateUserUtil.getDate(new Date()));
        this.save(folderEntity);
    }

    @Override
    public void updateByParam(FolderParam param) {
        User user = userService.getByUserName(param.getUserName());
        if(StringUtils.isEmpty(param.getName()) || param.getId() == null){
            throw new BusinessException(LoginConstant.FAILURE_CODE_3001, LoginConstant.FAILURE_MSG_3001);
        }
        List<Folder> list = findByParentIdAndName(param.getParentId(), param.getName(), user.getId(), param.getType());
        if(list != null && list.size() > 0){
            throw new BusinessException(SceneConstant.FAILURE_CODE_5030, SceneConstant.FAILURE_MSG_5030);
        }
        Folder folder = checkFolder(param.getId(), user.getId());
        folder.setName(param.getName());
        this.updateById(folder);
    }

    @Override
    public void delete(Long id, String username) {
        if(id == null){
            throw new BusinessException(LoginConstant.FAILURE_CODE_3001, LoginConstant.FAILURE_MSG_3001);
        }
        User user = userService.getByUserName(username);
        Folder folder = checkFolder(id, user.getId());

        //删除子文件夹
        List<Folder> list = new ArrayList<>();
        getAllFolder(id,list);
        list.add(folder);
        List<Long> delIds = list.parallelStream().map(Folder::getId).collect(Collectors.toList());
        folderSceneService.deleteByFolderIds(delIds,user.getId());
        this.removeByIds(delIds);
    }

    @Override
    public List<FolderTree> findListTree(String folderIds,Integer type, String username) {
        if(type == null ){
            throw new BusinessException(LoginConstant.FAILURE_CODE_3001, LoginConstant.FAILURE_MSG_3001);
        }
        User user = userService.getByUserName(username);
        if(user == null){
            throw new BusinessException(LoginConstant.FAILURE_CODE_3004, LoginConstant.FAILURE_MSG_3004);
        }
        List<Folder> list = this.getByUserAndType(folderIds,user.getId(),type);
        return new FolderTreeUtil(list).buildTree();
    }

    @Override
    public void move(FolderParam param, String username) {
        User user = userService.getByUserName(username);
        if(user == null){
            throw new BusinessException(LoginConstant.FAILURE_CODE_3004, LoginConstant.FAILURE_MSG_3004);
        }
        if(StringUtils.isEmpty(param.getFolderIds()) && StringUtils.isEmpty(param.getSceneIds())){
            throw new BusinessException(LoginConstant.FAILURE_CODE_3001, LoginConstant.FAILURE_MSG_3001);
        }
        if(param.getType() == null ){
            throw new BusinessException(LoginConstant.FAILURE_CODE_3001, LoginConstant.FAILURE_MSG_3001);
        }
        if(StringUtils.isNotEmpty(param.getFolderIds())){
            String[] folderIds = param.getFolderIds().split(",");
            Folder folderEntity = null;
            List<LambdaUpdateWrapper<Folder>> ListWr = new ArrayList<>();
            for (String folderId : folderIds) {
                folderEntity = this.getById(Long.valueOf(folderId));

                LambdaUpdateWrapper<Folder> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(Folder::getId,folderId);
                wrapper.set(Folder::getParentId,param.getParentId());
                if(!folderEntity.getType().equals(param.getType())){
                    throw new BusinessException(SceneConstant.FAILURE_CODE_5030, SceneConstant.FAILURE_MSG_5030);
                }
                if(param.getParentId() != null){ //移动到根目录
                    if(param.getParentId().equals(folderEntity.getId())){
                        throw new BusinessException(SceneConstant.FAILURE_CODE_5030, SceneConstant.FAILURE_MSG_5030);
                    }
                    Folder folder = this.getById(param.getParentId());
                    if(folder == null){
                        throw new BusinessException(ErrorConstant.FAILURE_CODE_5050, ErrorConstant.FAILURE_MSG_5050);
                    }
                    if(folder.getParentId() != null && folder.getParentId().equals(folderEntity.getId())){
                        throw new BusinessException(ErrorConstant.FAILURE_CODE_5051, ErrorConstant.FAILURE_MSG_5051);
                    }
                }

                List<Folder> byParentIdAndName = findByParentIdAndName(param.getParentId(), folderEntity.getName(), user.getId(),param.getType());
                if(byParentIdAndName != null && byParentIdAndName.size() > 0){
                    //表示迁移回当前目录，不做处理
                    if(byParentIdAndName.get(0).getId() == Long.parseLong(folderId)){
                        return;
                    }
                    throw new BusinessException(SceneConstant.FAILURE_CODE_5030, SceneConstant.FAILURE_MSG_5030);
                }
                ListWr.add(wrapper);
            }
            for (LambdaUpdateWrapper<Folder> wrapper : ListWr) {
                this.update(wrapper);
            }

        }
        if(StringUtils.isNotEmpty(param.getSceneIds())){
            for (String s : param.getSceneIds().split(",")) {
                FolderScene folderSceneEntity = null;
                folderSceneEntity = folderSceneService.getByType(s, param.getType());
                if(folderSceneEntity != null){
                    folderSceneService.removeById(folderSceneEntity.getId());
                }
                if(param.getParentId() != null){
                    Folder folderEntity = getById(param.getParentId());
                    if(!folderEntity.getType().equals(param.getType())){
                        throw new BusinessException(SceneConstant.FAILURE_CODE_5030, SceneConstant.FAILURE_MSG_5030);
                    }
                    folderSceneEntity = new FolderScene();
                    folderSceneEntity.setSceneId(Long.valueOf(s));
                    folderSceneEntity.setFolderId(param.getParentId());
                    folderSceneService.save(folderSceneEntity);
                }
            }

        }

    }

    @Override
    public List<Folder> getAllFolderIds(List<Long> folderIds) {
        List<Folder> list = new ArrayList<>();
        for (Long id : folderIds) {
            Folder byId = this.getById(id);
            List<Folder> allFolder = new ArrayList<>();
             this.getAllFolder(id,allFolder);
            list.add(byId);
            if(allFolder.size() >0){
                list.addAll(allFolder);
            }

        }
        return list;
    }


    private List<Folder> getByUserAndType(String folderIds,Long userId, Integer type) {
        LambdaQueryWrapper<Folder> wrapper = new LambdaQueryWrapper<>();

        List<Long> folderIdList = getByFolderIds(folderIds);
        if(folderIdList.size() >0){
            wrapper.notIn(Folder::getId,folderIdList);
        }
        wrapper.eq(Folder::getUserId,userId)
                .eq(Folder::getType,type);
        return this.list(wrapper);
    }

    private  void  getAllFolder(Long id ,List<Folder> allFolder){
        LambdaQueryWrapper<Folder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Folder::getParentId,id);
        List<Folder> list = this.list(wrapper);
        if(list == null || list.size() <= 0){
            return ;
        }
        for (Folder folder : list) {
             getAllFolder(folder.getId(),allFolder);
        }
        allFolder.addAll(list);
    }

    private Folder checkFolder(Long id, Long userId){
        Folder folderEntity = this.getById(id);
        if(folderEntity == null){
            throw new BusinessException(SceneConstant.FAILURE_CODE_5027, SceneConstant.FAILURE_MSG_5027);
        }

        if(folderEntity.getUserId().longValue() != userId){
            throw new BusinessException(SceneConstant.FAILURE_CODE_5028, SceneConstant.FAILURE_MSG_5028);
        }
        return folderEntity;
    }

    private List<Folder> findByParentIdAndName(Long parentId, String name, Long userId, Integer type){
        LambdaQueryWrapper<Folder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Folder::getName,name)
                .eq(Folder::getUserId,userId);
        if(type !=null){
            wrapper.eq(Folder::getType,type);
        }
        if(parentId!= null){
            wrapper.eq(Folder::getParentId,parentId);
        }else {
            wrapper.isNull(Folder::getParentId);
        }
        return this.list(wrapper);
    }

    @Override
    public List<Folder> findByUserIdAndType(Long userId, Integer type, String name,String folderIds) {
        LambdaQueryWrapper<Folder> wrapper = new LambdaQueryWrapper<>();

        List<Long> folderIdList = getByFolderIds(folderIds);
        if(folderIdList.size() >0){
            wrapper.notIn(Folder::getId,folderIdList);
        }
        wrapper.eq(Folder::getUserId,userId);
        wrapper.eq(Folder::getType,type);
        if(StringUtils.isNotBlank(name)){
            wrapper.like(Folder::getName,name);
        }
        return this.list(wrapper);
    }

    private List<Long> getByFolderIds(String folderIds){
        List<Long> folderIdList = new ArrayList<>();
        if(StringUtils.isNotBlank(folderIds)){
            if(folderIds.contains(",")){
                String[] split = folderIds.split(",");
                for (String s : split) {
                    folderIdList.add(Long.valueOf(s));
                }
            }else {
                folderIdList.add(Long.valueOf(folderIds));
            }
        }
        if(folderIdList.size() >0){
            List<Folder> allFolderIds = this.getAllFolderIds(folderIdList);
            return allFolderIds.stream().map(Folder::getId).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }
}
