package com.highdatas.mdm.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.highdatas.mdm.controller.MasterAuthorController;
import com.highdatas.mdm.entity.*;
import com.highdatas.mdm.mapper.MasterAuthorMapper;
import com.highdatas.mdm.pojo.MasterAuthorType;
import com.highdatas.mdm.service.*;
import com.highdatas.mdm.util.Constant;
import com.highdatas.mdm.util.ContentBuilder;
import com.highdatas.mdm.util.DbUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author kimi
 * @since 2020-03-23
 */
@Service
public class MasterAuthorServiceImpl extends ServiceImpl<MasterAuthorMapper, MasterAuthor> implements IMasterAuthorService {
    public static final String characterId = "characterId";
    @Autowired
    IMasterAuthorDetailService authorDetailService;
    @Autowired
    ITUserRoleService userRoleService;
    @Autowired
    ISysMenuService menuService;
    @Autowired
    ISysFieldService fieldService;
    @Autowired
    IMaintainFieldService maintainFieldService;
    @Autowired
    IMaintainService maintainService;

    @Override
    public HashMap<String, MasterAuthor> merageRoleAuthor(List<String> roleIds) {
        List<MasterAuthor> masterAuthors = selectList(new EntityWrapper<MasterAuthor>().eq(Constant.TYPE, MasterAuthorType.role).in(MasterAuthorController.character_id, roleIds));
        HashMap<String, MasterAuthor> resultMap = new HashMap<>();

        for (MasterAuthor masterAuthor : masterAuthors) {
            List<MasterAuthorDetail> masterAuthorDetails = authorDetailService.selectList(new EntityWrapper<MasterAuthorDetail>().eq(Constant.PARENT_ID, masterAuthor.getId()));
            masterAuthor.setFields(masterAuthorDetails);

            String key = DbUtils.getFieldRedisKey(masterAuthor.getTableName(), masterAuthor.getMaintainFieldId());
            MasterAuthor preMerageMasterAuthor = resultMap.get(key);
            if (preMerageMasterAuthor == null) {
                resultMap.put(key, masterAuthor);
            }
            else {
                preMerageMasterAuthor = merage(preMerageMasterAuthor, masterAuthor);
                resultMap.put(key, preMerageMasterAuthor);
            }
        }
        return resultMap;
    }

    @Override
    public List<SysMenu> getMenu(String userId) {
        List<MasterAuthor> masterAuthors = selectList(new EntityWrapper<MasterAuthor>().eq(Constant.TYPE, MasterAuthorType.user).eq(MasterAuthorController.character_id, userId));
        if (masterAuthors.size() == 0) {
            //user 获取role
            List<TUserRole> roles = userRoleService.selectList(new EntityWrapper<TUserRole>().eq("user_id", userId));
            List<String> roleIds = roles.stream().map(tUserRole -> tUserRole.getRoleId()).collect(Collectors.toList());
            masterAuthors = selectList(new EntityWrapper<MasterAuthor>().eq(Constant.TYPE, MasterAuthorType.role).in(MasterAuthorController.character_id, roleIds));
        }
        List<String> menuIds = masterAuthors.stream().map(masterAuthor -> masterAuthor.getMenuId()).collect(Collectors.toList());
        LinkedHashSet<String> strings = new LinkedHashSet<>(menuIds);
        LinkedHashSet<String> byParentId = menuService.getByParentId(strings);
        List<SysMenu> sysMenus = menuService.selectBatchIds(byParentId);
        return sysMenus;
    }

    @Override
    public List<SysField> getField(String userId, String maintainFieldId, String maintainId) {
        if (maintainFieldId.equalsIgnoreCase(Constant.All)) {
            List<SysField> total = fieldService.getFieldByMaintain(maintainId);
            return total;
        }
        List<MasterAuthor> masterAuthors = selectList(new EntityWrapper<MasterAuthor>().eq(Constant.TYPE, MasterAuthorType.user).eq(this.characterId, userId).eq("maintain_field_id", maintainFieldId));
        if (masterAuthors.size() == 0) {
            //user 获取role
            List<TUserRole> roles = userRoleService.selectList(new EntityWrapper<TUserRole>().eq("user_id", userId));
            List<String> roleIds = roles.stream().map(tUserRole -> tUserRole.getRoleId()).collect(Collectors.toList());
            masterAuthors = selectList(new EntityWrapper<MasterAuthor>().eq(Constant.TYPE, MasterAuthorType.role).in(this.characterId, roleIds).eq("maintain_field_id", maintainFieldId));
        }
        if (masterAuthors.isEmpty()) {
            return null;
        }
        List<String> authorIds = masterAuthors.stream().map(masterAuthor -> masterAuthor.getId()).collect(Collectors.toList());
        List<MasterAuthorDetail> masterAuthorDetails = authorDetailService.selectList(new EntityWrapper<MasterAuthorDetail>().in(Constant.PARENT_ID, authorIds));
        Set<String> codes = masterAuthorDetails.stream().map(masterAuthorDetail -> masterAuthorDetail.getField()).collect(Collectors.toSet());
        if (codes.isEmpty()) {
            return null;
        }
        Wrapper<SysField> wrapper = new EntityWrapper<SysField>().in(Constant.FIELD, codes);

        if (maintainFieldId.equalsIgnoreCase(Constant.Default)) {
            wrapper.eq("maintain_field_id", maintainFieldId);
        }else {
            wrapper.isNull("maintain_field_id");
        }
        List<SysField> fieldList = fieldService.selectList(wrapper);



        return fieldList;
    }

