package com.dxhy.admin.sys.service.impl;

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

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dxhy.admin.sys.config.SysConfig;
import com.dxhy.admin.sys.dao.SysTabulateDeptDao;
import com.dxhy.admin.sys.entity.SysTabulateDeptEntity;
import com.dxhy.admin.sys.entity.SysTabulateEntity;
import com.dxhy.admin.sys.service.SysTabulateDeptService;
import com.dxhy.admin.sys.service.SysTabulateService;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.constant.RedisConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.util.redis.RedisUtils;
import com.dxhy.common.utils.Aops;
import com.dxhy.common.utils.PageUtils;
import com.dxhy.common.utils.Query;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author jiaohongyang（焦红阳）
 * @date 2020-09-22
 */
@SuppressWarnings({"AlibabaMethodTooLong", "AlibabaUndefineMagicConstant"})
@Service("sysTabulateDeptService")
@Slf4j
public class SysTabulateDeptServiceImpl extends ServiceImpl<SysTabulateDeptDao, SysTabulateDeptEntity>
    implements SysTabulateDeptService {
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private SysTabulateService sysTabulateService;

    @Override
    public int saveTablateDeptJson(String dataList) {
        try {
            JSONObject jsonObject = JSON.parseObject(dataList);
            String domains = jsonObject.getString("domains");
            List<SysTabulateDeptEntity> tabulateDeptEntities = JSON.parseArray(domains, SysTabulateDeptEntity.class);
            for (SysTabulateDeptEntity tabulateDeptEntity : tabulateDeptEntities) {
                tabulateDeptEntity.setCreateDate(DateUtil.date());
                tabulateDeptEntity.setUpdateDate(DateUtil.date());
            }
            if (tabulateDeptEntities.size() > 0) {
                return this.saveTablateDept(tabulateDeptEntities, "tabulateDept");
            } else {
                return 4;
            }
        } catch (Exception e) {
            log.error("保存角色关联显示列表异常，异常信息：{}", e.toString());
            e.printStackTrace();
            return 3;
        }
    }

    @Override
    public int saveTablateDept(List<SysTabulateDeptEntity> tabulateDeptEntities, String type) {
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);
        if ("tabulate".equals(type)) {
            long menuId = tabulateDeptEntities.get(0).getMenuId();
            String company = tabulateDeptEntities.get(0).getCompany();
            // 删除显示列表分配
            Aops.getSelf(this).deleteTabDate(menuId, company, "");
        }

        // 新增显示列表分配
        Aops.getSelf(this).insertTablate(tabulateDeptEntities);
        return 1;
    }

    @Override
    public int getTablateCount(long menuId, String company) {
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        return Math.toIntExact(this.count(new QueryWrapper<SysTabulateDeptEntity>().eq("menu_id", menuId)
                .eq(StringUtils.isNotBlank(company), "company", company)));
    }

    @Override
    public int deleteTabulate(long tabulateDeptId) {
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);
        try {
            Aops.getSelf(this).deleteTabulateDeptTr(tabulateDeptId);
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("删除角色关联显示列表异常，异常信息：{}", e.toString());
            return 2;
        }

    }

    @Override
    public List<SysTabulateEntity> getTablateDept(long menuId, String company) {
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        return baseMapper.getTabluteDept(menuId, company);
    }

    @Override
    public List<SysTabulateEntity> getTablateNotDept(Map<String, Object> params) {
        String company = (String)params.get("company");
        String menuId = (String)params.get("menuId");
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        return baseMapper.getTabluteNotDept(Long.parseLong(menuId), company);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        String menuId = (String)params.get("menuId");
        String menuCode = (String)params.get("menuCode");
        String tabulateName = (String)params.get("tabulateName");
        String tabulateCode = (String)params.get("tabulateCode");
        String copmany = (String)params.get("company");
        IPage<SysTabulateDeptEntity> page = this.page(new Query<SysTabulateDeptEntity>().getPage(params),
            new QueryWrapper<SysTabulateDeptEntity>().eq("company", copmany).eq("menu_id", menuId)
                .eq(StringUtils.isNotBlank(menuCode), "menu_code", menuCode)
                .eq(StringUtils.isNotBlank(tabulateName), "tabulate_name", tabulateName)
                .eq(StringUtils.isNotBlank(tabulateCode), "tabulate_code", tabulateCode).orderByAsc("order_num"));
        List<SysTabulateDeptEntity> records = page.getRecords();
        if (records.size() > 0) {
            for (SysTabulateDeptEntity entity : records) {
                if (entity.isShowStatus()) {
                    entity.setShowStatusName("是");
                } else {
                    entity.setShowStatusName("否");
                }
            }
        }
        return new PageUtils(page);
    }

    @Override
    public void tabulateRedisValue(String company, long menuId, List<SysTabulateEntity> tabluteList) {
        boolean selection = false;
        boolean showhide = false;
        boolean indexType = false;
        String btnWidth = "";
        // 是否固定
        List<Boolean> titlefixed = new ArrayList<>();
        // 是否超出显示省略号
        List<Boolean> showOverflowTooltip = new ArrayList<>();
        // 是否可以输入
        List<Boolean> inputFixed = new ArrayList<>();
        // 是否显示图片
        List<Boolean> iconFixed = new ArrayList<>();
        // 宽度
        List<String> titlewidth = new ArrayList<>();
        // 中文显示名
        List<String> titlelist = new ArrayList<>();
        // 显示编码
        List<String> titleprop = new ArrayList<>();
        // 显示名空值存储
        List<String> nullTitleProp = new ArrayList<>();
        // 导出显示名
        List<String> excelTitlelist = new ArrayList<>();
        // 导出显示编码
        List<String> excelTitleprop = new ArrayList<>();
        // 是否超出显示省略号
        List<Boolean> sortable = new ArrayList<>();

        // 显示列表按钮
        List<Integer> btn = new ArrayList<>();

        if (tabluteList.size() > 0) {
            for (SysTabulateEntity tabulateEntity : tabluteList) {
                if (!selection) {
                    selection = tabulateEntity.isSelection();
                }
                if (!indexType) {
                    indexType = tabulateEntity.isIndexType();
                }
                if ("1".equals(tabulateEntity.getType())) {
                    if (StringUtils.isNotBlank(tabulateEntity.getTabulateName()) && tabulateEntity.isShowStatus()) {
                        titlefixed.add(tabulateEntity.isTitlefixed());
                        showOverflowTooltip.add(tabulateEntity.isShowOverflowTooltip());
                        titlewidth.add(tabulateEntity.getTitlewidth());
                        inputFixed.add(tabulateEntity.isInputFixed());
                        iconFixed.add(tabulateEntity.isIconFixed());
                        titlelist.add(tabulateEntity.getTabulateName());
                        titleprop.add(tabulateEntity.getTabulateCode());
                        sortable.add(tabulateEntity.isSortable());
                    }
                    if (StringUtils.isBlank(tabulateEntity.getTabulateName())) {
                        nullTitleProp.add(tabulateEntity.getTabulateCode());
                    }

                    if (StringUtils.isNotBlank(tabulateEntity.getTabulateName()) && tabulateEntity.isShowStatus()) {
                        excelTitlelist.add(tabulateEntity.getTabulateName());
                        excelTitleprop.add(tabulateEntity.getTabulateCode());
                    }
                } else if ("3".equals(tabulateEntity.getType())) {
                    if (StringUtils.isNotBlank(tabulateEntity.getTabulateName())) {
                        excelTitlelist.add(tabulateEntity.getTabulateName());
                        excelTitleprop.add(tabulateEntity.getTabulateCode());
                    }
                } else if ("2".equals(tabulateEntity.getType())) {
                    btnWidth = tabulateEntity.getTitlewidth();
                    String tabulateCode = tabulateEntity.getTabulateCode();
                    if (StringUtils.isNotBlank(tabulateCode)) {
                        String[] split = tabulateCode.split(",");
                        for (String b : split) {
                            btn.add(Integer.parseInt(b));
                        }
                        showhide = true;
                    }
                }
            }
        }
        Map<String, Object> map = new HashMap<>(12);
        map.put("listLoading", false);
        map.put("selection", selection);
        map.put("numberSerial", indexType);
        map.put("titlefixed", titlefixed);
        map.put("showOverflowTooltip", showOverflowTooltip);
        map.put("titlewidth", titlewidth);
        map.put("inputfixed", inputFixed);
        map.put("iconfixed", iconFixed);
        map.put("sortable", sortable);
        // 显示列
        Map<String, Object> mapTitle = new HashMap<>(2);
        if (nullTitleProp.size() > 0) {
            titleprop.addAll(nullTitleProp);
        }

        mapTitle.put("titlelist", titlelist);
        mapTitle.put("titleprop", titleprop);

        map.put("titlelist", mapTitle);

        // 按钮
        Map<String, Object> btnMap = new HashMap<>(3);
        btnMap.put("btn", btn);
        btnMap.put("showhide", showhide);
        btnMap.put("width", btnWidth);
        map.put("operating", btnMap);

        String redisKey = RedisConstant.MENU_TABULATE_COMPANY + company + ":" + company + "_" + menuId;
        // 存储redis

        redisUtils.set(redisKey, JSON.toJSONString(map, SerializerFeature.WriteMapNullValue), RedisUtils.NOT_EXPIRE);
        // 显示列
        Map<String, Object> mapExcleTitle = new HashMap<>(2);
        mapExcleTitle.put("titleExcleList", excelTitlelist);
        mapExcleTitle.put("titleExcleProp", excelTitleprop);

        // 保存显示列表到redis 以供导出使用
        redisKey = RedisConstant.MENU_TABULATE_EXCEL + company + ":" + company + "_" + menuId;
        redisUtils.set(redisKey, mapExcleTitle, RedisUtils.NOT_EXPIRE);
    }

    @Override
    public void saveListTablate(List<Long> menuIds, String company) {
        // 获取菜单信息
        List<SysTabulateEntity> tabulates;
        List<SysTabulateDeptEntity> sysTabulateDeptEntityList;
        Map<Long, List<SysTabulateEntity>> tabMap = new HashMap<>(menuIds.size());
        SysTabulateDeptEntity sysTabulateDeptEntity;
        for (long menuId : menuIds) {
            int tablateCount = this.getTablateCount(menuId, company);
            if (tablateCount <= 0) {
                // 获取中心企业id
                String redisKey = RedisConstant.MENU_TABULATE + menuId;
                String s = redisUtils.get(redisKey);
                if (StringUtils.isNotBlank(s)) {
                    tabulates = JSON.parseArray(s, SysTabulateEntity.class);
                } else {
                    tabulates = sysTabulateService.getTablate(null, String.valueOf(menuId), null, null, true);
                    if (tabulates.size() > 0) {
                        redisUtils.set(RedisConstant.MENU_TABULATE + menuId, JSON.toJSONString(tabulates),
                            RedisUtils.NOT_EXPIRE);
                    }

                }
                if (tabulates != null && tabulates.size() > 0) {
                    tabMap.put(menuId, tabulates);
                }
            }

        }
        log.info("保存菜单显示列信息信息：{}", tabMap.size());
        if (tabMap.size() > 0) {
            for (Long menuId : tabMap.keySet()) {
                List<SysTabulateEntity> sysTabulateEntities = tabMap.get(menuId);
                if (sysTabulateEntities.size() > 0) {
                    sysTabulateDeptEntityList = new ArrayList<>();
                    for (SysTabulateEntity tabulateEntity : sysTabulateEntities) {
                        if (tabulateEntity.isDefaultStatus()) {
                            sysTabulateDeptEntity = new SysTabulateDeptEntity();
                            sysTabulateDeptEntity.setCompany(company);
                            sysTabulateDeptEntity.setMenuId(tabulateEntity.getMenuId());
                            sysTabulateDeptEntity.setTabulateId(tabulateEntity.getId());
                            sysTabulateDeptEntity.setTabulateName(tabulateEntity.getTabulateName());
                            sysTabulateDeptEntity.setTabulateCode(tabulateEntity.getTabulateCode());
                            sysTabulateDeptEntity.setCreateDate(DateUtil.date());
                            sysTabulateDeptEntity.setUpdateDate(DateUtil.date());
                            sysTabulateDeptEntity.setOrderNum(tabulateEntity.getOrderNum());
                            sysTabulateDeptEntity.setShowStatus(tabulateEntity.isShowStatus());
                            sysTabulateDeptEntityList.add(sysTabulateDeptEntity);
                        }
                    }
                    if (sysTabulateDeptEntityList.size() > 0) {
                        this.saveTablateDept(sysTabulateDeptEntityList, "tabulate");
                    }
                }
            }

        }

    }

    @Override
    public int refreshCache(String company) {
        log.info("刷新缓存开始，集团编码：{}", company);
        try {
            if (StringUtils.isBlank(company)) {
                company = SysConfig.ZXQY;
            }
            return this.getRefreshCache(company);
        } catch (Exception e) {
            e.printStackTrace();
            return 2;
        }

    }

    @Override
    public int listRefreshCache() {

        try {
            DynamicContextHolder.push(DbConstant.BASICS_READ);
            List<String> listCompany = baseMapper.queryDeptCompany(null);
            if (listCompany.size() > 0) {
                for (String company : listCompany) {
                    this.getRefreshCache(company);
                }
                return 0;
            } else {
                return 1;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return 2;
        }

    }

    public int getRefreshCache(String company) {

        List<SysTabulateEntity> tabluteList = baseMapper.getTabluteDeptPoolRefreshCache(company);
        Map<Long, List<SysTabulateEntity>> collect =
            tabluteList.stream().collect(Collectors.groupingBy(SysTabulateEntity::getMenuId));
        if (!collect.isEmpty()) {
            for (Long menuId : collect.keySet()) {
                this.tabulateRedisValue(company, menuId, collect.get(menuId));
            }
        }

        return 0;

    }

    @Override
    public int deleteTabulateDept(Map<String, Object> params) {
        String menuId = (String)params.get("menuId");
        String tabulateId = (String)params.get("tabulateId");
        String company = (String)params.get("company");
        try {
            DynamicContextHolder.push(DbConstant.BASICS_WRITE);
            Aops.getSelf(this).deleteTabDate(Long.parseLong(menuId), company, tabulateId);
            DynamicContextHolder.push(DbConstant.BASICS_READ);
            List<SysTabulateEntity> tabluteList = baseMapper.getTabluteDept(Long.parseLong(menuId), company);
            if (tabluteList.size() > 0) {
                this.tabulateRedisValue(company, Long.parseLong(menuId), tabluteList);
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return 1;
        }

    }

    @Override
    public int updateTabulateDept(Map<String, Object> params) {
        try {
            String tabulateName = (String)params.get("tabulateName");
            int orderNum = (int)params.get("orderNum");
            String id = (String)params.get("id");
            boolean showStatus = (boolean)params.get("showStatus");
            String tabulateCode = (String)params.get("tabulateCode");
            DynamicContextHolder.push(DbConstant.BASICS_WRITE);

            Aops.getSelf(this).updateTabulateDate(tabulateName, orderNum, id, showStatus, tabulateCode);
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return 1;
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteTabulateDeptTr(long tabulateDeptId) {
        this.removeById(tabulateDeptId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteTabDate(long menuId, String company, String tabulateId) {
        this.remove(new QueryWrapper<SysTabulateDeptEntity>().eq("menu_id", menuId).eq("company", company)
            .eq(StringUtils.isNotBlank(tabulateId), "tabulate_id", tabulateId));
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertTablate(List<SysTabulateDeptEntity> tabulateDeptEntityList) {
        // 批量存储关联信息
        this.saveOrUpdateBatch(tabulateDeptEntityList);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateTabulateDate(String tabulateName, int orderNum, String id, boolean showStatus,
        String tabulateCode) {
        baseMapper.updateTabulateDept(tabulateName, orderNum, id, showStatus, tabulateCode);
    }

    public List<Long> getTabulateDeptPool(String company) {
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        return baseMapper.getTabluteDeptMneuId(company);
    }

    @Override
    public int saveListTablateDeptJson(String dataList) {
        List<SysTabulateDeptEntity> tabulateDeptList = null;
        try {
            JSONObject jsonObject = JSON.parseObject(dataList);
            String company = jsonObject.getString("company");
            if (!"ZXQY".equals(company)) {
                return 5;
            }
            String domains = jsonObject.getString("domains");
            List<SysTabulateDeptEntity> tabulateDeptEntities = JSON.parseArray(domains, SysTabulateDeptEntity.class);

            Long menuId = tabulateDeptEntities.get(0).getMenuId();
            List<String> companys = baseMapper.queryDeptCompany(menuId);
            // 根据菜单ID获取显示列表分配集团信息
            if (companys.size() > 0) {
                tabulateDeptList = new ArrayList<>();
                for (String companyStr : companys) {
                    for (SysTabulateDeptEntity tabulateDeptEntity : tabulateDeptEntities) {
                        tabulateDeptEntity.setCreateDate(DateUtil.date());
                        tabulateDeptEntity.setUpdateDate(DateUtil.date());
                        tabulateDeptEntity.setCompany(companyStr);
                        tabulateDeptList.add(tabulateDeptEntity);
                    }
                }
            }

            if (tabulateDeptList != null && tabulateDeptList.size() > 0) {
                return this.saveTablateDept(tabulateDeptList, "tabulateDept");
            } else {
                return 4;
            }
        } catch (Exception e) {
            log.error("批量保存显示列表异常，异常信息：{}", e.toString());
            e.printStackTrace();
            return 3;
        }
    }
}
