package com.jeeplus.sys.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeeplus.center.enums.ServiceAliasEnum;
import com.jeeplus.centerservice.utils.RestTemplateService;
import com.jeeplus.sys.domain.Office;
import com.jeeplus.sys.domain.RosterBaseC;
import com.jeeplus.sys.domain.SysUserFailedLog;
import com.jeeplus.sys.domain.User;
import com.jeeplus.sys.mapper.RosterBaseCMapper;
import com.jeeplus.sys.service.dto.UserDTO;
import com.jeeplus.sys.utils.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
public class RosterBaseCService extends ServiceImpl<RosterBaseCMapper, RosterBaseC> {

    @Autowired
    private OfficeService officeService;

    @Autowired
    private RestTemplateService restTemplateService;

    @Autowired
    private SysUserFailedLogService sysUserFailedLogService;

    @Autowired
    private UserService userService;

    /**
     * 推送其他系统同步保存用户信息
     * @param rosterBase
     */
    public void syncPushSubsystem(RosterBaseC rosterBase, String oldOfficeId) {
        // 接口所需参数
        Map<String,Object> bodyMap = JSONObject.parseObject(JSON.toJSONString(rosterBase), Map.class);
        // 判断是否有修改用户的所属部门(oldOfficeId为空，则直接进行保存推送)。
        // 没有修改的话，则直接进行保存推送。有修改的话，要判断是否所属同一个子系统。
        // 有修改的话。所属是同一个子系统 则直接进行保存推送，不是 则要清空旧所属系统的用户，再保存到新所属系统中
        String pushType = "";
        if (StringUtils.isNotBlank(oldOfficeId) && !oldOfficeId.equals(rosterBase.getOfficeId())) {
            String officeCode1 = getServiceByOffice(oldOfficeId);
            String officeCode2 = getServiceByOffice(rosterBase.getOfficeId());
            if (StringUtils.isNotBlank(officeCode1) && StringUtils.isNotBlank(officeCode2) && !officeCode1.equals(officeCode2) && !ServiceAliasEnum.CPA_PUBLIC.getValue().equals(officeCode2)) {
                // 有修改用户的所属部门，并且所属不是同一个子系统，修改后的所属部门不是公共部门时，则要清除旧所属系统的该用户，再保存到新所属系统中
                pushType = "clear";
            }
        }
        // 根据所属部门来判断，要向哪个子系统推送保存操作
        // 根据部门id找出该部门的二级部门，获取这个二级部门的别名code
        String officeCode = getServiceByOffice(rosterBase.getOfficeId());
        // 清除旧所属系统的该用户
        if (StringUtils.isNotBlank(pushType)&&pushType.equals("clear")) {
            String officeCodeOld = getServiceByOffice(oldOfficeId);  // 根据这个部门id获取二级部门的别名code来获取所属哪个子系统
            if (StringUtils.isNotBlank(officeCodeOld)) {
                // 评估
                if (ServiceAliasEnum.CPA_EVALUATION.getValue().equals(officeCodeOld) || (ServiceAliasEnum.CPA_PUBLIC.getValue().equals(officeCodeOld) && !ServiceAliasEnum.CPA_EVALUATION.getValue().equals(officeCode))) {
                    // 首先将数据记录为清除失败，待获取到其他系统执行成功的回值后再将此记录删掉
                    String dataId = sysUserFailedLogService.deleteFailedLog(rosterBase.getUserId(), ServiceAliasEnum.CPA_EVALUATION.getValue());
                    // 调用其他系统的用户删除操作
                    Object res = restTemplateService.postCPA_EVALUATION("/roster/base/deleteUserRoster",null,null,bodyMap);
                    if (ObjectUtil.isNotEmpty(res)) {
                        Map<String,Object> resMap = JSONObject.parseObject(JSON.toJSONString(res), Map.class);
                        if ((Boolean) resMap.get("success")) {
                            // 保存成功，将刚才记录的数据删除
                            sysUserFailedLogService.removeById(dataId);
                        }
                    }
                }
                // 财务
                if (ServiceAliasEnum.CPA_FINANCE.getValue().equals(officeCodeOld) || (ServiceAliasEnum.CPA_PUBLIC.getValue().equals(officeCodeOld) && !ServiceAliasEnum.CPA_FINANCE.getValue().equals(officeCode))) {
                    // 首先将数据记录为清除失败，待获取到其他系统执行成功的回值后再将此记录删掉
                    String dataId = sysUserFailedLogService.deleteFailedLog(rosterBase.getUserId(), ServiceAliasEnum.CPA_FINANCE.getValue());
                    // 调用其他系统的用户删除操作
                    Object res = restTemplateService.postCPA_FINANCE("/roster/base/deleteUserRoster",null,null,bodyMap);
                    if (ObjectUtil.isNotEmpty(res)) {
                        Map<String,Object> resMap = JSONObject.parseObject(JSON.toJSONString(res), Map.class);
                        if ((Boolean) resMap.get("success")) {
                            // 保存成功，将刚才记录的数据删除
                            sysUserFailedLogService.removeById(dataId);
                        }
                    }
                }
                // 中审
                if (ServiceAliasEnum.CPA_AUDIT.getValue().equals(officeCodeOld) || (ServiceAliasEnum.CPA_PUBLIC.getValue().equals(officeCodeOld)) && !ServiceAliasEnum.CPA_AUDIT.getValue().equals(officeCode)) {
                    // 首先将数据记录为清除失败，待获取到其他系统执行成功的回值后再将此记录删掉
                    String dataId = sysUserFailedLogService.deleteFailedLog(rosterBase.getUserId(), ServiceAliasEnum.CPA_AUDIT.getValue());
                    // 调用其他系统的用户删除操作
                    Object res = restTemplateService.postCPA_AUDIT("/roster/base/deleteUserRoster",null,null,bodyMap);
                    if (ObjectUtil.isNotEmpty(res)) {
                        Map<String,Object> resMap = JSONObject.parseObject(JSON.toJSONString(res), Map.class);
                        if ((Boolean) resMap.get("success")) {
                            // 保存成功，将刚才记录的数据删除
                            sysUserFailedLogService.removeById(dataId);
                        }
                    }
                }
            }
        }

        // 向子系统推送保存操作
        if (StringUtils.isNotBlank(officeCode)) {
            // 评估
            if (ServiceAliasEnum.CPA_EVALUATION.getValue().equals(officeCode) || ServiceAliasEnum.CPA_PUBLIC.getValue().equals(officeCode)) {
                // 首先将数据记录为保存失败，待获取到其他系统执行成功的回值后再将此记录删掉
                String dataId = sysUserFailedLogService.saveFailedLog(rosterBase.getUserId(), ServiceAliasEnum.CPA_EVALUATION.getValue());
                // 调用其他系统的用户保存操作
                Object res = restTemplateService.postCPA_EVALUATION("/roster/base/saveOrUpdateUserRoster",null,null,bodyMap);
                if (ObjectUtil.isNotEmpty(res)) {
                    Map<String,Object> resMap = JSONObject.parseObject(JSON.toJSONString(res), Map.class);
                    if ((Boolean) resMap.get("success")) {
                        // 保存成功，将刚才记录的数据删除
                        sysUserFailedLogService.removeById(dataId);
                    }
                }
            }
            // 财务
            if (ServiceAliasEnum.CPA_FINANCE.getValue().equals(officeCode) || ServiceAliasEnum.CPA_PUBLIC.getValue().equals(officeCode)) {
                // 首先将数据记录为保存失败，待获取到其他系统执行成功的回值后再将此记录删掉
                String dataId = sysUserFailedLogService.saveFailedLog(rosterBase.getUserId(), ServiceAliasEnum.CPA_FINANCE.getValue());
                // 调用其他系统的用户保存操作
                Object res = restTemplateService.postCPA_FINANCE("/roster/base/saveOrUpdateUserRoster",null,null,bodyMap);
                if (ObjectUtil.isNotEmpty(res)) {
                    Map<String,Object> resMap = JSONObject.parseObject(JSON.toJSONString(res), Map.class);
                    if ((Boolean) resMap.get("success")) {
                        // 保存成功，将刚才记录的数据删除
                        sysUserFailedLogService.removeById(dataId);
                    }
                }
            }
            // 中审
            if (ServiceAliasEnum.CPA_AUDIT.getValue().equals(officeCode) || ServiceAliasEnum.CPA_PUBLIC.getValue().equals(officeCode)) {
                // 首先将数据记录为保存失败，待获取到其他系统执行成功的回值后再将此记录删掉
                String dataId = sysUserFailedLogService.saveFailedLog(rosterBase.getUserId(), ServiceAliasEnum.CPA_AUDIT.getValue());
                // 调用其他系统的用户保存操作
                Object res = restTemplateService.postCPA_AUDIT("/roster/base/saveOrUpdateUserRoster",null,null,bodyMap);
                if (ObjectUtil.isNotEmpty(res)) {
                    Map<String,Object> resMap = JSONObject.parseObject(JSON.toJSONString(res), Map.class);
                    if ((Boolean) resMap.get("success")) {
                        // 保存成功，将刚才记录的数据删除
                        sysUserFailedLogService.removeById(dataId);
                    }
                }
            }
        }
    }

