
package nlib.user.web;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import egovframework.com.ext.oauth.service.OAuthUniversalUser;
import egovframework.rte.fdl.cryptography.EgovPasswordEncoder;
import nlib.cmm.NlibCommonController;
import nlib.cmm.qrcode.QRCodeUtil;
import nlib.cmm.service.NlibProperty;
import nlib.col.service.CollectionService;
import nlib.col.service.CollectionVO;
import nlib.col.service.InterestService;
import nlib.col.service.ReadService;
import nlib.col.service.RentService;
import nlib.restful.service.DataApiResVO;
import nlib.security.SecUserDetailsService;
import nlib.security.SecUserVO;
import nlib.user.service.LoginService;
import nlib.user.service.NlibLoginVO;
import nlib.user.service.UserInfoService;
import nlib.util.StringUtil;


/**
 * <pre>
 * @Class Name : userInfoController.java
 * 
 * @Description : 회원 정보 controller
 * 
 * 
 * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
 *
 * </pre>
 *
 * @ ------------    --------    ---------------------------
 * @ 수정일                     수정자             수정내용
 * @ ------------    --------    ---------------------------
 * @ 2021. 7. 14.    JSYOO       최초 생성
 * @ 2021.10.  7.    KKN         회원증 조회 기능 추가 
 * @ 2021.11. 09.    KNKIM       마이페이지 기능 추가 
 *
 * 
 * @author 이씨플라자 * DIGITALSHIP JSYOO
 * @since 2021. 7. 14.
 * @version 1.0
 *
 */
@Controller
public class UserInfoController extends NlibCommonController {
	
	private static final Logger log = LoggerFactory.getLogger(UserInfoController.class);
	
	@Resource(name="userInfoService")
	private UserInfoService userInfoService;
	
	@Resource(name="loginService")
	private LoginService loginService;
	
	@Resource(name = "egovEnvPasswordEncoderService")
    EgovPasswordEncoder egovPasswordEncoder;
	
	@Resource(name = "userDetailsService")
	private SecUserDetailsService SecUserDetailsService;
	
	@Resource(name = "rentService")
	private RentService rentService;

	@Resource(name = "readService")
	private ReadService readService;
	
	@Resource(name = "interestService")
	private InterestService interestService;
	
	@Resource(name = "collectionService")
	private CollectionService collectionService;
	
	/** QRCodeService (2021.10.07) */
	@Resource(name = "qrCodeService")
	private QRCodeUtil qrCodeService;
	

	
	//마이페이지 uri
	@Value("#{properties['mypage.uri']}")
	private String myPageUri;
		
	/**
	 * 내 정보 조회
	 * @exception Exception
	 */
	@Secured("ROLE_USER")
	@RequestMapping(value="/userInfo/getMyInfo.do")
	public String getMyInfo(HttpServletResponse response,HttpServletRequest request) throws Exception{
		return "nlib/userInfo/getMyInfo";
	}
	
	/**
	 * 내 정보 수정 페이지
	 * @exception Exception
	 */
	@Secured("ROLE_USER")
	@RequestMapping(value="/userInfo/putMyInfo.do")
	public String putMyInfo(NlibLoginVO vo,HttpServletResponse response,HttpServletRequest request,Authentication authentication,ModelMap model) throws Exception{
		//사용자 정보를 가져온다.
		NlibLoginVO loginVO = getNlibLoginVO(authentication);

		if(loginVO == null)
		{
			model.addAttribute("msg","잘못된 접근입니다. \\n장시간 대기로 다시 로그인 하신 후, 이용해 주시기 바랍니다.");
			model.addAttribute("url","/userInfo/pwCertMyInfo.do");
			return "nlib/cmm/alert";
		}
		
		loginVO.setJoinCouncilCd(getCurCouncilCd(request));
		
		loginVO = loginService.selectLoginUserInfo(loginVO);
		if(loginVO == null)
		{
			model.addAttribute("msg","비정상적인 접근입니다. \\n관리자에게 문의하여 주시기 바랍니다.");
			model.addAttribute("url","/userInfo/pwCertMyInfo.do");
			return "nlib/cmm/alert";
		}
		 
		List<OAuthUniversalUser> snsList = new ArrayList<OAuthUniversalUser>();
		
		//sns연동 계정 리스트
		snsList = userInfoService.selectSnsSignUpList(loginVO);
		
		String encodedText=null;
		encodedText = egovPasswordEncoder.encryptPassword(loginVO.getLoginUserId()+vo.getPassword());
		vo.setPassword(encodedText);
		
		//암호화된 패스워드 비교
		if(loginVO.getPassword().equals(vo.getPassword())) {
			model.addAttribute("loginVO",loginVO);
			model.addAttribute("snsList",snsList);
			return "nlib/userInfo/putMyInfo";
		}else {
			model.addAttribute("msg","비밀번호가 일치하지않습니다.");
			model.addAttribute("url","/userInfo/pwCertMyInfo.do");
			return "nlib/cmm/alert";
		}
	}
	
