/**
 * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xiaoniu.subsystem.system.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoniu.common.core.constant.Constants;
import com.xiaoniu.common.core.exception.ServiceException;
import com.xiaoniu.common.core.utils.StringUtils;
import com.xiaoniu.common.core.utils.bean.BeanUtils;
import com.xiaoniu.common.core.utils.bean.BeanValidators;
import com.xiaoniu.subsystem.system.domain.Unit;
import com.xiaoniu.subsystem.system.domain.vo.UnitImportVO;
import com.xiaoniu.subsystem.system.domain.vo.UnitTreeListVO;
import com.xiaoniu.subsystem.system.domain.vo.UnitVO;
import com.xiaoniu.subsystem.system.mapper.UnitMapper;
import com.xiaoniu.subsystem.system.service.IUnitService;
import com.xiaoniu.subsystem.system.utils.MobileNumberValidator;
import jakarta.validation.Validator;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.xiaoniu.common.security.utils.SecurityUtils.getUnitId;

/**
 * 单位管理表 服务实现类
 *
 * @author sst
 * @since 2024-11-26
 */
@Service
public class UnitServiceImpl extends ServiceImpl<UnitMapper, Unit> implements IUnitService {

    protected final Validator validator;


    public UnitServiceImpl(Validator validator) {
        this.validator = validator;
    }

    @Override
    public IPage<UnitVO> selectUnitPage(IPage<UnitVO> page, UnitVO unit) {
        return page.setRecords(baseMapper.selectUnitPage(page, unit));
    }

    @Override
    public List<UnitTreeListVO> unitTreeList(String unitName, String type) {
/*        List<Long> ids = new ArrayList<>();
        if (0 != getUnitId()){
            List<Unit> units;
            if (StringUtils.equals("0",type)) {
                units = baseMapper.selectList(new LambdaQueryWrapper<Unit>()
                        .eq(Unit::getParentId, getUnitId()));
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(units)) {
                    List<Long> longs = units.stream().map(Unit::getUnitId).toList();
                    ids.addAll(longs);
                    List<Unit> list = baseMapper.selectList(new LambdaQueryWrapper<Unit>()
                            .in(Unit::getParentId, longs));
                    setUnit(list, ids);
                } else {
                    ids.add(getUnitId());
                    units = baseMapper.selectList(new LambdaQueryWrapper<Unit>()
                            .eq(Unit::getParentId, getUnitId()));
                    if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(units)) {
                        List<Long> longs = units.stream().map(Unit::getUnitId).toList();
                        ids.addAll(longs);
                        List<Unit> list = baseMapper.selectList(new LambdaQueryWrapper<Unit>()
                                .in(Unit::getParentId, longs));
                        setUnit(list, ids);
                    }
                }
            }
        }*/
        List<Unit> list = baseMapper.selectList(new LambdaQueryWrapper<Unit>()
                .eq(StringUtils.isNotEmpty(type), Unit::getType, type)
                /*.in(StringUtils.equals("0", type)
                        && CollectionUtils.isNotEmpty(ids), Unit::getUnitId, ids)*/
                .like(StringUtils.isNotEmpty(unitName), Unit::getUnitName, unitName)
                .eq(Unit::getIsDeleted, Constants.ZERO));
        List<UnitTreeListVO> unitList = list.stream().map(item -> {
            UnitTreeListVO unitTreeListVO = new UnitTreeListVO();
            BeanUtils.copyProperties(item, unitTreeListVO);
            return unitTreeListVO;
        }).toList();
        return buildDeptTreeSelect(unitList);
    }

    @Override
    public List<UnitTreeListVO> unitTreeList(Unit unit, String type) {
        List<Unit> list = baseMapper.selectList(new LambdaQueryWrapper<Unit>()
                .eq(StringUtils.isNotEmpty(type), Unit::getType, type)
                .eq(null != unit.getUnitId(), Unit::getUnitId, unit.getUnitId())
                .eq(null != unit.getParentId(), Unit::getParentId, unit.getParentId())
                .like(StringUtils.isNotEmpty(unit.getUnitCode()), Unit::getUnitCode, unit.getUnitCode())
                .like(StringUtils.isNotEmpty(unit.getUnitName()), Unit::getUnitName, unit.getUnitName())
                .like(StringUtils.isNotEmpty(unit.getParentCode()), Unit::getParentCode, unit.getParentCode())
                .like(StringUtils.isNotEmpty(unit.getParentName()), Unit::getParentName, unit.getParentName())
                .eq(Unit::getIsDeleted, Constants.ZERO));
        List<UnitTreeListVO> unitList = list.stream().map(item -> {
            UnitTreeListVO unitTreeListVO = new UnitTreeListVO();
            BeanUtils.copyProperties(item, unitTreeListVO);
            return unitTreeListVO;
        }).toList();
        return buildDeptTreeSelect(unitList);
    }

