package incheon.res.rdm.oe.requsr.web;

import incheon.com.cmm.ComDefaultVO;
import incheon.com.cmm.ResponseCode;
import incheon.com.cmm.api.DefaultApiResponse;
import incheon.com.security.vo.LoginVO;
import incheon.res.app.code.service.UngisAppCodeService;
import incheon.res.com.excel.web.CommonExcelView;
import incheon.res.com.util.ComStringUtil;
import incheon.res.rdm.com.code.service.RdmComCodeService;
import incheon.res.rdm.oe.intusr.service.RmtAusrDtService;
import incheon.res.rdm.oe.intusr.service.RmtDusrDtService;
import incheon.res.rdm.oe.intusr.vo.RmtAusrDtVO;
import incheon.res.rdm.oe.intusr.vo.RmtDusrDtVO;
import incheon.res.rdm.oe.requsr.service.RdmOeRequsrService;
import incheon.res.rdm.oe.requsr.vo.RdmOeRequsr;
import incheon.res.rdm.oe.requsr.vo.RdmOeRequsrVO;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.property.EgovPropertyService;
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Controller
@SessionAttributes(types = ComDefaultVO.class)
@RequestMapping("${api.rps-path}")
@Slf4j
public class RdmOeRequsrController{

	@Resource
	private RdmOeRequsrService rdmOeRequsrService;
	@Resource
	private RmtAusrDtService rmtAusrDtService;
	@Resource
	private RmtDusrDtService rmtDusrDtService;
    @Resource
    protected EgovPropertyService propertiesService;
    @Resource
    protected UngisAppCodeService ungisAppCodeService;
    @Resource
    protected RdmComCodeService rdmComCodeService;

    public static final int KEY_SIZE = 2048;

    /**
     * @MethodDESC : 사용자 목록 조회
     */
    @RequestMapping(value="/RdmOeRequsrL010.do")
    public String selectRequsrList(@RequestParam(defaultValue = "1") int pageIndex,
								   @ModelAttribute("rdmOeRequsrVO") RdmOeRequsrVO vo, ModelMap model)
    		  throws Exception{

		/*페이징*/
		vo.setPageIndex(pageIndex);

		PaginationInfo paginationInfo = new PaginationInfo();
		paginationInfo.setCurrentPageNo(pageIndex);
		paginationInfo.setRecordCountPerPage(vo.getRecordCountPerPage());
		paginationInfo.setPageSize(vo.getPageSize());

		vo.setFirstIndex(paginationInfo.getFirstRecordIndex());
		vo.setLastIndex(paginationInfo.getLastRecordIndex());
		vo.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());

        int totCnt = rdmOeRequsrService.countList(vo);
        paginationInfo.setTotalRecordCount(totCnt);

        //사용자 등록 요청 목록
        List resultList = rdmOeRequsrService.selectRequsrList(vo);

        //사용자 상태 목록
        List ussCdeList = ungisAppCodeService.getCodeList("USS", "RMT_USER_DT", "Y");

        //사용자 권한 목록
        List uatCdeList = rdmComCodeService.selectApplicantCodeList("Y");

        model.addAttribute("resultList", resultList);
        model.addAttribute("ussCdeList", ussCdeList);
        model.addAttribute("uatCdeList", uatCdeList);
        model.addAttribute("paginationInfo", paginationInfo);
        model.addAttribute("searchVo", vo);

