package incheon.res.mng.us.vusr.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.app.code.service.UngisAppPostCodeService;
import incheon.res.app.code.vo.UngisAppPostCodeVO;
import incheon.res.com.util.ComStringUtil;
import incheon.res.mng.us.vusr.service.MngUsVusrService;
import incheon.res.mng.us.vusr.vo.MngUsVusrVO;
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.perorg.service.RdmOePerorgService;
import incheon.res.rdm.oe.perorg.vo.RdmOePerorgVO;
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.apache.log4j.Logger;
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.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@SessionAttributes(types = ComDefaultVO.class)
@Slf4j
@RequestMapping("${api.rcs-path}")
public class MngUsVusrController {

    @Resource(name = "propertiesService")
    protected EgovPropertyService propertiesService;

    @Resource
    protected MngUsVusrService mngUsVusrService;

    @Resource
    private RdmOeRequsrService rdmOeRequsrService;

    @Resource
    protected UngisAppCodeService ungisAppCodeService;

    @Resource
    protected RdmComCodeService rdmComCodeService;

    @Resource
    private RmtAusrDtService rmtAusrDtService;

    @Resource
    private RmtDusrDtService rmtDusrDtService;

    @Resource
    private RdmOePerorgService rdmOePerorgService;

    @Resource
    private UngisAppPostCodeService ungisAppPostCodeService;

    Logger logger = Logger.getLogger(this.getClass());

    public static final int KEY_SIZE = 2048;

    /**
     * @MethodDESC : 유관기관 사용자 조회.
     */

    @RequestMapping(value = "/MngUsVusrL010.do")
    public String selectVusrList(@RequestParam(defaultValue = "1") int pageIndex, @ModelAttribute("mngUsVusrVO") MngUsVusrVO vo, Model 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());

        //유관기관사용자 COUNT
        int totCnt = mngUsVusrService.countVusr(vo);
        paginationInfo.setTotalRecordCount(totCnt);
        model.addAttribute("resultCnt",totCnt);
        model.addAttribute("paginationInfo", paginationInfo);
        //사용자 상태 목록
        List ussCdeList = ungisAppCodeService.getCodeList("USS", "RMT_USER_DT", "Y");

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

        model.addAttribute("ussCdeList", ussCdeList);
        model.addAttribute("uatCdeList", uatCdeList);

        //유관기관사용자 LIST
        List resultList = mngUsVusrService.selectVusrList(vo);
        model.addAttribute("resultList", resultList);

        return "res/mng/us/vusr/MngUsVusrL010";
    }

    /**
     * @MethodDESC : 유관기관 사용자 상세 조회.
     */

    @RequestMapping("/MngUsVusrR010.do")
    public String selectVusr(@ModelAttribute("mngUsVusrVO") MngUsVusrVO vo, Model model) throws Exception{
        String resultURL = "";

        MngUsVusrVO resultVO = mngUsVusrService.selectVusr(vo);
        model.addAttribute("resultVO", resultVO);
        resultURL = "res/mng/us/vusr/MngUsVusrR010";

        return resultURL;
    }

    /**
     * @MethodDESC : 유관기관 사용자 수정페이지로 이동.
     */

    @RequestMapping("/MngUsVusrU010.do")
    public String updateVusr(HttpServletRequest request, @ModelAttribute("mngUsVusrVO") MngUsVusrVO vo, Model 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);

        MngUsVusrVO resultVO = mngUsVusrService.selectVusr(vo);
        model.addAttribute("mngUsVusrVO", resultVO);
        return "res/mng/us/vusr/MngUsVusrU010";
    }

    /**
     * @MethodDESC : 유관기관 사용자 일괄 사용승인.
     */

    @RequestMapping("/MngUsVusrU020.do")
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> vusrListUssApprove(@ModelAttribute("loginUser") LoginVO loginVO,
                                                                                      @Valid @RequestBody 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="/MngUsVusrU030.do")
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> vusrListUssCancel(@ModelAttribute("loginUser") LoginVO loginVO,
                                                                                     @Valid @RequestBody 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("/MngUsVusrU040.do")
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> vusrUssApprove(@ModelAttribute("loginUser") LoginVO loginVO,
                                                                                  @ModelAttribute("rdmOeRequsrVO") 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{
            rmtAusrDtService.approveRequsr(radVo);
        }

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

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

    /**
     * @MethodDESC : 유관기관 사용자 승인 취소
     */
    @RequestMapping(value="/MngUsVusrU050.do")
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> vusrUssCancel(@ModelAttribute("loginUser") LoginVO loginVO,
                                                                                 @ModelAttribute("rdmOeRequsrVO") 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);

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

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

    }

    /**
     * @MethodDESC : 유관기관 사용자 수정
     */
    @RequestMapping(value="/MngUsVusrU011.do")
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> vusrSave(@ModelAttribute("mngUsVusrVO") RdmOeRequsrVO vo, HttpServletRequest request)throws Exception {
        String encPwd = "";
        Map<String, Object> resultMap = new HashMap<>();

        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);
        }

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

        return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
    }
    /**
     * @MethodDESC : 유관기관 사용자 업체명 검색
     */
    @RequestMapping("/MngUsVusrP010.do")
    public String selectVusrListPopup(@RequestParam(defaultValue = "1") int pageIndex, @ModelAttribute("rdmOePerorgVO") RdmOePerorgVO 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());

        /** page count */
        int totCnt = rdmOePerorgService.countPerorgListPopup(vo);
        //업종
        List tobCdeList = rdmComCodeService.selectApplicantTobList("N");
        //검색
        List resultList = rdmOePerorgService.selectPerorgListPopup(vo);

        paginationInfo.setTotalRecordCount(totCnt);
        model.addAttribute("resultCnt", totCnt);
        model.addAttribute("resultList", resultList);
        model.addAttribute("tobCdeList", tobCdeList);
        model.addAttribute("paginationInfo", paginationInfo);
        model.addAttribute("searchVo", vo);

        return "res/mng/us/vusr/LayerPopMngUsVusrP010";
    }

    /**
     * @MethodDESC : 우편번호 검색
     */
    @RequestMapping(value = "MngUsVusrP020.do")
    public String selectPostCodeCompanyList(@RequestParam(defaultValue = "1") int pageIndex,@ModelAttribute("UngisAppPostCodeVO") UngisAppPostCodeVO vo, ModelMap model,
                                            HttpServletRequest request)
            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());

        if(vo.getBdstNm()==null){
            vo.setBdstNm("");
        }

        if(vo.getGunguNm()==null){
            vo.setGunguNm("");
        }

        if(vo.getCtpvNm()==null){
            vo.setCtpvNm("");
        }

        int totCnt = ungisAppPostCodeService.countCodeList(vo);
        paginationInfo.setTotalRecordCount(totCnt);
        List resultList = ungisAppPostCodeService.selectPostCodeList(vo);
        model.addAttribute("resultCnt", totCnt);
        model.addAttribute("resultList", resultList);
        model.addAttribute("paginationInfo", paginationInfo);
        model.addAttribute("searchVo", vo);
        return "res/mng/us/vusr/LayerPopMngUsVusrP020";
    }
}