    @Override
    public List<Long> juniorUnit(Long unitId) {
        return baseMapper.juniorUnit(unitId);
    }


    @Override
    @Transactional
    public String importData(List<Unit> list, Boolean isUpdateSupport, Long userId, Integer type) {
        if (CollectionUtils.isEmpty(list)) {
            throw new ServiceException("导入单位管理信息数据不能为空！");
        }
        Integer successNum = 0;
        Integer failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        List<Unit> save = new ArrayList<Unit>();
        List<Unit> update = new ArrayList<Unit>();
        List<Unit> units = list.stream()
                .filter(r -> StringUtils.isBlank(r.getParentCode())).collect(Collectors.toList());
        List<Unit> unitList = baseMapper.selectList(new LambdaQueryWrapper<Unit>()
                .eq(Unit::getType, type));
        Map<String, Unit> collect1 = unitList.stream().collect(Collectors.toMap(Unit::getUnitName, e -> e));
        Map<String, Unit> collect2 = unitList.stream().collect(Collectors.toMap(Unit::getUnitCode, e -> e));
        for (Unit d : units) {
            if (StringUtils.isBlank(d.getUnitName())) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、数据单位名称为空，导入失败");
                continue;
            }
            if (StringUtils.isNotBlank(d.getPhone())
                    && !MobileNumberValidator.isValidPhoneNumber(d.getPhone())){
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、电话号码有误：" + d.getPhone() +"，导入失败");
                continue;
            }
            Unit u = null;
            Unit unit = collect1.get(d.getUnitName());
            if (ObjectUtils.isNotEmpty(unit)) {
                u = unit;
            }
            Unit unit1 = collect2.get(d.getUnitCode());
            if (ObjectUtils.isNotEmpty(unit1)) {
                u = unit1;
            }
            if (StringUtils.isNull(u)) {
                BeanValidators.validateWithException(validator, d);
                d.setCreateUser(userId);
                d.setType(String.valueOf(type));
                this.save(d);
                successNum++;
                successMsg.append("<br/>" + successNum + "、单位:" + d.getUnitName() + ",导入成功");
            } else if (isUpdateSupport) {
                BeanValidators.validateWithException(validator, d);
                d.setUpdateUser(userId);
                d.setUnitId(u.getUnitId());
                this.updateById(d);
                successNum++;
                successMsg.append("<br/>" + successNum + "、单位:" + d.getUnitName() + ",更新成功");
            } else {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、单位:" + d.getUnitName() + ",已存在");
            }
        }
        if (CollectionUtils.isNotEmpty(save)){
            this.saveBatch(save);
        }
        if (CollectionUtils.isNotEmpty(update)){
            this.updateBatchById(update);
        }
        if (0 == type) {
            List<Unit> units1 = list.stream()
                    .filter(r -> StringUtils.isNotBlank(r.getParentCode())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(units1)) {
                Map<String, List<Unit>> collect = units1.stream().collect(Collectors.groupingBy(Unit::getParentCode));
                // 查询一级单位
                List<Unit> voList = getUnits(type, 0L);
                if (CollectionUtils.isNotEmpty(voList)) {
                    // 循环一级单位
                    for (Unit unit : voList) {
                        String s = saveOrUpdate(collect, unit, successNum, failureNum, successMsg, failureMsg,
                                isUpdateSupport, userId, type);
                        successNum = Integer.parseInt(s.split(",")[0]);
                        failureNum = Integer.parseInt(s.split(",")[1]);
                        // 查询一级单位下二级单位
                        List<Unit> voList2 = getUnits(type, unit.getUnitId());
                        if (CollectionUtils.isNotEmpty(voList2)) {
                            // 循环二级单位
                            for (Unit unit2 : voList2) {
                                // 查询二级单位代码查询三级单位并新增
                                s = saveOrUpdate(collect, unit2, successNum, failureNum, successMsg, failureMsg,
                                        isUpdateSupport, userId, type);
                                successNum = Integer.parseInt(s.split(",")[0]);
                                failureNum = Integer.parseInt(s.split(",")[1]);
                                // 查询二级单位下三级单位
                                List<Unit> voList3 = getUnits(type, unit2.getUnitId());
                                // 判断是否存在下级单位
                                if (CollectionUtils.isNotEmpty(voList3)) {
                                    // 循环三级单位
                                    for (Unit unit3 : voList3) {
                                        // 查询三级单位代码查询四级单位并新增
                                        s = saveOrUpdate(collect, unit3, successNum, failureNum, successMsg, failureMsg,
                                                isUpdateSupport, userId, type);
                                        successNum = Integer.parseInt(s.split(",")[0]);
                                        failureNum = Integer.parseInt(s.split(",")[1]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共: " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            if (10 < successNum) {
                successMsg = new StringBuilder();
                successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条.");
            } else {
                successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
            }
        }
        return successMsg.toString();
    }


    //通过名称获取单位信息
    @Override
    public Unit getUnitByName(String unitName) {
        return baseMapper.getUnitByName(unitName);
    }


    /**
     * 构建前端所需要下拉树结构
     *
     * @param unitList 部门列表
     * @return 下拉树结构列表
     */
    public List<UnitTreeListVO> buildDeptTreeSelect(List<UnitTreeListVO> unitList) {
        return buildDeptTree(unitList);
    }

    /**
     * 构建前端所需要树结构
     *
     * @param unitList 部门列表
     * @return 树结构列表
     */
    public List<UnitTreeListVO> buildDeptTree(List<UnitTreeListVO> unitList) {
        List<UnitTreeListVO> returnList = new ArrayList<UnitTreeListVO>();
        List<Long> tempList = unitList.stream().map(UnitTreeListVO::getUnitId).toList();
        for (UnitTreeListVO unit : unitList) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(unit.getParentId())) {
                recursionFn(unitList, unit);
                returnList.add(unit);
            }
        }
        if (returnList.isEmpty()) {
            returnList = unitList;
        }
        return returnList;
    }
    private void setUnit(List<Unit> list, List<Long> ids){
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)){
            List<Long> longs = list.stream().map(Unit::getUnitId).toList();
            ids.addAll(longs);
            List<Unit> units = baseMapper.selectList(new LambdaQueryWrapper<Unit>()
                    .in(Unit::getParentId,longs));
            setUnit(units,ids);
        }
    }
    private List<Unit> getUnits(Integer type, Long pid) {
        return baseMapper.selectList(new LambdaQueryWrapper<Unit>()
                .eq(Unit::getType, type).eq(Unit::getParentId, pid));
    }
    /**
     * 递归列表
     */
    private void recursionFn(List<UnitTreeListVO> list, UnitTreeListVO t) {
        // 得到子节点列表
        List<UnitTreeListVO> childList = getChildList(list, t);
        t.setChildren(childList);
        for (UnitTreeListVO tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<UnitTreeListVO> getChildList(List<UnitTreeListVO> list, UnitTreeListVO t) {
        List<UnitTreeListVO> tlist = new ArrayList<UnitTreeListVO>();
        Iterator<UnitTreeListVO> it = list.iterator();
        while (it.hasNext()) {
            UnitTreeListVO n = (UnitTreeListVO) it.next();
            if (StringUtils.isNotNull(n.getParentId()) &&
                    n.getParentId().longValue() == t.getUnitId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<UnitTreeListVO> list, UnitTreeListVO t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }
    private String saveOrUpdate(Map<String, List<Unit>> collect, Unit unit, Integer successNum,
                                Integer failureNum, StringBuilder successMsg,
                                StringBuilder failureMsg, Boolean isUpdateSupport, Long userId, Integer type) {
        List<Unit> list1 = collect.get(unit.getUnitCode());
        if (CollectionUtils.isNotEmpty(list1)) {
            for (Unit d : list1) {
                if (StringUtils.isBlank(d.getUnitName())) {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、数据单位名称为空，导入失败");
                    continue;
                }
                // 验证是否存在这个数据
                Unit u = baseMapper.selectOne(new LambdaQueryWrapper<Unit>()
                        .eq(Unit::getType, type)
                        // .eq(Unit::getParentCode, d.getParentCode())
                        .and(qw -> qw
                                .eq(Unit::getUnitName, d.getUnitName())
                                .or()
                                .eq(Unit::getUnitCode, d.getUnitCode())));
                if (StringUtils.isNull(u)) {
                    BeanValidators.validateWithException(validator, d);
                    d.setCreateUser(userId);
                    d.setParentId(unit.getUnitId());
                    d.setType(String.valueOf(type));
                    this.save(d);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、单位:" + d.getUnitName() + ",导入成功");
                } else if (isUpdateSupport) {
                    BeanValidators.validateWithException(validator, d);
                    d.setUpdateUser(userId);
                    d.setUnitId(u.getUnitId());
                    this.updateById(d);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、单位:" + d.getUnitName() + ",更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、单位:" + d.getUnitName() + ",已存在");
                }
            }
            collect.remove(unit.getUnitCode());
        }
        return successNum + "," + failureNum;
    }

}
