package com.microservices.system.task;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.UserConstants;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.system.api.domain.SysUser;
import com.microservices.system.domain.ForgeUser;
import com.microservices.system.domain.ForgeUserAction;
import com.microservices.system.domain.vo.ForgeUserActionSearchVo;
import com.microservices.system.mapper.ForgeUserActionMapper;
import com.microservices.system.mapper.ForgeUserMapper;
import com.microservices.system.mapper.SysUserMapper;
import com.microservices.system.service.ISysUserDeptRoleService;
import com.microservices.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author otto
 */
@Component
public class SyncGitLinkUserInfoJob {
    private static final Logger log = LoggerFactory.getLogger(SyncGitLinkUserInfoJob.class);

    @Autowired
    private ForgeUserMapper forgeUserMapper;
    @Autowired
    private ForgeUserActionMapper forgeUserActionMapper;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private ISysUserDeptRoleService sysUserDeptRoleService;

    /**
     * 每日凌晨两点执行一次全量用户从GitLink同步信息（同时同步Forge上已注销用户信息）
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void syncAllGitLinkUserInfo() {
        fullSyncForgeUserInfo();
        fullSyncForgeDeleteUserInfo();
    }

    /**
     * 每隔五分钟对GitLink上五分钟内有更新的用户进行一次同步（同时同步Forge上已注销用户信息）
     */
    @Scheduled(fixedDelay = 5, timeUnit = TimeUnit.MINUTES)
    public void syncIncrementGitLinkUserInfo() {
        incrementSyncForgeUserInfo();
        incrementSyncForgeDeleteUserInfo();
    }

    // 增量同步Forge用户信息
    private void incrementSyncForgeUserInfo() {
        SysUser sysUserSearch = new SysUser();
        List<SysUser> sysUserList = sysUserMapper.selectUserList(sysUserSearch);
        sysUserList = sysUserList.stream().filter(x -> x.getGitlinkUserId() != null).collect(Collectors.toList());
        for (SysUser sysUser : sysUserList) {
            ForgeUser forgeUser = forgeUserMapper.selectGitLinkUserById(sysUser.getGitlinkUserId());
            if (forgeUser != null && forgeUser.getUpdatedOn() != null) {
                long gitlinkUserUpdateTimeMillis = forgeUser.getUpdatedOn().getTime();
                long nowTimeMillis = DateUtils.getNowDate().getTime();
                long minutesDifference = (nowTimeMillis - gitlinkUserUpdateTimeMillis) / (60 * 1000);
                if (minutesDifference > 0 && minutesDifference < 10) {
                    sysUser = sysUserService.gitlinkUserToUpdateSysUser(sysUser, forgeUser);
                    sysUser.setUpdateTime(DateUtils.getNowDate());
                    sysUserMapper.updateUser(sysUser);
                    log.info("进行GitLink用户信息增量同步：同步【{}】用户信息", sysUser.getUserName());
                }
            }
        }
    }

    // 增量同步Forge上已注销账号信息
    private void incrementSyncForgeDeleteUserInfo() {
        ForgeUserActionSearchVo forgeUserActionSearchVo = new ForgeUserActionSearchVo();
        // 查询定时任务执行开始前十分钟到定时任务开始执行期间的所有Forge用户的账号注销记录
        Date now = DateUtils.getNowDate();
        forgeUserActionSearchVo.setStartTime(DateUtils.addHours(now, -10000));
        forgeUserActionSearchVo.setEndTime(now);
        List<ForgeUserAction> forgeUserActionList = forgeUserActionMapper.selectForgeUserActionList(forgeUserActionSearchVo);
        handleForgeDeleteUserInfo(forgeUserActionList);
    }

    // 全量同步Forge用户信息
    private void fullSyncForgeUserInfo() {
        SysUser sysUserSearch = new SysUser();
        List<SysUser> sysUserList = sysUserMapper.selectUserList(sysUserSearch);
        sysUserList = sysUserList.stream().filter(x -> x.getGitlinkUserId() != null).collect(Collectors.toList());
        for (SysUser sysUser : sysUserList) {
            ForgeUser forgeUser = forgeUserMapper.selectGitLinkUserById(sysUser.getGitlinkUserId());
            if (forgeUser != null) {
                sysUser = sysUserService.gitlinkUserToUpdateSysUser(sysUser, forgeUser);
                sysUser.setUpdateTime(DateUtils.getNowDate());
                sysUserMapper.updateUser(sysUser);
                log.info("进行GitLink用户信息全量同步：同步【{}】用户信息", sysUser.getUserName());
            }
        }
    }

    // 全量同步Forge已注销用户信息
    private void fullSyncForgeDeleteUserInfo() {
        // 查询所有注销用户记录
        List<ForgeUserAction> forgeUserActionList = forgeUserActionMapper.selectForgeUserActionList(new ForgeUserActionSearchVo());
        handleForgeDeleteUserInfo(forgeUserActionList);
    }

    private void handleForgeDeleteUserInfo(List<ForgeUserAction> forgeUserActionList) {
        // 遍历Forge用户注销记录列表，检查微服务平台是否存在有Forge注销记录但是在微服务平台未删除的用户
        for (ForgeUserAction forgeUserAction : forgeUserActionList) {
            String userActionDataBank = forgeUserAction.getDataBank();
            if (StringUtils.isNotEmpty(userActionDataBank)) {
                JSONObject jsonObject = JSON.parseObject(userActionDataBank);
                if (jsonObject != null) {
                    Long userId = jsonObject.getLong("id");
                    if (userId != null) {
                        SysUser sysUser = sysUserMapper.selectUserByGitLinkUserId(forgeUserAction.getUserId());
                        if (sysUser != null && UserConstants.DEL_FLAG_FALSE.equals(sysUser.getDelFlag())) {
                            log.info("检测到用户{}在Forge端已注销，将该用户在微服务平台的所有身份标记为已注销同时逻辑删除该用户", sysUser.getUserName());
                            // 更新用户所有身份为已注销
                            sysUserDeptRoleService.deleteSysUserDeptRoleByDeleteUser(sysUser.getUserId());
                            // 逻辑删除该用户
                            sysUserService.deleteUserById(sysUser.getUserId());
                        }
                    }
                }
            }
        }
    }
}
