package com.sdtool.business.service;

import com.sdtool.business.dao.SystemDao;
import com.sdtool.common.api.DictService;
import com.sdtool.common.api.NoSqlKeysService;
import com.sdtool.common.base.BaseService;
import com.sdtool.common.datas.RedisKeys;
import com.sdtool.common.entity.site.ERPTokenUser;
import com.sdtool.common.entity.system.DictData;
import com.sdtool.common.entity.system.DictType;
import com.dySweetFishPlugin.redis.RedisService;
import com.dySweetFishPlugin.sql.TableIdService;
import com.dySweetFishPlugin.sql.dao.TunaService;
import com.sweetfish.convert.json.JsonConvert;
import com.sweetfish.service.Local;
import com.sweetfish.service.RetResult;
import com.sweetfish.source.PageFlipper;
import com.sweetfish.util.AnyValue;
import com.sweetfish.util.AutoLoad;
import com.sweetfish.util.ResourceType;
import org.apache.commons.lang3.StringUtils;
import org.rex.RMap;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@AutoLoad(false)
@Local
@ResourceType(DictService.class)
public class DictServiceImpl extends BaseService implements DictService {

    @Resource
    RedisService redisService;

    @Resource
    NoSqlKeysService keysService;

    @Resource
    JsonConvert jsonConvert;

    @Resource
    TunaService tunaService;

    @Resource
    TableIdService tableIdService;

    private SystemDao systemDao;

    @Override
    public void init(AnyValue config) {
        super.init(config);
    }

    @Override
    public void destroy(AnyValue config) {
        super.destroy(config);
    }

    @Override
    public void start(AnyValue config) {
        systemDao = tunaService.generate(SystemDao.class);
    }

    //region 字典管理

    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public RetResult<List<DictType>> getDictTypeList(RMap searchData, PageFlipper pageFlipper, String dataSourceId, long supplierCode) {
        RMap params = new RMap();
        if (searchData != null) {
            params.putAll(searchData);
        }

        if (!params.containsKey("voidFlag")) {
            params.put("voidFlag", -1);
        }

        List<DictType> dictTypeList = systemDao.queryDictTypes(params, dataSourceId, supplierCode, pageFlipper);
        return RetResult.<List<DictType>>successT().result(dictTypeList).page(pageFlipper);
    }

    @Override
    public DictType getDictTypeInfoById(long id, String dataSourceId, long supplierCode) {
        String json = redisService.hget(keysService.getRedisKey(RedisKeys.KEY_ERPDICTTYPE, supplierCode), String.valueOf(id));

        if (StringUtils.isEmpty(json)) {
            return null;
        }

        return jsonConvert.convertFrom(DictType.class, json);
    }

    @Override
    public DictType getDictTypeInfoByText(String dictType, String dataSourceId, long supplierCode) {
        Map<String, String> dictTypeMap = redisService.hgetAll(keysService.getRedisKey(RedisKeys.KEY_ERPDICTTYPE, supplierCode));

        for (String v : dictTypeMap.values()) {
            DictType dict = jsonConvert.convertFrom(DictType.class, v);
            if (dictType.equalsIgnoreCase(dict.getDictType())) {
                return dict;
            }
        }
        return null;
    }

    @Override
    public String getDictTypeName(long id, String dataSourceId, long supplierCode) {
        DictType dictType = getDictTypeInfoById(id, dataSourceId, supplierCode);
        if (dictType == null) {
            return "";
        } else {
            return dictType.getDictName();
        }
    }

    @Override
    public RetResult<DictType> addDictType(DictType dictType, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
        dictType.setId(tableIdService.getTableIdMulti("tbDictType.id", 1, dataSourceId, String.valueOf(supplierCode)));
        dictType.setVoidFlag(0);

        DictType.create(dictType, currentUser.getId());

        //设置redis主表信息
        redisService.hset(keysService.getRedisKey(RedisKeys.KEY_ERPDICTTYPE, supplierCode), String.valueOf(dictType.getId()), jsonConvert.convertTo(dictType));

        systemDao.addDictType(dictType, dataSourceId, supplierCode);

        return RetResult.successT();
    }

    @Override
    public RetResult<DictType> updateDictType(DictType dictType, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
        if (dictType == null) {
            return RetResult.<DictType>errorT().retinfo("请求数据错误");
        }

        if (dictType.getId() <= 0L) {
            return RetResult.<DictType>errorT().retinfo("请求数据错误");
        }

        if (currentUser == null) {
            return RetResult.<DictType>errorT().retinfo("未登录");
        }

        DictType.update(dictType, currentUser.getId());

        DictType redisInfo = getDictTypeInfoById(dictType.getId(), dataSourceId, supplierCode);
        if (redisInfo != null) {
            redisInfo.setDictName(dictType.getDictName());
            redisInfo.setDictType(dictType.getDictType());
            redisInfo.setRemark(dictType.getRemark());
            redisInfo.setUpdateBy(dictType.getUpdateBy());
            redisInfo.setUpdateTime(dictType.getUpdateTime());

            redisService.hset(keysService.getRedisKey(RedisKeys.KEY_ERPDICTTYPE, supplierCode), String.valueOf(redisInfo.getId()), jsonConvert.convertTo(redisInfo));
        }

        systemDao.updateDictType(dictType, dataSourceId, supplierCode);

        return RetResult.successT();
    }

