package com.eactive.eai.rms.common.acl.user.util;

import com.eactive.apim.portal.user.entity.UserInfo;
import com.eactive.eai.rms.common.acl.user.UserManService;
import com.eactive.eai.rms.common.acl.user.mapper.UserBizUIMapper;
import com.eactive.eai.rms.common.acl.user.ui.AdminLoginVo;
import com.eactive.eai.rms.common.acl.user.ui.UserBizUI;
import com.eactive.eai.rms.common.acl.user.ui.UserUI;
import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.common.combo.IbatisComboService;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.data.entity.man.user.UserInfoService;
import com.eactive.eai.rms.data.entity.onl.bzwkdstcd.UserBusiness;
import com.eactive.eai.rms.data.entity.onl.bzwkdstcd.UserBusinessService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Transactional(transactionManager = "transactionManagerForEMS")
@RequiredArgsConstructor
public class UserRegistUtilService extends BaseService {

   private final UserInfoService userInfoService;
   private final UserManService userManService;
   private final UserBusinessService userBusinessService;
   private final IbatisComboService ibatisComboService;
   private final UserBizUIMapper userBizUIMapper;

   public List<UserRegistResponseVo> registUser(HashMap<String, String>[] userList, AdminLoginVo adminLoginVo)
			throws Exception {

		List<UserRegistResponseVo> responseList = new ArrayList<>();
      List<DataSourceType> datasourceList = DataSourceTypeManager.getDynamicDataSourceTypes();

      for (HashMap<String, String> userFromView : userList) {
         final UserUI userUIFromView = mapToUserUI(userFromView);
         final String userId = userUIFromView.getUserId();
			UserRegistResponseVo userRegistResponseVo = new UserRegistResponseVo();
			try {

            Optional<UserInfo> userFromDB = userInfoService.findById(userId);

            // INSERT USER (RM02)
            if (!userFromDB.isPresent()) { // 신규 등록 User
               userManService.insert(userUIFromView, adminLoginVo);
				} else {
               if (!userFromDB.get().getUsername().equals(userFromView.get("userName"))) {
                  throw new Exception("타 사용자 기등록 오류");
               }
				}

            // INSERT BIZCODE TO USER (RM06)
				for (DataSourceType datasource : datasourceList) {
               if (datasource.getName().contains("GW")) { // FIXME: how to handle GW?
                  continue;
               }
					DataSourceContextHolder.setDataSourceType(datasource);

               if ("ALL".equals(userFromView.get("bzwkCdList"))) {
                  // FIXME: ibatis -> jpaComboService
                  List<Map<String, Object>> allBizList = ibatisComboService.selectListComboForTable("TSEAICM01", "EAIBZWKDSTCD", "BZWKDSTICNAME", "", "EAIBZWKDSTCD");
                  List<UserBizUI> allBizUI = mapAllBizListToUserBizUI(userId, allBizList);
                  List<UserBusiness> bizEntityList = allBizUI.stream().map(userBizUIMapper::toEntity).filter(entity -> !userBusinessService.existsById(entity.getId())).collect(Collectors.toList());
                  userBusinessService.saveAll(bizEntityList);
					} else {

                  String[] split = userFromView.get("bzwkCdList").split(",");
                  List<UserBizUI> listUserRoleUI =
                        Arrays.stream(split)
                              .filter(StringUtils::isNotBlank)
                              .map(bizCode -> mapToUserBizUI(userId, bizCode)).collect(Collectors.toList());

                  if (listUserRoleUI.isEmpty()) {
							continue;
						}

                  List<UserBusiness> bizEntityList = listUserRoleUI.stream().map(userBizUIMapper::toEntity).filter(entity -> !userBusinessService.existsById(entity.getId())).collect(Collectors.toList());
                  userBusinessService.saveAll(bizEntityList);
					}
				}

            userRegistResponseVo.setMessage(successMessage(userFromView));
				responseList.add(userRegistResponseVo);

			} catch (Exception e) {
            userRegistResponseVo.setMessage(failMessage(userFromView, e));
				responseList.add(userRegistResponseVo);
				logger.debug("Not Registered User : " + userRegistResponseVo);
			}
		}

		return responseList;
	}

   private UserUI mapToUserUI(Map<String, String> userFromView) {
      UserUI userUI = new UserUI();
      userUI.setUserId(userFromView.get("userId"));
      userUI.setTeamName(userFromView.get("teamName"));
      userUI.setUserName(userFromView.get("userName"));
      userUI.setDvsnname(userFromView.get("teamName"));
      userUI.setJobtlname(" ");
      return userUI;
   }

   private UserBizUI mapToUserBizUI(String userId, String bizCode) {
      UserBizUI userBizUI = new UserBizUI();
      userBizUI.setUserId(userId);
      userBizUI.setBizCode(bizCode);
      userBizUI.setChk("true");
      return userBizUI;
   }

   private List<UserBizUI> mapAllBizListToUserBizUI(String userId, List<Map<String, Object>> allBizList) {
      List<UserBizUI> listUserRoleUI = new ArrayList<>();
      for (Map<String, Object> biz : allBizList) {
         UserBizUI userBizUI = new UserBizUI();
         userBizUI.setUserId(userId);
         userBizUI.setBizCode(biz.get("CODE").toString());
         userBizUI.setBizName(biz.get("NAME").toString());
         userBizUI.setSaveType("R");
         userBizUI.setChk("true");
         listUserRoleUI.add(userBizUI);
      }
      return listUserRoleUI;
   }

   private String failMessage(HashMap<String, String> user, Exception exception) {

      String userId = user.get("userId");
      String userName = user.get("userName");
      String teamName = user.get("teamName");
      String bzwkCdList = user.get("bzwkCdList");
      String message = exception.getMessage();

		return new StringBuilder().append(userId).append(" ").append(teamName).append(" ").append(userName)
				.append(" - 사용자 등록 실패 : ").append(message).toString();
	}

   private String successMessage(HashMap<String, String> user) {

      String userId = user.get("userId");
      String userName = user.get("userName");
      String teamName = user.get("teamName");
      String bzwkCdList = user.get("bzwkCdList");

		return new StringBuilder().append(userId).append(" ").append(teamName).append(" ").append(userName)
				.append(" - 신규 사용자 등록 및 어플리케이션 코드 ").append(bzwkCdList).append(" 적용").toString();
	}

}