	/**
	 * 내 정보 수정 
	 * @return 
	 * @exception Exception
	 */
	@Secured("ROLE_USER")
	@RequestMapping(value="/userInfo/updateMyInfo.do" , method=RequestMethod.POST)
	public String updateMyInfo(NlibLoginVO vo,Authentication authentication,HttpServletResponse response,HttpServletRequest request,ModelMap model) throws Exception{
		
		//사용자 정보를 가져온다.
		NlibLoginVO loginVO = getNlibLoginVO(authentication);
		
		//이메일인증 확인
		if(!(vo.getEmail().equals(loginVO.getEmail())))
		{
			if(!(vo.getEmailVrfctNo().equals(loginVO.getEmailVrfctNo()))
					||loginVO.getEmailVrfctDd() == null)  
			{
				model.addAttribute("msg","이메일인증이 정상적이지않습니다.");
				model.addAttribute("url",myPageUri);
				return "nlib/cmm/alert";
			}
			vo.setEmail(loginVO.getEmailTemp());
		}
		//핸드폰인증 확인
		if(!(vo.getMobileNo().equals(loginVO.getMobileNo())))
		{
			if(!(vo.getMobileVrfctNo().equals(loginVO.getMobileVrfctNo()))
					||loginVO.getMobileVrfctDd() == null)  
			{
				model.addAttribute("msg","핸드폰인증이 정상적이지않습니다.");
				model.addAttribute("url",myPageUri);
				return "nlib/cmm/alert";
			}
			vo.setMobileNo(loginVO.getMobileTemp());
		}
		
		String encodedText=null;
		encodedText = egovPasswordEncoder.encryptPassword(vo.getPassword());
		vo.setPassword(encodedText);
		
		// 내 정보 수정
		userInfoService.updateMyInfo(vo);
		NlibLoginVO sessionVO=(NlibLoginVO) SecUserDetailsService.loadUserByUsername(vo.getLoginUserId());
		
		//세션에 수정정보로 재 주입
		replaceNlibLoginVO(request,loginVO);
		
		model.addAttribute("msg","수정되었습니다.");
		model.addAttribute("url",myPageUri);
		return "nlib/cmm/alert";
	}
	
	/**
	 * 내 정보 수정 전 password 인증
	 * @exception Exception
	 */
	@Secured("ROLE_USER")
	@RequestMapping(value="/userInfo/pwCertMyInfo.do")
	public String pwCertMyInfo(HttpServletResponse response,HttpServletRequest request,ModelMap model) throws Exception{
		NlibLoginVO loginVO = getNlibLoginVO(request);
		
		if(loginVO == null)
		{
			model.addAttribute("msg","잘못된 접근입니다. \\n장시간 대기로 다시 로그인 하신 후, 이용해 주시기 바랍니다.");
			model.addAttribute("url","${pageContext.request.contextPath}"+"/");
			return "nlib/cmm/alert";
		}
		
		model.addAttribute("loginVO",loginVO);
		return "nlib/userInfo/pwCertMyInfo";
	}
	
	/** SNS연동을 해지한다.
	 * @param response
	 * @param request
	 * @return 
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/userInfo/deleteSnsLink.ajax")
	public @ResponseBody void deleteSnsLink(HttpServletResponse response,HttpServletRequest request) throws Exception{
		OAuthUniversalUser oAuthVO = new OAuthUniversalUser();
		oAuthVO.setMbSnsId(request.getParameter("mbSnsId"));
		userInfoService.deleteSnsLink(oAuthVO);
		
	}
	
	/**
	 * 회원증 QR코드를 조회한다.
	 *  
	 * (2021.10.07 KKN 추가)
	 * 
	 * @param request
	 * @param model
	 * @return
	 */
	@Secured("ROLE_USER")
	@RequestMapping(value="/userInfo/getMemberQrcodeFormPopup.do")
	public String getMemberQrcodeFormPopup(HttpServletRequest request, ModelMap model) {

		NlibLoginVO loginVO = getNlibLoginVO(request);
    	log.debug("getMemberQrcode : loginVO=" + loginVO.toString());
    	
    	model.addAttribute("loginVO", loginVO);
    	
        return "nlib/userInfo/getMemberQrcodeFormPopup";
	}
	
