
package nlib.user.web;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.annotation.Resource;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.util.UriComponentsBuilder;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.github.scribejava.core.model.OAuth2AccessToken;

import egovframework.com.ext.oauth.service.OAuthConfig;
import egovframework.com.ext.oauth.service.OAuthLogin;
import egovframework.com.ext.oauth.service.OAuthUniversalUser;
import egovframework.com.ext.oauth.service.OAuthVO;
import egovframework.rte.fdl.cryptography.EgovPasswordEncoder;
import nlib.cmm.crypto.AriaCrypto;
import nlib.cmm.service.NlibProperty;
import nlib.cmm.session.SessionConfig;
import nlib.cmm.snslogin.GoogleOAuthResponse;
import nlib.cmm.snslogin.KakaoController;
import nlib.info.service.InformService;
import nlib.mail.EmailSender;
import nlib.mail.service.EmailVO;
import nlib.restful.service.DataApiReqVO;
import nlib.user.service.MemberService;
import nlib.user.service.NlibLoginVO;
import nlib.user.service.MemberSiteVO;
import nlib.user.service.UserInfoService;
import nlib.util.StringUtil;

import org.springframework.mail.javamail.JavaMailSender;

/**
 * <pre>
 * @Class Name : MemberController.java
 * 
 * @Description : 
 * 
 * 
 * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
 *
 * </pre>
 *
 * @ ------------    --------    ---------------------------
 * @ 수정일                     수정자             수정내용
 * @ ------------    --------    ---------------------------
 * @ 2021. 7. 12.    JSYOO       최초 생성
 *
 * 
 * @author 이씨플라자 * DIGITALSHIP JSYOO
 * @since 2021. 7. 12.
 * @version 1.0
 *
 */

@Controller
public class MemberController {
	
	//-------------------------------------------
		// SNS 연동 환경설정 정보 : context-oauth.xml 참고 
		//-------------------------------------------
		@Inject
		private OAuthVO naverAuthVO; /* 네이버 */
		
		@Inject
		private OAuthVO googleAuthVO; /* 구글 */

		@Inject
		private OAuthVO kakaoAuthVO; /* 카카오 */
		//-------------------------------------------
		
	@Resource(name="userInfoService")
	private UserInfoService userInfoService;
	
	@Resource(name="memberService")
	private MemberService memberService;
	
	@Resource(name="informService")
	private InformService informService;

	@Resource(name = "egovEnvPasswordEncoderService")
    EgovPasswordEncoder egovPasswordEncoder;
	
	@Autowired
    private EmailSender emailSender;
	
	/* 이메일 메시지 및 템플릿 정보 */
	//템플릿 파일경로
	@Value("#{properties['mailing.sender.membership.template']}")
	private String template;
	
	@Value("#{properties['mailing.sender.membership.pwdTemplate']}")
	private String pwdTemplate;
	
	//보내는 사람 이메일주소
	@Value("#{properties['mailing.sender.membership.email']}")
	private String senderAddr;
	
	//보내는 사람 이름
	@Value("#{properties['mailing.sender.membership.name']}")
	private String senderName;
	
	//게스트 USERID
	@Value("#{properties['guest.userid']}")
	private String gUserId;
	
	
	public ModelMap certificateMember(HttpServletRequest req)  {
		return null;
	}
	public ModelMap sendEmailForMemberJoining(HttpServletRequest req)  {
		return null;
	}
	public ModelMap changePassword(HttpServletRequest req)  {
		return null;
	}

	public ModelMap selectMemberInfo(HttpServletRequest req)  {
		return null;
	}

	public ModelMap updateMemberInfoForm(HttpServletRequest req)  {
		return null;
	}

	public ModelMap updateMemberInfo(HttpServletRequest req)  {
		return null;
	}

	public ModelMap leaveMember(HttpServletRequest req)  {
		return null;
	}
	
	/**
	 * 약관 동의화면
	 * @param req
	 * @param model
	 * @return
	 * @throws Exception 
	 */
	@RequestMapping(value="/member/selectMemberJoiningInfo.do")
	public String selectMemberJoiningInfo(HttpServletRequest req,ModelMap model,HttpSession session) throws Exception  {
		String jsessionId = session.getId();
		OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId);
		
		int count=0;
		
