package com.njcn.gather.system.dictionary.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.db.mybatisplus.constant.DbConstant;
import com.njcn.gather.system.dictionary.mapper.DictTypeMapper;
import com.njcn.gather.system.dictionary.pojo.param.DictTypeParam;
import com.njcn.gather.system.dictionary.pojo.po.DictData;
import com.njcn.gather.system.dictionary.pojo.po.DictType;
import com.njcn.gather.system.dictionary.pojo.vo.DictDataExcel;
import com.njcn.gather.system.dictionary.pojo.vo.DictTypeExcel;
import com.njcn.gather.system.dictionary.service.IDictDataService;
import com.njcn.gather.system.dictionary.service.IDictTypeService;
import com.njcn.gather.system.pojo.enums.SystemResponseEnum;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.ExcelUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author hongawen
 * @since 2021-12-13
 */
@Service
@RequiredArgsConstructor
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper, DictType> implements IDictTypeService {
    private final IDictDataService dictDataService;

    @Override
    public Page<DictType> listDictTypes(DictTypeParam.QueryParam queryParam) {
        QueryWrapper<DictType> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(queryParam)) {
            queryWrapper.like(StrUtil.isNotBlank(queryParam.getName()), "sys_dict_type.name", queryParam.getName())
                    .like(StrUtil.isNotBlank(queryParam.getCode()), "sys_dict_type.code", queryParam.getCode());
            //排序
            if (ObjectUtil.isAllNotEmpty(queryParam.getSortBy(), queryParam.getOrderBy())) {
                queryWrapper.orderBy(true, queryParam.getOrderBy().equals(DbConstant.ASC), StrUtil.toUnderlineCase(queryParam.getSortBy()));
            } else {
                //没有排序参数，默认根据sort字段排序，没有排序字段的，根据updateTime更新时间排序
                queryWrapper.orderBy(true, true, "sys_dict_type.sort").orderByDesc("sys_dict_type.update_time");
            }
        } else {
            queryWrapper.orderBy(true, true, "sys_dict_type.sort").orderByDesc("sys_dict_type.update_time");
        }
        queryWrapper.ne("sys_dict_type.state", DataStateEnum.DELETED.getCode());
        return this.baseMapper.selectPage(new Page<>(PageFactory.getPageNum(queryParam), PageFactory.getPageSize(queryParam)), queryWrapper);
    }

    @Override
    @Transactional
    public boolean addDictType(DictTypeParam dictTypeParam) {
        dictTypeParam.setName(dictTypeParam.getName().trim());
        checkDicTypeName(dictTypeParam, false);
        DictType dictType = new DictType();
        BeanUtil.copyProperties(dictTypeParam, dictType);
        //默认为正常状态
        dictType.setState(DataStateEnum.ENABLE.getCode());
        return this.save(dictType);
    }

    @Override
    @Transactional
    public boolean updateDictType(DictTypeParam.UpdateParam updateParam) {
        updateParam.setName(updateParam.getName().trim());
        checkDicTypeName(updateParam, true);
        DictType dictType = new DictType();
        BeanUtil.copyProperties(updateParam, dictType);
        return this.updateById(dictType);
    }

    @Override
    @Transactional
    public boolean deleteDictType(List<String> ids) {
        dictDataService.deleteDictDataByDictTypeId(ids);
        return this.lambdaUpdate()
                .set(DictType::getState, DataStateEnum.DELETED.getCode())
                .in(DictType::getId, ids)
                .update();
    }

    @Override
    public void exportDictType(DictTypeParam.QueryParam queryParam) {
        QueryWrapper<DictType> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(queryParam)) {
            queryWrapper.like(StrUtil.isNotBlank(queryParam.getName()), "sys_dict_type.name", queryParam.getName())
                    .like(StrUtil.isNotBlank(queryParam.getCode()), "sys_dict_type.code", queryParam.getCode());
            //排序
            if (ObjectUtil.isAllNotEmpty(queryParam.getSortBy(), queryParam.getOrderBy())) {
                queryWrapper.orderBy(true, queryParam.getOrderBy().equals(DbConstant.ASC), StrUtil.toUnderlineCase(queryParam.getSortBy()));
            } else {
                //没有排序参数，默认根据sort字段排序，没有排序字段的，根据updateTime更新时间排序
                queryWrapper.orderBy(true, true, "sys_dict_type.sort").orderByDesc("sys_dict_type.update_time");
            }
        }
        queryWrapper.ne("sys_dict_type.state", DataStateEnum.DELETED.getCode());
        List<DictType> dictTypes = this.list(queryWrapper);

        List<DictTypeExcel> dictTypeVOS = new ArrayList<>();
        dictTypes.forEach(dictType -> {
            DictTypeExcel dictTypeExcel = BeanUtil.copyProperties(dictType, DictTypeExcel.class);
            List<DictData> dictDataList = dictDataService.listDictDataByTypeId(dictType.getId());
            List<DictDataExcel> dictDataExcels = BeanUtil.copyToList(dictDataList, DictDataExcel.class);
            dictTypeExcel.setDictDataExcels(dictDataExcels);
            dictTypeVOS.add(dictTypeExcel);
        });

        ExcelUtil.exportExcel("字典类型导出数据.xlsx", "字典类型", DictTypeExcel.class, dictTypeVOS);
    }

    @Override
    public DictType getByCode(String code) {
        return this.lambdaQuery().eq(DictType::getCode, code).eq(DictType::getState, DataStateEnum.ENABLE.getCode()).one();
    }

    /**
     * 校验参数，检查是否存在相同名称的字典类型
     */
    private void checkDicTypeName(DictTypeParam dictTypeParam, boolean isExcludeSelf) {
        LambdaQueryWrapper<DictType> dictTypeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dictTypeLambdaQueryWrapper.eq(DictType::getState, DataStateEnum.ENABLE.getCode())
                .and(w -> w.eq(DictType::getCode, dictTypeParam.getCode()).or().eq(DictType::getName, dictTypeParam.getName()));
        //更新的时候，需排除当前记录
        if (isExcludeSelf) {
            if (dictTypeParam instanceof DictTypeParam.UpdateParam) {
                dictTypeLambdaQueryWrapper.ne(DictType::getId, ((DictTypeParam.UpdateParam) dictTypeParam).getId());
            }
        }
        int countByAccount = this.count(dictTypeLambdaQueryWrapper);
        //大于等于1个则表示重复
        if (countByAccount >= 1) {
            throw new BusinessException(SystemResponseEnum.DICT_TYPE_REPEAT);
        }
    }
}
