package egovframework.service.impl;

import egovframework.service.AdminService;
import egovframework.service.mapper.AdminMapper;
import egovframework.util.CommonPath;
import egovframework.util.PageCriteria;
import egovframework.util.PageMaker;
import egovframework.util.SHA256;
import egovframework.vo.AdminVO;
import egovframework.vo.PopupVO;
import egovframework.vo.StatsVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
@RequiredArgsConstructor
@Service
public class AdminServiceImpl extends EgovAbstractServiceImpl implements AdminService {
    private final NoticeServiceImpl adminNoticeService;
    private final AdminMapper adminMapper;
    private final String ATTACH_FILE_PATH = CommonPath.getFilePath();
    private final String IMAGE_FILE_PATH   = CommonPath.getImageUploadPath();
    private PageCriteria criteria;
    private final String[] fileExtArray = {"xls", "xlsx", "doc", "docx",
            "ppt", "pptx", "csv", "txt", "hwp", "pdf", "ai", "psd", "zip"};

    @Override
    public AdminVO getUser(String id) {
        return this.adminMapper.getUser(id);
    }

    @Override
    public Map<String, Object> getPopupList(Map<String, Object> paramMap, PageCriteria criteria) {
        int page = 1;
        String searchText = "";
        String searchType = "";

        if (paramMap.get("page") != null) {
            page = Integer.parseInt((String)paramMap.get("page"));
        }

        if (paramMap.get("searchText") != null) {
            searchText = (String)paramMap.get("searchText");
        }

        if (paramMap.get("searchText") != null) {
            searchType = (String)paramMap.get("searchType");
        }

        criteria.setPage(page);
        criteria.setSearchText(searchText);
        criteria.setSearchType(searchType);

        PageMaker pageMaker = new PageMaker(page, this.adminMapper.getPopupTotalCount());

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("popupList", this.adminMapper.getPopupList(criteria));
        resultMap.put("pageMaker", pageMaker);
        return resultMap;
    }

    @Override
    public PopupVO getPopup(Map<String, Object> paramMap) {
        return this.adminMapper.getPopup(paramMap);
    }

    @Override
    public void insertPopup(Map<String, Object> paramMap) {
        this.adminMapper.insertPopup(paramMap);
    }

    @Override
    public int updatePopupUseYN(Map<String, Object> paramMap) {
        return this.adminMapper.updatePopupUseYN(paramMap);
    }

    @Override
    public int deletePopup(Map<String, Object> paramMap) {
        PopupVO popupVo = this.adminMapper.getPopup(paramMap);
        String imgFileName = popupVo.getImg_id();

        if (!"".equals(imgFileName) && imgFileName != null) {
            String imguploadPath = IMAGE_FILE_PATH;
            File tempImgFile = new File(imguploadPath, imgFileName);
            tempImgFile.setExecutable(false, true);
            tempImgFile.setReadable(true);
            tempImgFile.setWritable(false, true);
            if (tempImgFile.exists()) {
                tempImgFile.delete();
            }
        }
        return this.adminMapper.deletePopup(paramMap);
    }

    @Override
    public int updatePopup(Map<String, Object> paramMap, MultipartFile file) {

        PopupVO vo = this.adminMapper.getPopup(paramMap);
        boolean isWriteSuccess = true;
        String fileUuid = "";
        String fileName = "";

        if (vo.getImg_name() != null && vo.getImg_name().equals(paramMap.get("img_name"))) {
            fileUuid = vo.getImg_id();
            fileName =  vo.getImg_name();
        }
        else {
            Map<String, Object> resultMap = this.adminNoticeService.uploadFiles(file, true);
            isWriteSuccess = (Boolean) resultMap.get("isWriteSuccess");
            fileUuid = (String) resultMap.get("fileId");
            fileName = (String) resultMap.get("fileName");
        }
        if (isWriteSuccess) {
            paramMap.put("imgId", fileUuid);
            paramMap.put("imgName", fileName);
        }
        return this.adminMapper.updatePopup(paramMap);
    }

