package com.keyware.shandan.system.task;

import com.alibaba.fastjson.JSONObject;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.system.entity.OauthClientDetails;
import com.keyware.shandan.system.entity.SysUser;
import com.keyware.shandan.system.service.OauthClientDetailsService;
import com.keyware.shandan.system.service.SysUserService;
import com.keyware.shandan.system.utils.AsyncRestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Consumer;

/**
 * 用户信息同步处理
 *
 * @author Administrator
 */
@Slf4j
@Component
public class UserSyncHandler {
    private List<OauthClientDetails> clientList = new ArrayList<>();
    @Autowired
    private OauthClientDetailsService clientDetailsService;

    @Autowired
    private AsyncRestTemplate restTemplate;
    @Autowired
    private SysUserService userService;

    /**
     * 用户新增或插入同步
     *
     * @param param 参数
     */
    public void insertOrUpdate(Object param) {
        if (param instanceof SysUser) {
            SysUser user = (SysUser) param;
            user = userService.getById(user.getUserId());
            Date createTime = user.getCreateTime();
            Date modifyTime = user.getModifyTime();
            if (Math.abs(createTime.getTime() - modifyTime.getTime()) < 500) {
                insert(user);
            } else {
                update(user);
            }
        }

    }

    /**
     * 用户新增同步
     *
     * @param param 参数
     */
    public void insert(Object param) {
        if (param instanceof SysUser) {
            queryClientList();
            SysUser user = (SysUser) param;
            Map<String, Object> body = userToMapParam(user);
            clientList.forEach(item -> {
                if (StringUtils.hasText(item.getInsertUri())) {
                    restTemplate.sendAsyncPost(item.getInsertUri(), body, null).addCallback(obj -> {
                        if (isOk(obj)) {
                            log.debug("新增用户数据同步成功，clientId: {}， clientName: {}， uri:{}", item.getId(), item.getTitle(), item.getInsertUri());
                        } else {
                            log.warn("新增用户数据同步失败，msg:{}，clientId: {}， clientName: {}， uri:{}", obj.get("msg"), item.getId(), item.getTitle(), item.getInsertUri());
                        }
                    }, err -> log.warn("新增用户数据同步失败，msg:{}，clientId: {}， clientName: {}， uri:{}", err.getMessage(), item.getId(), item.getTitle(), item.getInsertUri()));
                } else {
                    log.warn("新增用户数据同步失败，msg:没有配置请求地址，clientId: {}， clientName: {}， uri:{}", item.getId(), item.getTitle(), item.getInsertUri());
                }
            });
        }
    }

    /**
     * 用户更新同步
     *
     * @param param 参数
     */
    public void update(Object param) {
        if (param instanceof SysUser) {
            queryClientList();
            SysUser user = (SysUser) param;
            Map<String, Object> body = userToMapParam(user);
            clientList.forEach(item -> {
                if (StringUtils.hasText(item.getUpdateUri())) {
                    restTemplate.sendAsyncPost(item.getUpdateUri(), body, null).addCallback(obj -> {
                        if (isOk(obj)) {
                            log.debug("更新用户数据同步成功，clientId: {}， clientName: {}， uri:{}", item.getId(), item.getTitle(), item.getUpdateUri());
                        } else {
                            log.warn("更新用户数据同步失败，msg:{}，clientId: {}， clientName: {}， uri:{}", obj.get("msg"), item.getId(), item.getTitle(), item.getUpdateUri());
                        }
                    }, err -> log.warn("更新用户数据同步失败，msg:{}，clientId: {}， clientName: {}， uri:{}", err.getMessage(), item.getId(), item.getTitle(), item.getUpdateUri()));
                } else {
                    log.warn("更新用户数据同步失败，msg:没有配置请求地址，clientId: {}， clientName: {}， uri:{}", item.getId(), item.getTitle(), item.getUpdateUri());
                }
            });
        }

    }