    @Override
    public RetResult<DictType> voidDictType(DictType dictType, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
        if (dictType == null) {
            return RetResult.<DictType>errorT().retinfo("请求数据错误");
        }

        if (dictType.getId() <= 0L) {
            return RetResult.<DictType>errorT().retinfo("请求数据错误");
        }

        if (currentUser == null) {
            return RetResult.<DictType>errorT().retinfo("未登录");
        }

        DictType.update(dictType, currentUser.getId());

        DictType redisInfo = getDictTypeInfoById(dictType.getId(), dataSourceId, supplierCode);
        if (redisInfo != null) {
            redisInfo.setVoidFlag(dictType.getVoidFlag());
            redisInfo.setUpdateBy(dictType.getUpdateBy());
            redisInfo.setUpdateTime(dictType.getUpdateTime());

            redisService.hset(keysService.getRedisKey(RedisKeys.KEY_ERPDICTTYPE, supplierCode), String.valueOf(redisInfo.getId()), jsonConvert.convertTo(redisInfo));
        }

        systemDao.voidDictType(dictType, dataSourceId, supplierCode);

        return RetResult.successT();
    }

    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public RetResult<List<DictData>> getDictDataList(RMap searchData, PageFlipper pageFlipper, String dataSourceId, long supplierCode) {
        RMap params = new RMap();
        if (searchData != null) {
            params.putAll(searchData);
        }

        if (!params.containsKey("idType")) {
            params.put("idType", 0);
        }

        if (!params.containsKey("voidFlag")) {
            params.put("voidFlag", -1);
        }

        List<DictData> dictDataList = systemDao.queryDictDatas(params, dataSourceId, supplierCode, pageFlipper);
        return RetResult.<List<DictData>>successT().result(dictDataList).page(pageFlipper);
    }

    @Override
    public DictData getDictDataInfo(long idType, long id, String dataSourceId, long supplierCode) {
        String json = redisService.hget(keysService.getRedisKey(RedisKeys.KEY_ERPDICTDATA, supplierCode, true) + idType, String.valueOf(id));

        if (StringUtils.isEmpty(json)) {
            return null;
        }

        return jsonConvert.convertFrom(DictData.class, json);
    }

    @Override
    public DictData getDictDataInfoV2(String dictTypeText, long id, String dataSourceId, long supplierCode) {
        DictType dictType = getDictTypeInfoByText(dictTypeText, dataSourceId, supplierCode);

        if (dictType == null) {
            return null;
        }
        String json = redisService.hget(keysService.getRedisKey(RedisKeys.KEY_ERPDICTDATA, supplierCode, true) + dictType.getId(), String.valueOf(id));

        if (StringUtils.isEmpty(json)) {
            return null;
        }

        return jsonConvert.convertFrom(DictData.class, json);
    }

    @Override
    public RetResult<DictData> addDictData(DictData dictData, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
        dictData.setId(tableIdService.getTableIdMulti("tbDictData.id", 1, dataSourceId, String.valueOf(supplierCode)));
        dictData.setVoidFlag(0);

        DictData.create(dictData, currentUser.getId());

        //设置redis主表信息
        redisService.hset(keysService.getRedisKey(RedisKeys.KEY_ERPDICTDATA, supplierCode, true) + dictData.getIdType(), String.valueOf(dictData.getId()), jsonConvert.convertTo(dictData));

        systemDao.addDictData(dictData, dataSourceId, supplierCode);

        return RetResult.successT();
    }

    @Override
    public RetResult<DictData> updateDictData(DictData dictData, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
        if (dictData == null) {
            return RetResult.<DictData>errorT().retinfo("请求数据错误");
        }

        if (dictData.getId() <= 0L) {
            return RetResult.<DictData>errorT().retinfo("请求数据错误");
        }

        if (dictData.getIdType() <= 0L) {
            return RetResult.<DictData>errorT().retinfo("请求数据错误");
        }

        if (currentUser == null) {
            return RetResult.<DictData>errorT().retinfo("未登录");
        }

        DictData.update(dictData, currentUser.getId());

        DictData redisInfo = getDictDataInfo(dictData.getIdType(), dictData.getId(), dataSourceId, supplierCode);
        if (redisInfo != null) {
            redisInfo.setDictLabel(dictData.getDictLabel());
            redisInfo.setDictValue(dictData.getDictValue());
            redisInfo.setSortNum(dictData.getSortNum());
            redisInfo.setCssClass(dictData.getCssClass());
            redisInfo.setListClass(dictData.getListClass());
            redisInfo.setRemark(dictData.getRemark());
            redisInfo.setUpdateBy(dictData.getUpdateBy());
            redisInfo.setUpdateTime(dictData.getUpdateTime());

            redisService.hset(keysService.getRedisKey(RedisKeys.KEY_ERPDICTDATA, supplierCode, true) + redisInfo.getIdType(), String.valueOf(redisInfo.getId()), jsonConvert.convertTo(redisInfo));
        }

        systemDao.updateDictData(dictData, dataSourceId, supplierCode);

        return RetResult.successT();
    }

