package com.samsung.batch.impl;

import com.samsung.batch.UserSyncBatchService;
import com.samsung.batch.dao.UserSyncDao;
import com.samsung.batch.entity.UserSync;
import com.samsung.core.annotation.BatchJob;
import com.samsung.user.dao.UserDao;
import com.samsung.user.entity.User;
import com.samsung.user.enums.ExpireStatus;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Log4j2
@Service
public class UserSyncBatchServiceImpl implements UserSyncBatchService {
    @Value("${batch.user.sync.retire.enabled:false}")
    private boolean retireEnabled;

    private final UserSyncDao userSyncDao;
    private final UserDao userDao;

    public UserSyncBatchServiceImpl(UserSyncDao userSyncDao, UserDao userDao) {
        this.userSyncDao = userSyncDao;
        this.userDao = userDao;
    }

    @Override
    @Transactional
    @BatchJob("com.samsung.batch.impl.UserBatchServiceImpl.execUserSync")
    public void execUserSync() {
        log.info("User Sync Check Batch Job starting...");
        syncUser();
        log.info("User Sync Check Batch Job finished!!!");
    }

    /**
     * 사용자테이블(TN_CF_USER)과 사용자동기화테이블(TN_CF_USER_SYNC) 동기화 <BR/>
     * - 프로젝트 환경에 따라 적절히 수정하여 적용바랍니다.
     */
    private void syncUser() {
        // 현재 사용자 테이블의 미사용자, 대기자
        Map<String, Object> condition = new HashMap<>();
        condition.put("deleted", false);
        condition.put("activeFlag", false);
        List<User> currentUserList = userDao.getUserList(condition);
        Map<String, User> userMap = getUserListToMap(currentUserList);

        // 사전에 사용자동기화테이블(TN_CF_USER_SYNC)에 데이터 동기화 필요 (프로젝트별 구현)
        List<UserSync> userSyncList = userSyncDao.getUserSyncList();
        for (UserSync userSync : userSyncList) {
            User user = userMap.get(userSync.getUserId());
            if (user != null) {
                BeanUtils.copyProperties(userSync, user, "deleted", "jwt");
                userDao.update(user);
            } else {
                User newUser = new User();
                BeanUtils.copyProperties(userSync, newUser, "deleted", "jwt");
                newUser.setActiveFlag(true);
                newUser.setExternalUser(false);
                userDao.insert(newUser);
            }
        }
        if (retireEnabled) {
            userRetireCheck(currentUserList, userSyncList);
        }
    }

    private void userRetireCheck(List<User> currentUserList, List<UserSync> userSyncList) {
        Map<String, UserSync> userSyncMap = getUserSyncListToMap(userSyncList);
        for (User user : currentUserList) {
            UserSync userSync = userSyncMap.get(user.getUserId());
            // userSync에 없는 사용자면 퇴직 처리함.
            if (userSync == null) {
                user.setActiveFlag(false);
                user.setExpireStatus(ExpireStatus.RETIRE.toString());
                userDao.update(user);
            }
        }
    }

    private Map<String, UserSync> getUserSyncListToMap(List<UserSync> userSyncList) {
        Map<String, UserSync> userSyncMap = new HashMap<>();
        for (UserSync userSync : userSyncList) {
            if (userSyncMap.get(userSync.getUserId()) == null) {
                userSyncMap.put(userSync.getUserId(), userSync);
            }
        }
        return userSyncMap;
    }

    private Map<String, User> getUserListToMap(List<User> userList) {
        Map<String, User> userMap = new HashMap<>();
        for (User user : userList) {
            if (userMap.get(user.getUserId()) == null) {
                userMap.put(user.getUserId(), user);
            }
        }
        return userMap;
    }
}