		//기 가입계정인지 확인
		count=memberService.selectSnsIdCount(oauthUser);
		if(count>0)
		{
			model.addAttribute("msg","이미 가입된 계정입니다. 로그인해주세요.");
			model.addAttribute("url","/nlib"+NlibProperty.getString("login.url"));
			return "nlib/cmm/alert";
		}
		return "/nlib/member/selectMemberJoiningInfo";
	}
	
	@RequestMapping(value="/member/snsCertForm.do")
    public String snsCertForm(HttpSession session,
    		HttpServletRequest req, 
			@RequestParam(required = false) String error,
			@RequestParam(required = false) String message,
			Model model) throws Exception{
		//----------------------------------------------
		// SNS 연동 URL 생성 
		//----------------------------------------------
		OAuthLogin naverLogin = new OAuthLogin(naverAuthVO, OAuthLogin.CALL_TYPE_MEMBER);
		model.addAttribute("naverUrl", naverLogin.getOAuthURL());
		
		OAuthLogin googleLogin = new OAuthLogin(googleAuthVO, OAuthLogin.CALL_TYPE_MEMBER);
		model.addAttribute("googleUrl", googleLogin.getOAuthURL());

		OAuthLogin kakaoLogin = new OAuthLogin(kakaoAuthVO, OAuthLogin.CALL_TYPE_MEMBER);
		model.addAttribute("kakaoUrl", kakaoLogin.getOAuthURL());
		
		model.addAttribute("error", error);
		model.addAttribute("message", message);
        return "nlib/member/snsCertForm";
    }
	
	/**
	 * 회원가입 폼
	 * @exception Exception
	 */
	@RequestMapping(value="/member/insertMemberInfoForm.do")
	public String insertMemberInfoForm(HttpServletRequest request,NlibLoginVO vo,HttpSession session,ModelMap model ) throws Exception{
		MemberSiteVO msVO= new MemberSiteVO();
		int siteCnt;
		String jsessionId = session.getId();
		String councilCd = (String)session.getAttribute("councilCd");
		//String councilReturnUrl = (String)session.getAttribute("councilReturnUrl");
		
		OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId);
		
		String mId = null;
		
		// 등록된 ID가 있는 지 확인
		if(!(StringUtil.getString(oauthUser.getSnsUserId(),"")== ""))
			mId =memberService.selectAlreadySignUpId(oauthUser);
		
		/* 등록된 ID가 있을때 통합처리 */
		if(!StringUtil.getString(mId, "").equals(""))
		{
			oauthUser.setMbInfoId(mId);
			memberService.insertMemberSns(oauthUser);
			
			//가입문화원정보 설정
			msVO.setMbInfoId(mId);
			msVO.setJoinType(oauthUser.getSnsType());
			msVO.setJoinCouncilCd(councilCd);
			msVO.setMasterYn("N");
			siteCnt= memberService.selectMemberSiteCount(msVO);
			//문화원에 가입하지않았을 시 insert
			if(!(siteCnt>0))
			{
				memberService.insertMemberSite(msVO);
			}
			//통합처리 url
			return "nlib/member/accountConsolidationForm";
		}
		model.addAttribute("loginVO",oauthUser);
		return "nlib/member/insertMemberInfoForm";
	}
	
	/**
	 * 회원가입
	 * @exception Exception
	 */
	@RequestMapping(value="/member/insertMemberInfo.do")
	public String insertMemberInfo(NlibLoginVO vo,ModelMap model,HttpSession session) throws Exception{
		MemberSiteVO msVO= new MemberSiteVO();
		List<NlibLoginVO> voList = new ArrayList<NlibLoginVO>();
		EmailVO email = new EmailVO();
		
		//문화원코드
		String councilCd = (String)session.getAttribute("councilCd");
				
		// 등록된 전화번호가 있는 지 확인 (리스트)
		voList = memberService.selectAlreadySignUpMobile(vo);
		
		/* 등록된 ID가 있을때 통합처리 */
		if(voList.size() > 0)
		{
			//통합처리 url
			model.addAttribute("result",voList);
			return "nlib/member/accountConsolidationForm";
		}
		
		String jsessionId = session.getId();
		OAuthUniversalUser oauthUser = SessionConfig.popNewMemberInfo(jsessionId);
		
		if(oauthUser.getNlibVO()!=null)
		{
			//핸드폰인증시 sns제공 번호와 회원가입폼 번호 비교
			if(!(vo.getMobileNo().equals(oauthUser.getSnsMobileNo())))
			{
				if(!(vo.getMobileVrfctNo().equals(oauthUser.getNlibVO().getMobileVrfctNo()))
						||oauthUser.getNlibVO().getMobileVrfctDd() == null)  
				{
					model.addAttribute("msg","핸드폰인증에 문제가 있습니다. 다시 회원가입을 진행해주세요.");
					model.addAttribute("url","${pageContext.request.contextPath}"+NlibProperty.getString("member.new.url"));
					return "nlib/cmm/alert";
				}
				/*vo.setMobileVrfctNo(vo.getMobileVrfctNo());
				vo.setMobileVrfctDd(vo.getMobileVrfctNo());*/
			}
			//이메일인증시 sns제공 이메일과 회원가입폼 이메일 비교
			if(!(vo.getEmail().equals(oauthUser.getSnsUserId())))
			{
				if(!(vo.getEmailVrfctDd().equals(oauthUser.getNlibVO().getEmailVrfctDd()))
						||oauthUser.getNlibVO().getEmailVrfctDd() == null)  
				{
					model.addAttribute("msg","이메일인증에 문제가 있습니다. 다시 회원가입을 진행해주세요.");
					model.addAttribute("url","${pageContext.request.contextPath}"+NlibProperty.getString("member.new.url"));
					return "nlib/cmm/alert";
				}
			}
		}
		//회원정보 insert 
		
		NlibLoginVO result =memberService.insertMemberInfo(vo);
		
		//sns 테이블 insert
		oauthUser.setMbInfoId(result.getMbInfoId());
		
		memberService.insertMemberSns(oauthUser);
		
		
		//가입문화원정보 테이블 insert
		msVO.setMbInfoId(result.getMbInfoId());
		msVO.setJoinType(oauthUser.getSnsType());
		msVO.setJoinCouncilCd(councilCd);
		msVO.setMasterYn("Y");
		
		memberService.insertMemberSite(msVO);
		
		
    	
    	// 결과가 정상이면, 안내 메일 발송 
    	// > 템플릿파일에서 내용 mailing.sender.membership.template
    	// > 치환 (사용자명, 이메일주소)
    	// > 발송처리 요청 
		String reciver = vo.getLoginUserId(); //받을사람의 이메일입니다.-> naver nate 등등 
        String subject = "온라인자료대출시스템 회원가입을 축하드립니다.";
        
    	Path path = Paths.get(template);
    	Charset cs = StandardCharsets.UTF_8;
    	List<String> list = new ArrayList<String>();
    	String contents = "";
    	try {
    		list = Files.readAllLines(path,cs);
    	}catch(IOException e) {
    		e.printStackTrace();
    	}
    	
    	for(String readLine : list) {
    		contents+=readLine;
    	}
    	contents=contents.replace("${userName}",vo.getName());
    	
    	email.setReciver(reciver);
        
        email.setSubject(subject);
        email.setContent(contents);
        emailSender.SendEmail(email);
        
		return "nlib/member/insertMemberInfoResult";
	}
	/**
	 * 이메일 인증번호 발송
	 * @exception Exception
	 */
	@RequestMapping(value="/member/emailCertNum.ajax" , method=RequestMethod.POST)
	public @ResponseBody void emailCertNum(HttpServletResponse response,HttpServletRequest request,HttpSession session) throws Exception{
		String email = request.getParameter("email");
		EmailVO emailVO = new EmailVO();
		//인증번호 생성
		String CertNumber=memberService.numberGen(6,1);
		System.out.println(CertNumber);
		//세션에 저장
		String jsessionId = session.getId();
		OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId);
		
		NlibLoginVO vo=oauthUser.getNlibVO();
		//이미 생성된 VO가 없을때
		if(vo==null)
			vo= new NlibLoginVO();
		vo.setEmail(email);
		vo.setEmailVrfctNo(CertNumber);
		oauthUser.setNlibVO(vo);
		SessionConfig.setNewMemberInfo(jsessionId,oauthUser);
		
		//이메일 발송
		// 결과가 정상이면, 안내 메일 발송 
    	// > 템플릿파일에서 내용 mailing.sender.membership.template
    	// > 치환 (사용자명, 이메일주소)
    	// > 발송처리 요청 
		String reciver = email; //받을사람의 이메일입니다.-> naver nate 등등 
        String subject = "온라인자료대출시스템 이메일 인증번호";
        
    	Path path = Paths.get(template);
    	Charset cs = StandardCharsets.UTF_8;
    	List<String> list = new ArrayList<String>();
    	String contents = "";
    	try {
    		list = Files.readAllLines(path,cs);
    	}catch(IOException e) {
    		e.printStackTrace();
    	}
    	
    	for(String readLine : list) {
    		contents+=readLine;
    	}
    	contents=contents.replace("${userName}",vo.getName()+"님의 인증번호는"+CertNumber+"입니다.");
    	
    	emailVO.setReciver(reciver);
        
    	emailVO.setSubject(subject);
    	emailVO.setContent(contents);
    	emailSender.SendEmail(emailVO);
		
		//------------
	}
	
	/**
	 * 이메일 인증번호 확인
	 * @exception Exception
	 */
	@RequestMapping(value="/member/emailCertNumChk.ajax" , method=RequestMethod.POST)
	public @ResponseBody String emailCertNumChk(HttpServletResponse response,HttpServletRequest request,HttpSession session) throws Exception{
		String email = request.getParameter("email");
		String emailVrfctNo = request.getParameter("emailVrfctNo");
		
		SimpleDateFormat format = new SimpleDateFormat ( "yyyy년 MM월dd일 HH시mm분ss초");
		
		//세션에 저장
		String jsessionId = session.getId();
		OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId);
		
		//핸드폰번호와 인증번호 확인
		if(oauthUser.getNlibVO().getEmail().equals(email) && oauthUser.getNlibVO().getEmailVrfctNo().equals(emailVrfctNo))
		{
			Date time = new Date();
			NlibLoginVO sessionNlibLoginVO = oauthUser.getNlibVO();
			sessionNlibLoginVO.setEmailVrfctDd(format.format(time));
			oauthUser.setNlibVO(sessionNlibLoginVO);
			SessionConfig.setNewMemberInfo(jsessionId,oauthUser);
			return "true";
		}else {
			return "false";
		}
	}
	
	/**
	 * 핸드폰 인증번호 발송
	 * @exception Exception
	 */
	@RequestMapping(value="/member/mobileCertNum.ajax" , method=RequestMethod.POST)
	public @ResponseBody void phoneCertNum(HttpServletResponse response,HttpServletRequest request,HttpSession session) throws Exception{
		String mobileNo = request.getParameter("mobileNo");
		
		//인증번호 생성
		String CertNumber=memberService.numberGen(6,1);
		System.out.println(CertNumber);
		//세션에 저장
		String jsessionId = session.getId();
		OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId);
		
		
		NlibLoginVO vo=oauthUser.getNlibVO();
		//이미 생성된 VO가 없을때
		if(vo==null)
			vo= new NlibLoginVO();
		
		vo.setMobileNo(mobileNo);
		vo.setMobileVrfctNo(CertNumber);
		oauthUser.setNlibVO(vo);
		SessionConfig.setNewMemberInfo(jsessionId,oauthUser);
		
		//문자발송 솔루션
		
		//------------
	}
	
	/**
	 * 핸드폰 인증번호 확인
	 * @exception Exception
	 */
	@RequestMapping(value="/member/mobileCertNumChk.ajax" , method=RequestMethod.POST)
	public @ResponseBody String mobileCertNumChk(HttpServletResponse response,HttpServletRequest request,HttpSession session) throws Exception{
		String mobileNo = request.getParameter("mobileNo");
		String mobileVrfctNo = request.getParameter("mobileVrfctNo");
		
		SimpleDateFormat format = new SimpleDateFormat ( "yyyy년 MM월dd일 HH시mm분ss초");
		
		//세션에 저장
		String jsessionId = session.getId();
		OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId);
		
		//핸드폰번호와 인증번호 확인
		if(oauthUser.getNlibVO().getMobileNo().equals(mobileNo) && oauthUser.getNlibVO().getMobileVrfctNo().equals(mobileVrfctNo))
		{
			Date time = new Date();
			NlibLoginVO sessionNlibLoginVO = oauthUser.getNlibVO();
			sessionNlibLoginVO.setMobileVrfctDd(format.format(time));
			oauthUser.setNlibVO(sessionNlibLoginVO);
			SessionConfig.setNewMemberInfo(jsessionId,oauthUser);
			return "true";
		}else {
			return "false";
		}
	}
	
    /**
	 * 비밀번호초기화 폼
	 * @exception Exception
	 */
	@RequestMapping(value="/member/initPasswordForm.do")
	public String searchIdForm(HttpServletResponse response,HttpServletRequest request) throws Exception{
		
		return "nlib/member/initPasswordForm";
	}
	
	/**
	 * 비밀번호 초기화
	 * @exception Exception
	 */
	@RequestMapping(value="/member/initPassword.ajax")
	public @ResponseBody String initPassword(NlibLoginVO vo,HttpServletResponse response,HttpServletRequest request,ModelMap model) throws Exception{
		
		NlibLoginVO loginVO =userInfoService.selectMyInfo(vo);
		
		EmailVO email = new EmailVO();
		
		String message = null;
		
		//비밀번호 초기화 변수 생성
		String InitPwd=memberService.createInitPwd();
		
		String encodedText=null;

		//ID와 핸드폰 번호가 일치하는지 확인
		if(loginVO!=null && (loginVO.getMobileNo().equals(vo.getMobileNo()) && loginVO.getLoginUserId().equals(vo.getLoginUserId())))
		{
			String reciver = vo.getLoginUserId(); //받을사람의 이메일입니다.-> naver nate 등등 
	        String subject = "온라인자료대출시스템 비밀번호 초기화 메일입니다.";
	        
	        
	    	// 결과가 정상이면, 안내 메일 발송 
	    	// > 템플릿파일에서 내용 mailing.sender.membership.pwdtemplate
	    	// > 치환 (사용자명, 이메일주소)
	    	// > 발송처리 요청 
	    	Path path = Paths.get(pwdTemplate);
	    	Charset cs = StandardCharsets.UTF_8;
	    	List<String> list = new ArrayList<String>();
	    	String contents = "";
	    	try {
	    		list = Files.readAllLines(path,cs);
	    	}catch(IOException e) {
	    		e.printStackTrace();
	    	}
	    	
	    	for(String readLine : list) {
	    		contents+=readLine;
	    	}
	    	
	    	encodedText = egovPasswordEncoder.encryptPassword(InitPwd);
			vo.setPassword(encodedText);
				
			vo.setMbInfoId(gUserId);
				
			//암호화된 비밀번호로 수정
			memberService.changePassword(vo);
				
	    	contents=contents.replace("${userPwd}",InitPwd);
			
	        email.setReciver(reciver);
	        
	        email.setSubject(subject);
	        email.setContent(contents);
	        emailSender.SendEmail(email);
	        
	       
			
	        message="초기화된 비밀번호가 이메일로 발송됐습니다.";
		}else {
			message="일치하는 아이디가 없습니다.";
		}
		
		return message;
	}
	

	/**
	 * 회원가입 SNS 구글인증
	 * @exception Exception
	 *//*
	@RequestMapping(value = "/member/googleCallback.do")
	public String googleCallback(@RequestParam(value = "code") String authCode, HttpSession session, Model model,
			HttpServletRequest request,RedirectAttributes rttr) throws Exception {

		String code = request.getParameter("code");
        HttpHeaders headers = new HttpHeaders();
        RestTemplate restTemplate = new RestTemplate(); 
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        
        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
        parameters.add("code", code);
        parameters.add("client_id", "879126511006-jro7bld7b2epl3n5mkksp0p24k2inbpu.apps.googleusercontent.com");
        parameters.add("client_secret", "F6T-ZV9jibLhKtcugxPUtBlN");
        parameters.add("redirect_uri", "http://nlib.nculture.org/nlib/member/googleCallback.do");
        parameters.add("grant_type", "authorization_code");
        
        HttpEntity<MultiValueMap<String,String>> rest_request = new HttpEntity<>(parameters,headers);
        
        URI uri = URI.create("https://www.googleapis.com/oauth2/v4/token");
        
        ResponseEntity<String> resultEntity;
        resultEntity = restTemplate.postForEntity(uri, rest_request, String.class);
		// JSON 파싱을 위한 기본값 세팅
		// 요청시 파라미터는 스네이크 케이스로 세팅되므로 Object mapper에 미리 설정해준다.
		ObjectMapper mapper = new ObjectMapper();
		mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
		mapper.setSerializationInclusion(Include.NON_NULL);
		// Token Request
		GoogleOAuthResponse result = mapper.readValue(resultEntity.getBody(), new TypeReference<GoogleOAuthResponse>() {
		});
		
		// ID Token만 추출 (사용자의 정보는 jwt로 인코딩 되어있다)
		String jwtToken = result.getIdToken();
		String requestUrl = UriComponentsBuilder.fromHttpUrl("https://oauth2.googleapis.com/tokeninfo")
				.queryParam("id_token", jwtToken).toUriString();

		String resultJson = restTemplate.getForObject(requestUrl, String.class);

		Map<String, String> userInfo = mapper.readValue(resultJson, new TypeReference<Map<String, String>>() {
		});
		
		rttr.addFlashAttribute("email",userInfo.get("email"));
		return "redirect:/member/insertMemberInfoForm.do";
	}*/
}