    /**
     * 带回调函数的用户信息更新同步方法，
     *
     * @param param
     * @param errorCallback
     */
    public void update(Object param, Consumer<Object> errorCallback) {
        if (param instanceof SysUser) {
            queryClientList();
            SysUser user = (SysUser) param;
            Map<String, Object> body = userToMapParam(user);
            clientList.forEach(item -> {
                if (StringUtils.hasText(item.getUpdateUri())) {
                    restTemplate.sendAsyncPost(item.getUpdateUri(), body, null).addCallback(obj -> {
                        if (isOk(obj)) {
                            log.debug("更新用户数据同步成功，clientId: {}， clientName: {}， uri:{}", item.getId(), item.getTitle(), item.getUpdateUri());
                        } else {
                            log.warn("更新用户数据同步失败，msg:{}，clientId: {}， clientName: {}， uri:{}", obj.get("msg"), item.getId(), item.getTitle(), item.getUpdateUri());
                            if (errorCallback != null) {
                                errorCallback.accept(param);
                            }
                        }
                    }, err -> {
                        log.warn("更新用户数据同步失败，msg:{}，clientId: {}， clientName: {}， uri:{}", err.getMessage(), item.getId(), item.getTitle(), item.getUpdateUri());
                        if (errorCallback != null) {
                            errorCallback.accept(param);
                        }
                    });
                } else {
                    log.warn("更新用户数据同步失败，msg:没有配置请求地址，clientId: {}， clientName: {}， uri:{}", item.getId(), item.getTitle(), item.getUpdateUri());
                }
            });
        }
    }

    /**
     * 用户删除同步
     *
     * @param param 参数
     */
    public void delete(Object param) {
        if (param instanceof String) {
            queryClientList();
            String userId = (String) param;
            Map<String, Object> body = new HashMap<>(1);
            body.put("userId", userId);
            clientList.forEach(item -> {
                if (StringUtils.isNotBlank(item.getDeleteUri())) {
                    restTemplate.sendAsyncPost(item.getDeleteUri(), body, null).addCallback(obj -> {
                        if (isOk(obj)) {
                            log.debug("删除用户数据同步成功，clientId: {}， clientName: {}， uri:{}", item.getId(), item.getTitle(), item.getDeleteUri());
                        } else {
                            log.warn("删除用户数据同步失败，msg:{}，clientId: {}， clientName: {}， uri:{}", obj.get("msg"), item.getId(), item.getTitle(), item.getDeleteUri());
                        }
                    }, err -> log.warn("删除用户数据同步失败，msg:{}，clientId: {}， clientName: {}， uri:{}", err.getMessage(), item.getId(), item.getTitle(), item.getDeleteUri()));
                } else {
                    log.warn("删除用户数据同步失败，msg:没有配置请求地址，clientId: {}， clientName: {}， uri:{}", item.getId(), item.getTitle(), item.getDeleteUri());
                }
            });
        }

    }

    /**
     * 判断结果是否成功
     *
     * @param result 请求结果
     * @return 是否成功
     */
    private Boolean isOk(JSONObject result) {
        Object code = result.get("code");
        boolean ok = false;
        if (code instanceof String) {
            ok = "200".equals(code);
        } else if (code instanceof Number) {
            ok = ((Number) code).intValue() == 200;
        }
        return ok;
    }

    /**
     * 将用户实体对象数据转换为map
     *
     * @param user 用户
     * @return map
     */
    private Map<String, Object> userToMapParam(SysUser user) {
        Map<String, Object> param = new HashMap<>(6);
        if (user.getUserId() != null) {
            param.put("userId", user.getUserId());

        }
        if (user.getLoginName() != null) {
            param.put("loginName", user.getLoginName());
        }
        if (user.getUserName() != null) {
            param.put("userName", user.getUserName());
        }
        if (user.getOrgId() != null) {
            param.put("orgId", user.getOrgId());
        }
        if (user.getOrg() != null) {
            param.put("orgName", user.getOrg().getOrgName());
        }

        return param;
    }

    /**
     * 查询客户端列表
     */
    private void queryClientList() {
        this.clientList = clientDetailsService.listByUserSync();
    }
}