    /**
     * 根据部门id找出该部门的二级部门(包含此部门就是二级部门的可能)，然后获取这个二级部门的别名code
     * @param officeId
     * @return
     */
    public String getServiceByOffice(String officeId) {
        String officeAlias = "";
        Office office = officeService.getById(officeId);
        if (ObjectUtil.isNotEmpty(office)) {
            if (StringUtils.isNotBlank(office.getIsPublic()) && "1".equals(office.getIsPublic())) {
                officeAlias = ServiceAliasEnum.CPA_PUBLIC.getValue(); // 共有部门
            }else if (StringUtils.isNotBlank(office.getGrade()) && "2".equals(office.getGrade())) {
                officeAlias =  StringUtils.isNotBlank(office.getCode()) ? office.getCode() : "";
            } else {
                if (StringUtils.isNotBlank(office.getParentIds())) {
                    String[] split = office.getParentIds().split(",");
                    List<String> ids = Arrays.asList(split);
                    for (String oId : ids) {
                        Office o = officeService.getById(oId);
                        if (ObjectUtil.isNotEmpty(o) && StringUtils.isNotBlank(o.getGrade()) && "2".equals(o.getGrade())) {
                            officeAlias =  StringUtils.isNotBlank(o.getCode()) ? o.getCode() : "";
                        }
                    }
                }
            }
        }
        return officeAlias;
    }