    @Override
    public boolean checkMaintainAuthor(String userId, String maintainId) {
        Maintain maintain = maintainService.selectById(maintainId);
        if (maintain == null) {
            return false;
        }
        int checked = selectCount(new EntityWrapper<MasterAuthor>()
                .eq(Constant.TYPE, MasterAuthorType.user)
                .eq(MasterAuthorController.character_id, userId)
                .eq("table_name", maintain.getTableName())
                .eq("maintain_field_id", Constant.All));
        if(checked > 0) {
            return true;
        }
        MaintainField maintainField = fieldService.getMaintainFieldByMaintain(maintainId);
        if (maintainField == null) {
            return false;
        }
        //get user author
        checked = selectCount(new EntityWrapper<MasterAuthor>()
                .eq(Constant.TYPE, MasterAuthorType.user)
                .eq(MasterAuthorController.character_id, userId)
                .eq("table_name", maintain.getTableName())
                .eq("maintain_field_id", maintainField.getId()));
        if (checked > 0) {
            return true;
        }
        List<TUserRole> roles = userRoleService.selectList(new EntityWrapper<TUserRole>().eq("user_id", userId));
        Set<String> collect = roles.stream().map(tUserRole -> tUserRole.getRoleId()).collect(Collectors.toSet());
        checked = selectCount(new EntityWrapper<MasterAuthor>()
                .eq(Constant.TYPE, MasterAuthorType.role)
                .in(MasterAuthorController.character_id, collect)
                .eq("table_name", maintain.getTableName())
                .eq("maintain_field_id", maintainField.getId()));
        if (checked > 0) {
            return true;
        }
        return false;
    }

    @Override
    public String getFilter(String userId, String maintainId) {
        MaintainField maintainField = fieldService.getMaintainFieldByMaintain(maintainId);
        if (maintainField)
        if (maintainFieldId.equalsIgnoreCase(Constant.All)) {
            return Constant.WHERE_DEFAULT;
        }
        List<MasterAuthor> masterAuthors = selectList(new EntityWrapper<MasterAuthor>().eq(Constant.TYPE, MasterAuthorType.user).eq(this.characterId, userId).eq("maintain_field_id", maintainFieldId));
        if (masterAuthors.size() == 0) {
            //user 获取role
            List<TUserRole> roles = userRoleService.selectList(new EntityWrapper<TUserRole>().eq("user_id", userId));
            List<String> roleIds = roles.stream().map(tUserRole -> tUserRole.getRoleId()).collect(Collectors.toList());
            masterAuthors = selectList(new EntityWrapper<MasterAuthor>().eq(Constant.TYPE, MasterAuthorType.role).in(this.characterId, roleIds).eq("maintain_field_id", maintainFieldId));
        }
        if (masterAuthors.isEmpty()){
            return Constant.WHERE_DEFAULTUN;
        }
        List<String> authorIds = masterAuthors.stream().map(masterAuthor -> masterAuthor.getId()).collect(Collectors.toList());
        List<MasterAuthorDetail> masterAuthorDetails = authorDetailService.selectList(new EntityWrapper<MasterAuthorDetail>().in(Constant.PARENT_ID, authorIds));
        if (masterAuthorDetails.isEmpty()) {
            return Constant.WHERE_DEFAULTUN;
        }
        HashMap<String, List<String>> segmentMap = new HashMap<>();
        HashMap<String, Boolean> segmentAllMap = new HashMap<>();

        for (MasterAuthorDetail detail : masterAuthorDetails) {
            String field = detail.getField();
            Boolean all = detail.getAll();
            if (!(segmentAllMap.containsKey(field) && segmentAllMap.get(field))) {
                segmentAllMap.put(field, all);
            }

            Boolean preAll = segmentAllMap.get(field);
            if (preAll && segmentMap.containsKey(field)) {
                segmentMap.remove(field);
            }

            String val = detail.getVal();
            List<String> split = DbUtils.split(val);
            segmentMap.put(field,split);
        }
        ContentBuilder builder = new ContentBuilder(Constant.AND);
        Set<String> keySet = segmentMap.keySet();
        for (String code : keySet) {
            List<String> vals = segmentMap.get(code);
            String val = vals.stream()
                    .filter(s -> !StringUtils.isEmpty(s))
                    .map(s -> DbUtils.quotedStr(s)).collect(Collectors.joining(Constant.COMMA));
            String format = MessageFormat.format(Constant.MYSQL_UUID, code, val);
            builder.append(format);
        }
        String filter = builder.toString();
        return filter;
    }

    private MasterAuthor merage(MasterAuthor preMerageMasterAuthor, MasterAuthor masterAuthor) {
        // table name  masterField 一样 只有字段不同了
        List<MasterAuthorDetail> preFields = preMerageMasterAuthor.getFields();
        Map<String, MasterAuthorDetail> fieldMap = masterAuthor.getFields().stream().collect(Collectors.toMap(MasterAuthorDetail::getField, masterAuthorDetail -> masterAuthorDetail));

        HashSet<String> valSet = new HashSet<>();
        for (MasterAuthorDetail preField : preFields) {
            valSet.clear();
            String fieldId = preField.getField();
            String val = preField.getVal();
            if (val.equalsIgnoreCase(Constant.All)) {
                continue;
            }
            MasterAuthorDetail detail = fieldMap.get(fieldId);
            if (detail == null) {
                continue;
            }
            String preAddVal = detail.getVal();
            if (preAddVal.equalsIgnoreCase(Constant.All)) {
                preField.setVal(preAddVal);
                continue;
            }

            valSet.addAll(DbUtils.split(val));
            valSet.addAll(DbUtils.split(preAddVal));

            String resultVal = valSet.stream().collect(Collectors.joining(Constant.SEMICOLON));
            preField.setVal(resultVal);
        }
        return preMerageMasterAuthor;
    }
}