    @Override
    public Map<String, Object> checkPrePw(Map<String, Object> paramMap) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("code", "F");
        resultMap.put("message", "입력하신 정보를 확인해주세요.");
        if (paramMap != null) {
            if (paramMap.get("originPwd") == null) {
                resultMap.put("message", "기존 비밀번호를 입력해주세요.");
                return resultMap;
            }
            if (paramMap.get("newPwd") == null) {
                resultMap.put("message", "신규 비밀번호를 입력해주세요.");
                return resultMap;
            }
            if (paramMap.get("checkPwd") == null) {
                resultMap.put("message", "비밀번호 확인란을 입력해주세요.");
                return resultMap;
            }

            String originPwd = (String)paramMap.get("originPwd");
            String newPwd    = (String)paramMap.get("newPwd");
            String checkPwd  = (String)paramMap.get("checkPwd");

            if (originPwd.equals(newPwd)) {
                resultMap.put("message", "기존 비밀번호와 신규 비밀번호를 다르게 입력해주세요.");
                return resultMap;
            }

            if (!newPwd.equals(checkPwd)) {
                resultMap.put("message", "신규 비밀번호를 확인란과 동일하게 입력해주세요.");
                return resultMap;
            }

            String encryptPwd = SHA256.encrypt(originPwd);
            paramMap.put("prePw", encryptPwd);

            if (this.adminMapper.checkPrePw(paramMap) == null) {
                resultMap.put("message", "비밀번호가 일치하지 않습니다. 입력된 정보를 확인해주세요.");
                return resultMap;
            }
            paramMap.put("pwd", SHA256.encrypt(newPwd));
            int effectedRows = this.adminMapper.updatePw(paramMap);

            if (effectedRows > 0) {
                resultMap.put("message", "비밀번호 변경이 완료되었습니다.");
                resultMap.put("code", "S");
                return resultMap;
            }
            resultMap.put("message", "비밀번호 변경이 완료되지 않았습니다. 다시 시도해 주세요");
        }
        return resultMap;
    }

    @Override
    public List<StatsVO> getDDStatus(Map<String, Object> paramMap) {
        List<StatsVO> statsArr = this.adminMapper.getDDStatus(paramMap);
        return getStatus(statsArr, 31, false);
    }

    @Override
    public List<StatsVO> getHHStatus(Map<String, Object> paramMap) {
        List<StatsVO> statsArr = this.adminMapper.getHHStatus(paramMap);
        return getStatus(statsArr, 24, true);
    }

    @Override
    public List<StatsVO> getMMStatus(Map<String, Object> paramMap) {
        List<StatsVO> statsArr = this.adminMapper.getMMStatus(paramMap);
        return getStatus(statsArr, 12, false);
    }

    public List<StatsVO> getStatus(List<StatsVO> statsArr, int arrayLength, boolean isHour) {
        for (StatsVO vo : statsArr) {

            int[] formatArray = new int[arrayLength];
            Arrays.fill(formatArray, 0);
            if (vo.getConnCnt() != null) {
                String[] statsData = vo.getDt().split(",");
                String[] connCnt   = vo.getConnCnt().split(",");
                if (vo.getConnCnt() != null) {
                    for (int ii = 0; ii < statsData.length; ii++) {
                        int dyNum = Integer.parseInt(statsData[ii]);
                        if (isHour == false) {
                            --dyNum;
                        }
                        formatArray[dyNum] = Integer.parseInt(connCnt[ii]);
                    }
                }
            }
            vo.setStatsInArr(formatArray);
        }
        return statsArr;
    }

    @Override
    public void adminLoginMake(Map<String, Object> paramMap) {
        this.adminMapper.adminLoginMake(paramMap);
    }

    @Override
    public void adminLogoutMake(Map<String, Object> paramMap) {
        this.adminMapper.adminLogoutMake(paramMap);
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public Map<String, Object> loginCheck(Map<String, Object> paramMap, HttpSession session) {
        Map<String,Object> resultMap = new HashMap<>();
        AdminVO userInfo = adminMapper.getUser(paramMap.get("email").toString());
        if (userInfo != null) {
            String pw = SHA256.encrypt(paramMap.get("password").toString()); // 원본
            if (userInfo.getIs_account_lock() != null && userInfo.getIs_account_lock().equals("Y") ) {
                log.error("Login Failed : {}, Already Lock State", paramMap.get("email"));
                resultMap.put("msg", "3회 이상 로그인 실패로 계정 이용 불가\n관리자에게 문의하세요.");
            }
            else if (userInfo.getPassword() != null && userInfo.getPassword().equals(pw)) {
                //로그인성공
                String id = userInfo.getEmail();
                session.setAttribute("userId", id);
                adminMapper.adminLoginMake(null);
                resultMap.put("code", "S");
                paramMap.put("count", 0);
                adminMapper.setFailCount(paramMap);
                log.info("Login User : {}, Time : {}", id, getSysTime());
            }
            else {
                Map<String,Object> failCountMap = adminMapper.getFailCount(paramMap);
                int count;
                if (failCountMap == null) {
                    count = 0;
                }
                else {
                    count =  Integer.parseInt(String.valueOf(failCountMap.get("LOGIN_FAIL_COUNT")));
                }
                paramMap.put("count", ++count);
                adminMapper.setFailCount(paramMap);
                if (count > 2) {
                    adminMapper.setAcountLock(paramMap);
                    log.error("Login Failed, 3 Count Over Then Locking Your ID : {}", paramMap.get("email"));
                    resultMap.put("msg", "3회 이상 로그인 실패로 계정 이용 불가\n관리자에게 문의하세요");
                }
                else {
                    log.error("Login Failed, Please Check Your Login Information, ID : {}", paramMap.get("email"));
                    //로그인 실패
                    resultMap.put("msg", "정보입력 " + count + " 회 오류");
                }
                resultMap.put("code", "F");
            }
        }
        else {
            log.error("Login Failed, Please Check Your Login Information, ID : {}", paramMap.get("email"));
            resultMap.put("code", "F");
            resultMap.put("msg", "입력하신 정보를 다시 확인해주세요.");
        }
        return resultMap;
    }

    public String getSysTime() {
        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date dtLog = new Date();
        return sdfDate.format(dtLog);
    }

}