    @Override
    public RetResult<DictData> voidDictData(DictData dictData, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
        if (dictData == null) {
            return RetResult.<DictData>errorT().retinfo("请求数据错误");
        }

        if (dictData.getId() <= 0L) {
            return RetResult.<DictData>errorT().retinfo("请求数据错误");
        }

        if (dictData.getIdType() <= 0L) {
            return RetResult.<DictData>errorT().retinfo("请求数据错误");
        }

        if (currentUser == null) {
            return RetResult.<DictData>errorT().retinfo("未登录");
        }

        DictData.update(dictData, currentUser.getId());

        DictData redisInfo = getDictDataInfo(dictData.getIdType(), dictData.getId(), dataSourceId, supplierCode);
        if (redisInfo != null) {
            redisInfo.setVoidFlag(dictData.getVoidFlag());
            redisInfo.setUpdateBy(dictData.getUpdateBy());
            redisInfo.setUpdateTime(dictData.getUpdateTime());

            redisService.hset(keysService.getRedisKey(RedisKeys.KEY_ERPDICTDATA, supplierCode, true) + redisInfo.getIdType(), String.valueOf(redisInfo.getId()), jsonConvert.convertTo(redisInfo));
        }
        systemDao.voidDictData(dictData, dataSourceId, supplierCode);
        // systemDao.updateDictData(dictData, dataSourceId, supplierCode);

        return RetResult.successT();
    }

    /**
     * 客户端选择字典类型
     * 从redis中获取字典类型
     *
     * @return 字典数据
     */
    @Override
    public RetResult<List<DictType>> selectDictTypeList(String dataSourceId, long supplierCode) {
        Map<String, String> dictTypeMap = redisService.hgetAll(keysService.getRedisKey(RedisKeys.KEY_ERPDICTTYPE, supplierCode));
        List<DictType> dictTypeList = new ArrayList<>();
        dictTypeMap.forEach((k, v) -> {
            DictType dictType = jsonConvert.convertFrom(DictType.class, v);

            if (dictType.getVoidFlag() == 0) {
                dictTypeList.add(dictType);
            }
        });

        //排序
        dictTypeList.sort((v1, v2) -> -1 * Long.compare(v1.getId(), v2.getId()));

        return RetResult.<List<DictType>>successT().result(dictTypeList);

    }

    /**
     * 客户端选择字典数据
     * 先从redis中获取对应的字典类型，然后获取对应的字典数据
     *
     * @param dictTypeText 字典类型
     * @return 字典数据
     */
    @Override
    @SuppressWarnings("unchecked")
    public RetResult<List<DictData>> selectDictDataList(String dictTypeText, String dataSourceId, long supplierCode) {
        DictType dictType = getDictTypeInfoByText(dictTypeText, dataSourceId, supplierCode);

        if (dictType == null) {
            return RetResult.error().retcode(-1).retinfo("请求数据错误,找不到[" + dictTypeText + "]对应的字典类型");
        }

        Map<String, String> dictDataMap = redisService.hgetAll(keysService.getRedisKey(RedisKeys.KEY_ERPDICTDATA, supplierCode, true) + dictType.getId());
        List<DictData> dictDataList = new ArrayList<>();
        dictDataMap.forEach((k, v) -> {
            DictData dictData = jsonConvert.convertFrom(DictData.class, v);

            if (dictData.getVoidFlag() == 0) {
                dictDataList.add(dictData);
            }
        });

        //排序
        dictDataList.sort((v1, v2) -> {
            if (v1.getSortNum() == v2.getSortNum()) {
                return Long.compare(v1.getId(), v2.getId());
            } else {
                return Integer.compare(v1.getSortNum(), v2.getSortNum());
            }
        });

        return RetResult.success().retcode(0).result(dictDataList);

    }

    @Override
    public RetResult<Map<String, List<DictData>>> selectDictDataListMulti(String dictTypeTextMulti, String dataSourceId, long supplierCode) {
        String[] dictTypeTextArr = dictTypeTextMulti.split(",");
        Map<String, List<DictData>> totalResult = new HashMap<>();
        for (String s : dictTypeTextArr) {
            RetResult<List<DictData>> dictResult = this.selectDictDataList(s, dataSourceId, supplierCode);
            totalResult.put(s, dictResult.getResult());
        }

        return RetResult.<Map<String, List<DictData>>>successT().result(totalResult);
    }


    //endregion
}
