package com.sdtool.business.service;

import com.sdtool.business.dao.SystemDao;
import com.sdtool.common.api.DeptService;
import com.sdtool.common.api.NoSqlKeysService;
import com.sdtool.common.base.BaseService;
import com.sdtool.common.datas.RedisKeys;
import com.sdtool.common.entity.base.ZTreeData;
import com.sdtool.common.entity.convert.EntityReproduce;
import com.sdtool.common.entity.site.ERPTokenUser;
import com.sdtool.common.entity.system.Dept;
import com.sdtool.common.tool.ERPUtils;
import com.sdtool.common.tool.TreeDeptUtils;
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.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.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@AutoLoad(false)
@Local
@ResourceType(DeptService.class)
public class DeptServiceImpl extends BaseService implements DeptService {

    @Resource
    RedisService redisService;

    @Resource
    NoSqlKeysService keysService;

    @Resource
    JsonConvert jsonConvert;

    @Resource
    TableIdService tableIdService;

    @Resource
    TunaService tunaService;

    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 部门档案

    private Dept getRedisDept(long deptId, long supplierCode) {
        String json = redisService.hget(keysService.getRedisKey(RedisKeys.KEY_DEPT, supplierCode), String.valueOf(deptId));

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

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

    /**
     * 获取部门名称
     *
     * @param deptId       部门id
     * @param supplierCode 分表
     * @return 部门名称
     */
    public String getRedisDeptName(long deptId, long supplierCode) {
        Dept dept = getRedisDept(deptId, supplierCode);

        if (dept == null) {
            return "";
        } else {
            return dept.getDeptName();
        }
    }

    public String getRedisDeptCode(long deptId, long supplierCode) {
        Dept dept = getRedisDept(deptId, supplierCode);

        if (dept == null) {
            return "";
        } else {
            return dept.getDeptCode();
        }
    }

    @SuppressWarnings("unused")
    private List<Dept> processTreeDepts(List<Dept> deptList) {
        //排序完成后进行树形处理
        return TreeDeptUtils.generateTreeDepts(deptList, 0);
    }

    /**
     * 获取部门列表
     * 从redis中获取
     *
     * @param searchData 查询条件
     * @return 部门列表
     */
    @SuppressWarnings("rawtypes")
    public RetResult<List<Dept>> getDeptList(RMap searchData, long supplierCode) {
        String searchDeptName = "";
        if (ERPUtils.mapContainKey(searchData, "deptName")) {
            searchDeptName = searchData.getString("deptName");
        } else if (ERPUtils.mapContainKey(searchData, "keyWord")) {
            searchDeptName = searchData.getString("keyWord");
        }

        int searchStatus = -1;
        if (ERPUtils.mapContainKey(searchData, "status")) {
            searchStatus = searchData.getInt("status");
        }

        Map<String, String> deptMap = redisService.hgetAll(keysService.getRedisKey(RedisKeys.KEY_DEPT, supplierCode));
        List<Dept> deptList = new ArrayList<>();

        final String finalDeptName = searchDeptName;
        final int finalStatus = searchStatus;

        deptMap.forEach((k, v) -> {
            Dept dept = jsonConvert.convertFrom(Dept.class, v);
            boolean canAdd = true;

            if (StringUtils.isNotEmpty(finalDeptName)) {
                canAdd = dept.getDeptName().contains(finalDeptName);
            }

            if (finalStatus >= 0) {
                canAdd = canAdd && (dept.getStatus() == finalStatus);
            }

            if (canAdd) {
                deptList.add(dept);
            }
        });
        List<Dept> sortedList = deptList.stream().sorted(Comparator.comparing(Dept::getSortNum)).collect(Collectors.toList());

        // List<Dept> resultDeptList = processTreeDepts(deptList);
        return RetResult.<List<Dept>>successT().result(sortedList);

    }

    public RetResult<List<ZTreeData>> getDeptTreeData(int showAll, long supplierCode) {
        Map<String, String> deptMap = redisService.hgetAll(keysService.getRedisKey(RedisKeys.KEY_DEPT, supplierCode));
        List<ZTreeData> deptList = new ArrayList<>();

        if (showAll == 1) {
            ZTreeData dataAll = new ZTreeData();
            dataAll.setId(-1);
            dataAll.setpId(0);
            dataAll.setName("全部");
            dataAll.setTitle("全部");

            deptList.add(dataAll);
        }

        deptMap.forEach((k, v) -> {
            Dept dept = jsonConvert.convertFrom(Dept.class, v);
            if (dept.getStatus() == 0) {
                ZTreeData data = new ZTreeData();
                data.setId(dept.getId());
                data.setpId(dept.getParentId());
                data.setName(dept.getDeptName());
                data.setTitle(dept.getDeptName());

                deptList.add(data);
            }
        });

        return RetResult.<List<ZTreeData>>successT().result(deptList);
    }

    /**
     * 增加部门
     *
     * @param dept        部门信息
     * @param currentUser 操作人
     * @return 操作信息
     */
    public RetResult<Dept> addDept(Dept dept, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
        dept.setId(tableIdService.getTableIdMulti("tbDept.id", 1, dataSourceId, String.valueOf(supplierCode)));
        dept.setDeptCode(tableIdService.getTableCodeMulti("tbDept.code", dataSourceId, String.valueOf(supplierCode)));
        dept.setStatus(0);

        if (dept.getParentId() <= 0) {
            dept.setParentId(0);
        }

        Dept.create(dept, currentUser.getId());

        redisService.hset(keysService.getRedisKey(RedisKeys.KEY_DEPT, supplierCode), String.valueOf(dept.getId()), jsonConvert.convertTo(dept));

        systemDao.addDept(dept, dataSourceId, supplierCode);

        return RetResult.successT();
    }

    public RetResult<Dept> getDeptInfo(long deptId, long supplierCode) {
        Dept dept = getRedisDept(deptId, supplierCode);

        if (dept != null) {
            dept.setParentName(getRedisDeptName(dept.getParentId(), supplierCode));
        }

        return RetResult.<Dept>successT().result(dept);
    }

    /**
     * 修改部门
     *
     * @param dept        部门信息
     * @param currentUser 操作人
     * @return 操作信息
     */
    public RetResult<Dept> updateDept(Dept dept, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
        if (dept == null) {
            return RetResult.<Dept>errorT().retinfo("请求数据错误");
        }

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

        if (dept.getId() == dept.getParentId()) {
            return RetResult.<Dept>errorT().retinfo("上级部门不能为本部门");
        }

        Dept.update(dept, currentUser.getId());

        Dept redisDept = getRedisDept(dept.getId(), supplierCode);
        if (redisDept != null) {
            EntityReproduce.deptReproduce.apply(redisDept, dept);
            redisService.hset(keysService.getRedisKey(RedisKeys.KEY_DEPT, supplierCode), String.valueOf(redisDept.getId()), jsonConvert.convertTo(redisDept));
        }

        systemDao.updateDept(dept, dataSourceId, supplierCode);

        return RetResult.successT();
    }

    /**
     * 切换部门状态
     *
     * @param dept        部门信息
     * @param currentUser 操作人
     * @return 操作信息
     */
    public RetResult<Dept> voidDept(Dept dept, ERPTokenUser currentUser, String dataSourceId, long supplierCode) {
        Dept.update(dept, currentUser.getId());

        Dept redisDept = getRedisDept(dept.getId(), supplierCode);
        if (redisDept != null) {
            redisDept.setStatus(dept.getStatus());
            redisDept.setUpdateBy(dept.getUpdateBy());
            redisDept.setUpdateTime(dept.getUpdateTime());

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

        systemDao.voidDept(dept, dataSourceId, supplierCode);

        return RetResult.successT();
    }

    //endregion

}
