package com.dbs.mplus.service.mobile.user;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.dbs.mplus.exception.mobile.ApiCallException;
import com.dbs.mplus.framework.exception.MPlusServiceException;
import com.dbs.mplus.framework.template.GenericService;
import com.dbs.mplus.service.api.MPlusApi;
import com.dbs.mplus.service.api.MPlusApiCallService;
import com.dbs.mplus.service.mobile.user.repository.MPlusUserAgreementRepository;
import com.dbs.mplus.service.mobile.user.repository.MPlusUserRepository;
import com.dbs.mplus.service.mobile.user.repository.dao.MPlusUser;
import com.dbs.mplus.service.mobile.user.repository.dao.MPlusUserAgreement;

/**
 * 사용자 관리  
 * @author hyeeun 
 *
 */
@Service 
public class MPUserService extends GenericService<MPlusUser, MPlusUserRepository> {
	private static Logger logger = LoggerFactory.getLogger(MPUserService.class); 
	@Autowired 
	private MPlusUserAgreementRepository userAgreementRepository; 
	@Autowired 
	private MPlusApiCallService apiCallService; 
	
	/**
	 * 사용자 추가 
	 * @param userId
	 * @param userName
	 * @param sha256PassWord
	 * @param aggList 동의서 목록 
	 * @throws MPlusServiceException
	 */
	@Transactional(value = "mplusTransactionManager", rollbackFor = { Exception.class })
	public String insertUser(String userId, String userName, String sha256PassWord) throws MPlusServiceException {
		final UUID uuid = UUID.randomUUID(); 
		String key = uuid.toString(); 
		
		try { 
			// key 길이 자르기 
			// sqlChiper는 32bytes key data를 가짐 
			if(key.length() > 32) { 
				key = key.substring(0, 31); 
			}
			
			if(logger.isInfoEnabled()) {
				logger.info("사용자등록 : " + userId + ", " + userName);
			}
			
			// 사용자 등록 
			this.repository.insertUser(userId, userName, sha256PassWord, key); 
		}
		catch(final Exception ex) { 
			logger.error("사용자 추가 실패", ex);
			throw new MPlusServiceException("사용자 추가 실패", ex);
		}
		
		return key; 
	}
	
	/**
	 * 사용자 추가 후 동의서 추가 등록
	 * @param userId
	 * @param agreementList
	 * @throws MPlusServiceException
	 */
	public void insertUserAgreement(String userId, List<MPlusUserAgreement> agreementList) throws MPlusServiceException {
		// 동의서 등록 
		try {
			if(agreementList != null) { 
				for(final MPlusUserAgreement m : agreementList) { 
					m.setUserid(userId);
					this.userAgreementRepository.insert(m); 
				}
			}
		}
		catch(final Exception ex) {
			logger.error("사용자 동의서 등록 실패", ex);
			throw new MPlusServiceException("사용자 동의서 등록 실패", ex);
		}
	}
	
	/**
	 * 사용자 패스워드 변경
	 * @param chartNoValue
	 * @param chartName
	 * @param sha256PassWord
	 * @throws ApiCallException
	 */
	public void updateUserPWD(String chartNoValue, String chartName, String newPassword) throws ApiCallException {
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("userId", chartNoValue);
		paramMap.put("pName", chartName);
		paramMap.put("passwordValue", newPassword);
		

		this.apiCallService.execute(MPlusApi.USER_PASSWORD_RESETPWD, paramMap); 
	}
	
	/**
	 * 사용자 패스워드가 맞는지 확인 한다. --> api호출은 controller단에 올라가 있는데 얘만 service 단에 내려와서 이상한것 같지만 서비스가 맞긴함... 생각해봐야겠다. 
	 * @param chartNoValue
	 * @param chartName
	 * @param hashPwd
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public boolean checkUserPWD(String chartNoValue, String hashPwd) {
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("userId", chartNoValue);
		paramMap.put("passwordValue", hashPwd);

		Map<String, Object> checkMap = null;

		try { 
			checkMap = (Map<String, Object>) this.apiCallService.execute(MPlusApi.USER_PASSWORD_CHECKPWD, paramMap); 
			//logger.debug("비번확인 : " + checkMap);
		}
		catch(ApiCallException ex) { 
			if(logger.isDebugEnabled()) {
				logger.debug("예외발생", ex); 
			}
			
			return false; 
		}
		
		if(checkMap == null || checkMap.isEmpty()) {
			//logger.debug("결과없음. paramMap=" + paramMap);
			return false; 
		}
		

		if("true".equals((String) checkMap.get("validpassword"))) {
			return true; 
		}

		
		return false;
	}
	/**
	 * 
	 * @param user
	 * @throws MPlusServiceException
	 * 사용자 block 해제
	 */
	public void clear(MPlusUser user) throws MPlusServiceException{
		try {
			this.repository.update(user);
		} catch (final Exception ex) {
			logger.error("사용자 block 해제 실패", ex);
			throw new MPlusServiceException("사용자 block 해제 실패", ex);
		}
	}
//	/**
//	 * 사용자 목록 조회
//	 * @return
//	 * @throws MPServiceException
//	 */
//	public List<MPUser> getUserList() throws MPServiceException {
//		return this.userRepository.findAll();
//	}
	
	/**
	 * 사용자 목록 조회 
	 * @param params
	 * @return
	 * @throws MPlusServiceException
	 */
	public Map<String, Object> selectUserList(Map<String, Object> params) throws MPlusServiceException {
		// 결과를 받아서 전달 
		// 관리자 사용자 관리에서 사용자 검색기능을 사용하면 다른 쿼리를 호출하도록 추가함
		
		String userId = (String) params.get("searchUserId"); 
		
		if(!StringUtils.isEmpty(userId)){
			// 특정사용자에 대한 것이므로 사실 paging이 필요없으나 리턴값을 맞추기 위함 
			return this.repository.queryForPaging("selectOneUser", "selectOneUserCount", params, false); 
		} 
		else {
			return this.repository.queryForPaging("selectUserList", "selectUserListCount", params, false); 
		}
	}
	
	/**
	 * 사용자 삭제 
	 * @param userId
	 * @throws MPlusServiceException
	 */
	@Transactional(value = "mplusTransactionManager", rollbackFor = { Exception.class })
	public void removeUser(String userId) throws MPlusServiceException {
		try {
			// 파라미터 정리 
			Map<String, Object> paramMap = new HashMap<>(); 
			paramMap.put("userId", userId); 
			
			// 토큰삭제 
			this.repository.deleteUserDeviceToken(paramMap);
			// 동의서 삭제 
			this.userAgreementRepository.delete(paramMap); 
			// 사용자 삭제 
			this.repository.delete(paramMap); 
		}
		catch(final Exception ex) { 
			final MPlusServiceException f = new MPlusServiceException("사용자 삭제 실패. userId=" + userId, ex); 
			logger.error("", f);
			throw f; 
		}
	}

}