    /**
     * 회원정보를 가지고 QR 2D 바코드를 생성하여 이미지(JPG)로 출력한다.  
     * (Zxing Lib 사용)
     *  
	 * (2021.10.07 KKN 추가)
     * 
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
	@Secured("ROLE_USER")
    @RequestMapping(value="/userInfo/getMemberQrcode.do", produces=MediaType.IMAGE_JPEG_VALUE)
    public ResponseEntity<byte[]> getMemberQrcode(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
    	NlibLoginVO loginVO = getNlibLoginVO(request);
    	
    	if(loginVO == null || StringUtil.isEmpty(loginVO.getMbInfoId())) {
    		throw new Exception("잘못된 접근입니다.");
    	}
    	
    	BufferedImage bufferedImage = qrCodeService.generateMemberQrcodeImage(loginVO);
    	
    	ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write( bufferedImage  , "jpg", byteArrayOutputStream);
        byte[] bs = byteArrayOutputStream.toByteArray();
        response.setContentLength(bs.length);
        
        final HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG);
        return new ResponseEntity<byte[]>(bs , headers, HttpStatus.OK);
    }

    /**
     * 회원의 마이페이지를 출력한다.  
     * (Zxing Lib 사용)
     *  
	 * (2021.10.07 KKN 추가)
     * 
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Secured("ROLE_USER")
    @RequestMapping(value="/userInfo/getMyHome.do")
	public String getMyHome(HttpServletRequest request, ModelMap model) throws Exception {

		NlibLoginVO loginVO = getNlibLoginVO(request);
    	log.debug("getMemberQrcode : loginVO=" + loginVO.toString());
    	
    	model.addAttribute("loginVO", loginVO);
    	
    	// 이전접속정보 
    	Map<String, String> lastLogin = null;
    	List<Map<String, String>> lastLoginList = userInfoService.getLastLogin(loginVO.getMbInfoId());
    	if(lastLoginList == null || lastLoginList.size() < 1) {
    		lastLogin = new HashMap<String, String>(); 
    		lastLogin.put("dtStr", "(최초접속)");
    		lastLogin.put("dtStr", " ");
    	} else if(lastLoginList.size() == 1) {
    		lastLogin = lastLoginList.get(0);
    	} else {
    		lastLogin = lastLoginList.get(1);
    	}
    	model.addAttribute("lastLogin", lastLogin);
    	
    	// 소장자료관 접속현황  (최근 5개)
    	List<Map<String, String>> visitedOrgs = userInfoService.getVisitedOrgs(loginVO.getMbInfoId());
    	model.addAttribute("visitedOrgs", visitedOrgs);
    	
    	// 대출/방문열람 현황
    	Map<String, String> rentStats = rentService.getRentStats(loginVO.getMbInfoId());
    	model.addAttribute("rentStats", rentStats);
    	
    	CollectionVO searchCollectionVO = new CollectionVO();
    	searchCollectionVO.setMbInfoId(loginVO.getMbInfoId());
    	searchCollectionVO.setPageSize(5);

    	// 관심자료  (최근 5개) 
    	List<CollectionVO> interestList = interestService.listInterests(searchCollectionVO);
    	int interestTotalCount = interestService.countListInterests(searchCollectionVO);

    	interestList = collectionService.setDetailInfoForList(interestList, searchCollectionVO.getMbInfoId());
		
    	model.addAttribute("interestList", interestList);
    	model.addAttribute("interestTotalCount", interestTotalCount);
    	
    	// 대출내역   (최근 5개)
    	// 조회 
    	// 대출상태구분코드("": 전체, A:신청, B:대출준비완료, C:취소, W:대출중, R0:정상반납, R1:연체반납, P:연체)
		DataApiResVO resRentVO = rentService.listRentItems(searchCollectionVO);
		List<CollectionVO> rentList = collectionService.setDetailInfoForHashList(resRentVO.getRecordList(), searchCollectionVO.getMbInfoId());
		model.addAttribute("rentList", rentList);
		model.addAttribute("rentTotalCount", resRentVO.getRecordTotCount());
    	
    	// 방문열람내역  (최근 5개) 
		searchCollectionVO.setReqStatusDivCd(null); 
		DataApiResVO resReadVO = readService.listReadItems(searchCollectionVO);
		List<CollectionVO> readList = collectionService.setDetailInfoForHashList(resReadVO.getRecordList(), searchCollectionVO.getMbInfoId());
		model.addAttribute("readList", readList);
		model.addAttribute("readTotalCount", resReadVO.getRecordTotCount());

        return "nlib/userInfo/getMyHome";
	}
}