    	return "res/rdm/oe/requsr/RdmOeRequsrL010";
    }

    /**
     * @MethodDESC : 사용자 상세 정보 조회
     */
    @RequestMapping(value="/RdmOeRequsrR010.do")
    public String selectRequsr(@ModelAttribute("rdmOeRequsrVO") RdmOeRequsrVO vo, ModelMap model)
    		  throws Exception{
		RdmOeRequsr result = rdmOeRequsrService.selectRequsr(vo);

		model.addAttribute("result", result);
        model.addAttribute("searchVo", vo);

    	return "res/rdm/oe/requsr/RdmOeRequsrR010";
    }

    /**
     * @MethodDESC : 유관기관 사용자 정보 수정 화면 이동
     */
    @RequestMapping(value="/RdmOeRequsrU010.do")
    public String updateRequsrView(HttpServletRequest request, @ModelAttribute("rdmOeRequsrVO") RdmOeRequsrVO vo, ModelMap model)
    		  throws Exception{
    	String publicKeyModulus = "";
		String publicKeyExponent= "";
		try {
			KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
			generator.initialize(KEY_SIZE);
			
			KeyPair keyPair = generator.genKeyPair();
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			
			PublicKey publicKey = keyPair.getPublic();
			PrivateKey privateKey = keyPair.getPrivate();
			
			HttpSession session = request.getSession();
			//세션에 공개키를 개인키로 저장한다.
			session.setAttribute("UFIS_RDM_VAL", privateKey);
			
			//공개키를 문자열로 변환하여 javascript RSA 라이브러리로 넘겨준다.
			RSAPublicKeySpec publicSpec = (RSAPublicKeySpec) keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class);
			
			publicKeyModulus = publicSpec.getModulus().toString(16);
			publicKeyExponent = publicSpec.getPublicExponent().toString(16);

			
		} catch (GeneralSecurityException e) {
			log.error("암호화 키 생성 알고리즘 오류 발생", e);
			throw new RuntimeException("암호화 처리 중 시스템 오류가 발생했습니다.");
		} catch (IllegalArgumentException e) {
			log.error("암호화 키 사이즈 또는 파라미터 오류", e);
			throw new RuntimeException("암호화 설정 오류가 발생했습니다.");
		}
		model.addAttribute("publicKeyModulus", publicKeyModulus);
		model.addAttribute("publicKeyExponent", publicKeyExponent);
    	
		RdmOeRequsr result = rdmOeRequsrService.selectRequsr(vo);
		
    	String uatCde = result.getUserAuthrt();
    	String ssoyn = "n";
    	
		model.addAttribute("uatCde", uatCde);
		model.addAttribute("ssoyn", ssoyn);
		model.addAttribute("rdmOeRequsr", result);
        model.addAttribute("searchVo", vo);

    	return "res/rdm/oe/requsr/RdmOeRequsrU010";
    }
    
    /**
     * @MethodDESC : 개인사용자 정보 수정화면ㅇ 이동
     */
    @RequestMapping(value="/RdmOeRequsrU060.do")
    public String updateRequsrView2(HttpServletRequest request, @ModelAttribute("rdmOeRequsrVO") RdmOeRequsrVO vo, ModelMap model)
    		  throws Exception{
    	String publicKeyModulus = "";
		String publicKeyExponent= "";
		try {
			KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
			generator.initialize(KEY_SIZE);
			
			KeyPair keyPair = generator.genKeyPair();
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			
			PublicKey publicKey = keyPair.getPublic();
			PrivateKey privateKey = keyPair.getPrivate();
			
			HttpSession session = request.getSession();
			//세션에 공개키를 개인키로 저장한다.
			session.setAttribute("UFIS_RDM_VAL", privateKey);
			
			//공개키를 문자열로 변환하여 javascript RSA 라이브러리로 넘겨준다.
			RSAPublicKeySpec publicSpec = (RSAPublicKeySpec) keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class);
			
			publicKeyModulus = publicSpec.getModulus().toString(16);
			publicKeyExponent = publicSpec.getPublicExponent().toString(16);

			
		} catch (GeneralSecurityException e) {
			log.error("암호화 키 생성 알고리즘 오류 발생", e);
			throw new RuntimeException("암호화 처리 중 시스템 오류가 발생했습니다.");
		} catch (IllegalArgumentException e) {
			log.error("암호화 키 사이즈 또는 파라미터 오류", e);
			throw new RuntimeException("암호화 설정 오류가 발생했습니다.");
		}
		model.addAttribute("publicKeyModulus", publicKeyModulus);
		model.addAttribute("publicKeyExponent", publicKeyExponent);
    	
		RdmOeRequsr result = rdmOeRequsrService.selectRequsr(vo);
		
    	String uatCde = result.getUserAuthrt();
		String ssoyn = "n";
    	
		model.addAttribute("uatCde", uatCde);
		model.addAttribute("ssoyn", ssoyn);
		model.addAttribute("rdmOeRequsr", result);
        model.addAttribute("searchVo", vo);

    	return "res/rdm/oe/requsr/RdmOeRequsrU060";
    }

    /**
     * @MethodDESC : 사용자 정보 수정
     */
	@PostMapping(
			value = "/RdmOeRequsrU011.do",
			consumes = MediaType.MULTIPART_FORM_DATA_VALUE
	)
	public ResponseEntity<DefaultApiResponse<Map<String, Object>>> updateRequsr(@ModelAttribute RdmOeRequsrVO vo, HttpServletRequest request
	) throws Exception {

		String encPwd = "";

		HttpSession session = request.getSession();
		PrivateKey privateKey = (PrivateKey) session.getAttribute("UFIS_RDM_VAL");

		if (privateKey == null) {
			log.error("암호화 비밀키 정보를 찾을 수 없습니다.");
		}

		String uuPwd = vo.getUserPswd();

		//복호화
		try{
			if(uuPwd != null && !"".equals(uuPwd)){
				String pswd = ComStringUtil.decryptRsa(privateKey, uuPwd);
				vo.setUserPswd(pswd);
			}
		}catch(IllegalArgumentException e){
			throw new Exception("복호화 과정중 오류가 발생하였습니다.");
		}

		session.removeAttribute("UFIS_RDM_VAL"); // 키의 재사용을 막는다. 항상 새로운 키를 받도록 강제.

		if(!"".equals(vo.getUserPswd())){
			rmtAusrDtService.updateRmtAusrDt(vo);
		}else{
			rmtAusrDtService.updateRmtAusrDtWithoutPwd(vo);
		}
		Map<String, Object> resultMap = new HashMap<String, Object>();

		resultMap.put("result", "succ");

		return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
    }

    /**
     * @MethodDESC : 사용자 승인처리
     */
	@PostMapping(value = "/RdmOeRequsrU020.do")
	public ResponseEntity<DefaultApiResponse<Map<String, Object>>> approveRequsr(@ModelAttribute("loginUser") LoginVO loginVO,
																				 @ModelAttribute RdmOeRequsrVO vo) throws Exception {


		String sessionUserId = loginVO.getUserUnqId();

		RdmOeRequsr rdmOeRequsr = rdmOeRequsrService.selectRequsr(vo);
		RmtAusrDtVO radVo = new RmtAusrDtVO();
		radVo.setUserAcntMngNo(rdmOeRequsr.getUserAcntMngNo());
		radVo.setAutzrId(sessionUserId);

		RmtAusrDtVO dvo = rmtAusrDtService.selectRmtAusrInfo(radVo);
		if(dvo == null){
			RmtDusrDtVO rmtDusrDtVO = new RmtDusrDtVO();
			rmtDusrDtVO.setUserAcntMngNo(rdmOeRequsr.getUserAcntMngNo());

			RmtDusrDtVO resultVO = rmtDusrDtService.selectRmtDusrInfo(rmtDusrDtVO);

			rmtDusrDtService.deleteRmtDusrDt(rmtDusrDtVO);

			RmtAusrDtVO approveVO = new RmtAusrDtVO();

			approveVO = rdmOeRequsrService.dusr2Ausr(resultVO);
			approveVO.setAutzrId(sessionUserId);

			rmtAusrDtService.approveRequsrInfo(approveVO);

		}else{
			RmtDusrDtVO rmtDusrDtVO = new RmtDusrDtVO();
			rmtDusrDtVO.setUserAcntMngNo(rdmOeRequsr.getUserAcntMngNo());

			RmtDusrDtVO resultVO = rmtDusrDtService.selectRmtDusrInfo(rmtDusrDtVO);
			
			if(resultVO != null ){
				rmtDusrDtService.deleteRmtDusrDt(rmtDusrDtVO);
				rmtAusrDtService.approveRequsr(radVo);
			}else{
				rmtAusrDtService.approveRequsr(radVo);
			}
		}

		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("result", "succ");

		return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
		
    }

    /**
     * @MethodDESC : 사용자 승인 취소 처리
     */
	@PostMapping(
			value = "/RdmOeRequsrU030.do",
			consumes = MediaType.MULTIPART_FORM_DATA_VALUE
	)
	public ResponseEntity<DefaultApiResponse<Map<String, Object>>> rejectRequsr(@ModelAttribute("loginUser") LoginVO loginVO,
			@ModelAttribute RdmOeRequsrVO vo) throws Exception {


		String sessionUserId = loginVO.getUserUnqId();

		RdmOeRequsr rdmOeRequsr = rdmOeRequsrService.selectRequsr(vo);

		// 사용자 테이블 분리
		RmtAusrDtVO rmtAusrDtVO = new RmtAusrDtVO();
		rmtAusrDtVO.setUserAcntMngNo(rdmOeRequsr.getUserAcntMngNo());
		rmtAusrDtVO.setCnclrId(sessionUserId);
		RmtAusrDtVO resultVO = rmtAusrDtService.selectRmtAusrInfo(rmtAusrDtVO);

		rmtAusrDtService.updateRmtAusrCancelDt(rmtAusrDtVO);
		
		RmtDusrDtVO rmtDusrDtDVO = new RmtDusrDtVO();
		rmtDusrDtDVO = rdmOeRequsrService.ausr2Dusr(resultVO);

		rmtDusrDtDVO.setCnclrId(sessionUserId);
		rmtDusrDtService.rejectRequsrInfo(rmtDusrDtDVO);
		rmtDusrDtService.insertRmtAusrLogDt(rmtDusrDtDVO);

		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("result", "succ");

		return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
	}

    /**
     * @MethodDESC : 사용자 일괄 승인 처리
     */
	@RequestMapping(value="/RdmOeRequsrU040.do")
	public ResponseEntity<DefaultApiResponse<Map<String, Object>>> approveRequsrList(@ModelAttribute("loginUser") LoginVO loginVO,
																					 @ModelAttribute RdmOeRequsrVO vo) throws Exception {


		String sessionUserId = loginVO.getUserUnqId();

    	//사용자 테이블 일괄 변경
    	vo.setAutzrId(sessionUserId);
    	rdmOeRequsrService.approveRequsrBatch(vo);

		Map<String, Object> resultMap = new HashMap<>();
    	resultMap.put("result", "succ");

		return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
	}

    /**
     * @MethodDESC : 사용자 일괄 승인 취소 처리
     */
	@RequestMapping(value="/RdmOeRequsrU050.do")
	public ResponseEntity<DefaultApiResponse<Map<String, Object>>> rejectRequsrList(@ModelAttribute("loginUser") LoginVO loginVO,
																					@ModelAttribute RdmOeRequsrVO vo) throws Exception {


		String sessionUserId = loginVO.getUserUnqId();

    	//사용자 테이블 일괄 변경
    	vo.setCnclrId(sessionUserId);
    	rdmOeRequsrService.rejectRequsrBatch(vo);

		Map<String, Object> resultMap = new HashMap<>();
    	resultMap.put("result", "succ");

		return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
    }
    
    /**
    * @MethodDESC : 비밀번호 초기화
    */
   @RequestMapping(value="/RdmOeRequsrU070.do")
   public ResponseEntity<DefaultApiResponse<Map<String, Object>>> resetRequsrList(@ModelAttribute RdmOeRequsrVO vo)
   		  throws Exception{

	   //비밀번호 리셋
	   try{
		rdmOeRequsrService.resetRequsr(vo);
	   }catch(IllegalStateException e){
		   log.error("비밀번호 리셋 중 오류가 발생했습니다.");
		   Map<String, Object> failMap = new HashMap<>();
		   failMap.put("result", "fail");
		   return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
	   }

	   Map<String, Object> resultMap = new HashMap<>();
	   resultMap.put("result", "succ");

	   return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
   }

    
    /**
    * @MethodDESC : 사용취소이력 조회
    */
   @RequestMapping(value="/RdmOeRequsrLogL010.do")
   public String selectRequsrCancelLogList(@RequestParam(defaultValue = "1") int pageIndex, @ModelAttribute RdmOeRequsrVO vo, ModelMap model)
   		  throws Exception{

	   /*페이징*/
	   vo.setPageIndex(pageIndex);

	   PaginationInfo paginationInfo = new PaginationInfo();
	   paginationInfo.setCurrentPageNo(pageIndex);
	   paginationInfo.setRecordCountPerPage(vo.getRecordCountPerPage());
	   paginationInfo.setPageSize(vo.getPageSize());

	   vo.setFirstIndex(paginationInfo.getFirstRecordIndex());
	   vo.setLastIndex(paginationInfo.getLastRecordIndex());
	   vo.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());

       int totCnt = rdmOeRequsrService.countLogList(vo);
       paginationInfo.setTotalRecordCount(totCnt);

       //사용자 등록 요청 목록
       List resultList = rdmOeRequsrService.selectRequsrLogList(vo);

       //사용자 상태 목록
       List ussCdeList = ungisAppCodeService.getCodeList("USS", "RMT_USER_DT", "Y");

       //사용자 권한 목록
       List uatCdeList = rdmComCodeService.selectApplicantCodeList("Y");

       model.addAttribute("resultList", resultList);
       model.addAttribute("ussCdeList", ussCdeList);
       model.addAttribute("uatCdeList", uatCdeList);
       model.addAttribute("paginationInfo", paginationInfo);
       model.addAttribute("searchVo", vo);

	   return "res/rdm/oe/requsr/RdmOeRequsrLogL010";
   }
   
   /**
   * @MethodDESC : 사용취소이력 상세 정보 조회
   */
  @RequestMapping(value="/RdmOeRequsrLogR010.do")
  public String selectRequsrLog(@ModelAttribute("rdmOeRequsrVO") RdmOeRequsrVO vo, ModelMap model)
  		  throws Exception{

		RdmOeRequsr result = rdmOeRequsrService.selectRequsrLog(vo);

		model.addAttribute("result", result);
		model.addAttribute("searchVo", vo);

		return "res/rdm/oe/requsr/RdmOeRequsrLogR010";
  }
  
  /**
  * @MethodDESC : 사용취소이력 상세 정보 조회
  */
  @RequestMapping(value = "/RdmOeRequsrLogL010Excel.do")
	public ModelAndView RdmOeRequsrLogL010Excel(@ModelAttribute("rdmOeRequsrVO")RdmOeRequsrVO vo, HttpServletRequest request,
												HttpServletResponse response) throws Exception {
		
		Map<String, Object> map = rdmOeRequsrService.selectRequsrLogExcel(vo);

		LinkedHashMap<String, String> cellValue = new LinkedHashMap<String, String>();
		
		cellValue.put( "사용자계정관리번호", "userAcntMngNo");
		cellValue.put( "업체기관관리번호", "bzentyInstMngNo");
		cellValue.put( "업체명", "bzentyNm");
		cellValue.put( "사용자 ID", "userId");
		cellValue.put( "주민번호", "rrno");
		cellValue.put( "사용자암호", "userPswd");
		cellValue.put( "사용자명", "userNm");
		cellValue.put( "이메일", "eml");
		cellValue.put( "소속부서", "ogdpDeptNm");
		cellValue.put( "직위", "jbps");
		cellValue.put( "전화번호", "telno");
		cellValue.put( "휴대폰번호", "mblTelno");
		
		cellValue.put( "우편번호(개인굴착)", "zip");
		cellValue.put( "주소(개인굴착)", "addr");
		cellValue.put( "상세주소(개인굴착)", "daddr");
		cellValue.put( "공인인증번호", "athriCertNo");
		cellValue.put( "공인인증기관", "athriCertInst");
		cellValue.put( "공인인증ID", "athriCertId");
		cellValue.put( "담당협의구", "tkcgCnsltnGu");
		cellValue.put( "담당협의동", "tkcgCnsltnDng");
		
		cellValue.put( "승인일시", "aprvDt");
		cellValue.put( "사용자권한", "userAuthrt");
		
		cellValue.put( "사용자권한명", "userAuthrtNm");
		cellValue.put( "시군구민원접수담당자ID", "sggCvlcptRcptPicId");
		cellValue.put( "사용상태", "useStts");
		cellValue.put( "사용상태명", "useSttsNm");
		cellValue.put( "인터넷사용자등록일시", "itntUserRegDt");
		cellValue.put( "인터넷사용자수정일시", "itntUserMdfcnDt");
		cellValue.put( "개인굴착동의여부", "indvDggAgreYn");
		cellValue.put( "전자문서사용자ID", "elaprLgnId");
		cellValue.put( "필수협의여부", "esntlCnsltnManYn");
		cellValue.put( "취소일시", "rtrcnDt");

	  Map<String, Object> model = new HashMap<>();
	  model.put("resultList", map.get("resultList"));
	  model.put("cellValue", cellValue);

	  model.put("excelTitle", "사용취소이력");
	  //다운로드 완료 후 쿠키셋 (로딩바닫기)
	  String token = request.getParameter("downloadToken");
	  if (token != null && !token.isEmpty()) {
		  javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie("fileDownloadToken",token);
		  cookie.setPath("/");
		  cookie.setHttpOnly(false);   // JS에서 읽어야 하므로 false
		  cookie.setMaxAge(120);
		  response.addCookie(cookie);
	  }

	  return new ModelAndView(new CommonExcelView(), model);

	}
}
