package com.sy.coinage.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sy.coinage.core.exception.RetException;
import com.sy.coinage.core.util.TreeUtil;
import com.sy.coinage.core.util.TreeUtil.TreeNode;
import com.sy.coinage.sys.req.DictBatchAddReq;
import com.sy.coinage.sys.req.DictBatchUpdateReq;
import com.sy.coinage.sys.req.AdminDictAddReq;
import com.sy.coinage.sys.req.vo.DictBatchAddVO;
import java.util.Collection;
import java.util.List;

import com.sy.coinage.sys.req.vo.DictBatchUpdateVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.sy.coinage.sys.dao.DictDao;
import com.sy.coinage.sys.model.*;
import com.sy.coinage.sys.service.IDictService;
import com.sy.coinage.sys.vo.*;
import com.sy.coinage.core.constants.Constants;
import com.sy.coinage.core.vo.OptVO;
import org.springframework.transaction.annotation.Transactional;

/**
 * 字典ServiceImpl
 */
@Service
public class DictServiceImpl extends ServiceImpl<DictDao, Dict> implements IDictService {

    @Override
    public List<DictListVO> treeList(String tag, Integer tenantId) {
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tenant_id", tenantId);
        // queryWrapper.eq("status", Constants.STATUS_USABLE);
        queryWrapper.eq(StringUtils.isNotBlank(tag), "tag", tag);
        queryWrapper.orderByAsc("sorted");
        List<DictListVO> list = this.baseMapper.queryList(queryWrapper);
        Collection<? extends TreeNode<Integer>> resp = TreeUtil.buildTree(list, 0);
        return (List<DictListVO>) resp;
    }

    @Override
    public List<OptVO> opt(String tag, Integer tenantId) {
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
//        queryWrapper.and(wq -> {
//            // 拼接sql
//            wq.eq("tenant_id", tenantId)
//                    .or()
//                    .eq("tenant_id", -1);
//        });
        queryWrapper.ne("pid", 0);
        queryWrapper.eq("status", Constants.STATUS_USABLE);
        queryWrapper.eq(StringUtils.isNotBlank(tag), "tag", tag);
        queryWrapper.orderByAsc("sorted");
        List<OptVO> resp = this.baseMapper.queryOptList(queryWrapper);
        return resp;
    }

    @Override
    public List<OptVO> treeOpt(String tag, Integer tenantId) {
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
//        queryWrapper.and(wq -> {
//            // 拼接sql
//            wq.eq("tenant_id", tenantId)
//                    .or()
//                    .eq("tenant_id", -1);
//        });
        queryWrapper.ne("pid", 0);
        queryWrapper.eq("status", Constants.STATUS_USABLE);
        queryWrapper.eq(StringUtils.isNotBlank(tag), "tag", tag);
        queryWrapper.orderByAsc("sorted");
        List<OptVO> list = this.baseMapper.queryOptList(queryWrapper);
        Collection<? extends TreeNode<Integer>> resp = TreeUtil.buildTree(list, 0);
        return (List<OptVO>) resp;
    }

    @Override
    public List<OptVO> cascadeOpt(String tag, Integer id, Integer tenantId) {
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
//        queryWrapper.and(wq -> {
//            // 拼接sql
//            wq.eq("tenant_id", tenantId)
//                    .or()
//                    .eq("tenant_id", -1);
//        });
        queryWrapper.eq("tag", tag).eq("status", Constants.STATUS_USABLE);
        queryWrapper.eq("pid", id);
        queryWrapper.orderByAsc("sorted");
        List<OptVO> resp = this.baseMapper.queryOptList(queryWrapper);
        return resp;
    }

    @Override
    @Transactional
    public void batchAdd(DictBatchAddReq req) {
        Dict model = this.getById(req.getId());
        // 添加子集
        this.addChild(model, req.getList());
    }

    @Override
    @Transactional
    public void batchUpdate(DictBatchUpdateReq req) {
        Dict p = this.getById(req.getId());
        BeanUtils.copyProperties(req, p);
        this.updateById(p);
        for (int i = 0; i < req.getList().size(); i++) {
            DictBatchUpdateVO vo = req.getList().get(i);
            if (vo.getId() != null && vo.getId() > 0) {
                Dict model = this.getById(req.getList().get(i).getId());
                BeanUtils.copyProperties(req.getList().get(i), model);
                this.updateById(model);
            } else {
                Dict model = new Dict();
                BeanUtils.copyProperties(vo, model);
                model.setLevels(null == p.getLevels() ? 1 : p.getLevels() + 1);
                model.setPid(p.getId());
                model.setStatus(Constants.STATUS_USABLE);
                model.setTenantId(p.getTenantId());
                model.setTag(p.getTag());
                this.save(model);
            }
        }
    }

    @Override
    @Transactional
    public void adminaAdd(AdminDictAddReq req) {
        if (req.getTenantIds() != null && req.getTenantIds().size() > 0) {
            for (int i = 0; i < req.getTenantIds().size(); i++) {
                for (int j = 0; j < req.getList().size(); j++) {
                    DictBatchAddVO dictBatchAddVO = req.getList().get(j);
                    // 验证tag是否重复
                    this.validTag(dictBatchAddVO.getTag());
                    this.baseAdd(dictBatchAddVO, req.getTenantIds().get(i));
                }
            }
        } else {
            for (int i = 0; i < req.getList().size(); i++) {
                DictBatchAddVO dictBatchAddVO = req.getList().get(i);
                // 验证tag是否重复
                this.validTag(dictBatchAddVO.getTag());
                this.baseAdd(dictBatchAddVO, null);
            }
        }
    }

    @Override
    public Dict getByVal(Object tag, Object val, Integer tenantId) {
        LambdaQueryWrapper<Dict> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.and(wq -> {
//            // 拼接sql
//            wq.eq(Dict::getTenantId, tenantId)
//                    .or()
//                    .eq(Dict::getTenantId, -1);
//        });
        queryWrapper.ne(Dict::getPid, 0);
        queryWrapper.eq(Dict::getVal, val);
        queryWrapper.eq(Dict::getTag, tag);
        Dict resp = this.getOne(queryWrapper);
//        if (resp == null) {
//            throw new RetException("字典不存在tag=" + tag + ",val=" + val);
//        }
        return resp;
    }

    private void baseAdd(DictBatchAddVO dictBatchAddVO, Integer tenantId) {
//        if (tenantId == null) {
//            tenantId = -1;
//        }
        Dict model = new Dict();
        BeanUtils.copyProperties(dictBatchAddVO, model);
        model.setLevels(1);
        model.setPid(0);
        model.setStatus(Constants.STATUS_USABLE);
        model.setTenantId(tenantId);
        this.save(model);
    }

    /**
     * 添加子集
     */
    private void addChild(Dict p, List<DictBatchAddVO> list) {
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                Dict model = new Dict();
                BeanUtils.copyProperties(list.get(i), model);
                model.setTenantId(p.getTenantId());
                model.setPid(p.getId());
                model.setTag(p.getTag());
                model.setLevels(null == p.getLevels() ? 1 : p.getLevels() + 1);
                model.setStatus(Constants.STATUS_USABLE);
                this.save(model);
            }
        }
    }


    /**
     * 验证tag是否重复
     *
     * @param tag
     */
    private void validTag(String tag) {
        LambdaQueryWrapper<Dict> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dict::getTag, tag);
        long count = this.count(queryWrapper);
        if (count > 0) {
            throw new RetException(tag + "字典标识已存在");
        }
    }

}
