package com.dbnt.kcscbackend.auth.service.impl;

import com.dbnt.kcscbackend.auth.entity.UserInfo;
import com.dbnt.kcscbackend.auth.mapper.LoginUserMapper;
import com.dbnt.kcscbackend.auth.repository.UserInfoRepository;
import com.dbnt.kcscbackend.auth.service.EgovLoginService;
import com.dbnt.kcscbackend.auth.entity.LoginVO;
import com.dbnt.kcscbackend.config.egov.EgovFileScrty;
import com.dbnt.kcscbackend.config.util.EgovNumberUtil;
import com.dbnt.kcscbackend.config.util.EgovStringUtil;
import lombok.RequiredArgsConstructor;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Random;

/**
 * 일반 로그인을 처리하는 비즈니스 구현 클래스
 * @author 공통서비스 개발팀 박지욱
 * @since 2009.03.06
 * @version 1.0
 * @see
 *
 * <pre>
 * << 개정이력(Modification Information) >>
 *
 *   수정일      수정자          수정내용
 *  -------    --------    ---------------------------
 *  2009.03.06  박지욱          최초 생성
 *  2011.08.31  JJY            경량환경 템플릿 커스터마이징버전 생성
 *
 *  </pre>
 */


@Service("loginService")
@RequiredArgsConstructor
public class EgovLoginServiceImpl extends EgovAbstractServiceImpl implements EgovLoginService, UserDetailsService {

	private final LoginUserMapper loginMapper;
	private final UserInfoRepository userInfoRepository;


	@Transactional
	public Integer insertUser(LoginVO loginVO){
		UserInfo idCheck = userInfoRepository.findByUserId(loginVO.getId()).orElse(null);
		if (idCheck != null){
			return -1;
		}
		UserInfo emailCheck = userInfoRepository.findByEmail(loginVO.getEmail()).orElse(null);
		if(emailCheck != null){
			return -2;
		}
		UserInfo info = new UserInfo();
		info.setUserId(loginVO.getId());
		info.setPassword(convertPassword(loginVO.getPassword()));
		info.setEmail(loginVO.getEmail());
		info.setUserSe("USR");
		userInfoRepository.save(info);
		return info.getUserSeq();
	}

	public String selectEmail(LoginVO loginVO){
		UserInfo savedUser = userInfoRepository.findByEmail(loginVO.getEmail()).orElse(null);
		return savedUser==null?null:savedUser.getUserId();
	}

	@Transactional
	public String updateTempPassword(LoginVO loginVO){
		UserInfo user = userInfoRepository.findByEmailAndUserId(loginVO.getEmail(), loginVO.getId()).orElse(null);
		if(user!=null){
			Random rd = new Random();
			StringBuilder password = new StringBuilder();
			for(int i=0; i<10; i++){
				int rdNum = rd.nextInt(95)+33;
				password.append((char)rdNum);
			}
			user.setPassword(convertPassword(password.toString()));
			return password.toString();
		}
		return null;
	}

	@Override
	public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException {
		return userInfoRepository.findByUserId(userId).orElseThrow(() -> new UsernameNotFoundException(userId));
	}

	/**
	 * 일반 로그인을 처리한다
	 * @param vo LoginVO
	 * @return LoginVO
	 * @exception Exception
	 */
	@Override
	public LoginVO actionLogin(LoginVO vo) throws Exception {

		// 1. 입력한 비밀번호를 암호화한다.
		String enpassword = EgovFileScrty.encryptPassword(vo.getPassword(), vo.getId());
		vo.setPassword(enpassword);

		// 2. 아이디와 암호화된 비밀번호가 DB와 일치하는지 확인한다.
		LoginVO loginVO = loginMapper.actionLogin(vo);

		// 3. 결과를 리턴한다.
		if (loginVO != null && !loginVO.getId().equals("") && !loginVO.getPassword().equals("")) {
			return loginVO;
		} else {
			loginVO = new LoginVO();
		}

		return loginVO;
	}

	/**
	 * 아이디를 찾는다.
	 * @param vo LoginVO
	 * @return LoginVO
	 * @exception Exception
	 */
	@Override
	public LoginVO searchId(LoginVO vo) throws Exception {

		// 1. 이름, 이메일주소가 DB와 일치하는 사용자 ID를 조회한다.
		LoginVO loginVO = loginMapper.searchId(vo);

		// 2. 결과를 리턴한다.
		if (loginVO != null && !loginVO.getId().equals("")) {
			return loginVO;
		} else {
			loginVO = new LoginVO();
		}

		return loginVO;
	}

	/**
	 * 비밀번호를 찾는다.
	 * @param vo LoginVO
	 * @return boolean
	 * @exception Exception
	 */
	@Override
	public boolean searchPassword(LoginVO vo) throws Exception {

		boolean result = true;

		// 1. 아이디, 이름, 이메일주소, 비밀번호 힌트, 비밀번호 정답이 DB와 일치하는 사용자 Password를 조회한다.
		LoginVO loginVO = loginMapper.searchPassword(vo);
		if (loginVO == null || loginVO.getPassword() == null || loginVO.getPassword().equals("")) {
			return false;
		}

		// 2. 임시 비밀번호를 생성한다.(영+영+숫+영+영+숫=6자리)
		String newpassword = "";
		for (int i = 1; i <= 6; i++) {
			// 영자
			if (i % 3 != 0) {
				newpassword += EgovStringUtil.getRandomStr('a', 'z');
				// 숫자
			} else {
				newpassword += EgovNumberUtil.getRandomNum(0, 9);
			}
		}

		// 3. 임시 비밀번호를 암호화하여 DB에 저장한다.
		LoginVO pwVO = new LoginVO();
		String enpassword = EgovFileScrty.encryptPassword(newpassword, vo.getId());
		pwVO.setId(vo.getId());
		pwVO.setPassword(enpassword);
		pwVO.setUserSe(vo.getUserSe());
		loginMapper.updatePassword(pwVO);

		return result;
	}


	private String convertPassword(String password){
		Pbkdf2PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder();
		return passwordEncoder.encode(password);
	}
}