    /**
     * 查询当前花名册推送子系统是否成功
     * @param userId
     * @return
     */
    public Map<String,Object> checkIsSyncFailed(String userId) {
        User user = userService.getById(userId);
        Map<String,Object> res = new HashMap<>();
        if (ObjectUtil.isNotEmpty(user)) {
            // 查询当前用户推送子系统是否成功， isPush != 1说明未推送成功
            List<SysUserFailedLog> sysUserFailedLogList = sysUserFailedLogService.list(new LambdaQueryWrapper<SysUserFailedLog>()
                    .eq(SysUserFailedLog::getUserId, user.getId())
                    .ne(SysUserFailedLog::getIsPush, "1")
            );
            if (sysUserFailedLogList.size() > 0) {
                res.put("success", false);
                List<String> msg = changeFailedLogToMsg(sysUserFailedLogList);
                if (msg.size() > 0) {
                    String message = msg.stream().collect(Collectors.joining(","));
                    res.put("message", message);
                } else {
                    res.put("message", "有推送失败的数据");
                }
            } else {
                res.put("success", true);
            }
        } else {
            res.put("success", false);
            res.put("message", "没有获取到当前用户数据");
        }

        return res;
    }

    // 推送到子系统未成功的日志转换为msg
    public List<String> changeFailedLogToMsg(List<SysUserFailedLog> sysUserFailedLogList) {
        List<String> msg = new ArrayList<>();
        sysUserFailedLogList.stream().forEach(item -> {
            ServiceAliasEnum serviceAliasEnum = ServiceAliasEnum.getByValue(item.getBelongService());
            String label = serviceAliasEnum.getLabel();
            if ("0".equals(item.getIsSuccess())) {
                msg.add("“" + label + "”系统同步保存数据未成功");
            } else if ("1".equals(item.getIsSuccess())) {
                msg.add("清除”" + label + "“系统的数据未成功");
            } else if ("2".equals(item.getIsSuccess())) {
                msg.add("“" + label + "”系统同步删除数据未成功");
            }
        });
        return msg;
    }

}
