package com.bb.config;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import com.bb.admin.controller.MainController;
import com.bb.exception.ApiException;
import com.bb.model.OTPInfo;
import com.bb.model.Site;
import com.bb.service.SiteService;
import com.bb.util.TOTPTokenGenerator;

import lombok.extern.slf4j.Slf4j;

/**
 * Description: 스프링시큐리티 로그인 인증
 * Path       : 스프링시큐리티       
 *  @FileName : AsRepairController.java
 *  @Version  : 2019. 8. 27.
 *  @Author   : LeeChunghan
 *  @Comment  :
 */
@Slf4j
@Component("authProvider")
public class AuthProvider implements AuthenticationProvider  {
	
	@Autowired
	SiteService siteService;

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		String id = authentication.getName();
		String password = authentication.getCredentials().toString();
		String verificationCode = ((CustomWebAuthenticationDetails) authentication.getDetails()).getVerificationCode();
		
		final String LOG_PREFIX = "#-AP::"+id+":::";
		log.info(LOG_PREFIX+ "Authentication::"+authentication.toString());
		log.info(LOG_PREFIX+ "verificationCode::"+verificationCode);
		
		Site agency = null;
		boolean isAdmin = false;
		if(!"".equals(id)) {
			log.info(LOG_PREFIX+ "Super Login!!!");
			isAdmin = true;
			agency = siteService.getSiteLogin(authentication);
		} else {
			log.info(LOG_PREFIX+ "Guest Login!!!");
			isAdmin = false;
			agency = siteService.getGuestLogin();
			id = "oms";
		}
		
		OTPInfo otpInfo = siteService.getOtpInfo(agency.getSiteIdx());
		if(otpInfo == null || otpInfo.getAccount().equals("")) {
			log.error(LOG_PREFIX+ "OTP 정보를 찾을 수 없습니다.");
			return null;
		}
		
		if(otpInfo.getSecretKey() == null || otpInfo.getSecretKey().equals("")) {
			// Create New OTP
	        otpInfo = TOTPTokenGenerator.getGoogleAuthQRUrl(otpInfo);
	        
			log.info(LOG_PREFIX+ "makeOtp:: secret : " + otpInfo.getSecretKey());
	        log.info(LOG_PREFIX+ "makeOtp::account : " + otpInfo.getAccount());
	        log.info(LOG_PREFIX+ "makeOtp:: issuer : " + otpInfo.getIssuer());
	        log.info(LOG_PREFIX+ "makeOtp::    URL : " + otpInfo.getUrl());
	        
	        int result = siteService.registSuperOtp(otpInfo);
	        log.info(LOG_PREFIX+ "makeOtp:: result : " + result);
		} else {
			log.info(LOG_PREFIX+ "OTP Info : " + otpInfo);
			String secret = otpInfo.getSecretKey();
			
			if(verificationCode == null || verificationCode.equals("")) {
				log.error(LOG_PREFIX+ "OTP 번호를 입력하세요.");
				return null;
			}
			
			boolean chkOtp = TOTPTokenGenerator.otpVerify(secret, Integer.parseInt(verificationCode));
			if(!chkOtp) {
				log.error(LOG_PREFIX+ "OTP 번호가 일치하지 않습니다.");
				return null;
			}
		}
		
		if(isAdmin) {
			OTPInfo otpManager = siteService.getOtpInfoByManger(agency.getSiteIdx());
			if(otpManager.getSecretKey() == null || otpManager.getSecretKey().equals("")) {
				// Create New Manager OTP
				otpManager = TOTPTokenGenerator.getGoogleAuthQRUrl(otpManager);
		        
				log.info(LOG_PREFIX+ "Manager makeOtp:: secret : " + otpManager.getSecretKey());
		        log.info(LOG_PREFIX+ "ManagermakeOtp::account : " + otpManager.getAccount());
		        log.info(LOG_PREFIX+ "ManagermakeOtp:: issuer : " + otpManager.getIssuer());
		        log.info(LOG_PREFIX+ "ManagermakeOtp::    URL : " + otpManager.getUrl());
		        
		        log.info(LOG_PREFIX+ "Manager otpManager:: " + otpManager.toString());
		        int result = siteService.registSuperOtp(otpManager);
		        log.info(LOG_PREFIX+ "ManagermakeOtp:: result : " + result);
			}
		}
		
		if(agency == null) {
			return null;
		} else {
			Site loginVO = new Site();
			loginVO = agency;
	
			List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
			if(isAdmin) {
				roles.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
			} else {
				roles.add(new SimpleGrantedAuthority("ROLE_GUEST"));
			}
		
			UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(id, password, roles);	
			result.setDetails(loginVO);
			// log.info(LOG_PREFIX+ "UsernamePasswordAuthenticationToken result::"+result.getDetails().toString());
				
			return result;
		}
	
	}
		

	
	@Override
	public boolean supports(Class<?> authentication) {
		return authentication.equals(UsernamePasswordAuthenticationToken.class);
	}

}
