package egovframework.controller;

import egovframework.service.impl.AdminServiceImpl;
import egovframework.service.impl.NoticeServiceImpl;
import egovframework.util.CommonPath;
import egovframework.util.PageCriteria;
import egovframework.vo.NoticeVO;
import egovframework.vo.StatsVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.text.NumberFormat;
import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Controller
@RequestMapping("/admin")
public class AdminController {

    private final AdminServiceImpl adminService;
    private final NoticeServiceImpl adminNoticeService;
    private final String IMAGE_FILE_PATH   = CommonPath.getImageUploadPath();
    private PageCriteria criteria;

    @PostConstruct
    void init() {
        this.criteria = new PageCriteria();
    }

    @RequestMapping(value = "/index.do", method = RequestMethod.GET)
    public String index(Model model, HttpServletRequest request, HttpServletResponse response) {
        model.addAttribute("siteSubInfo", "subWrap");
        if (request.getSession().getAttribute("userId") != null) {
            return "redirect:/admin/noticeList.do";
        }
        model.addAttribute("subTitle", "로그인");
        return "admin/index.tiles";
    }

    @ResponseBody
    @RequestMapping(value = "/login.do", method = RequestMethod.POST,	produces = {"application/json; charset=utf8"})
    public Map<String,Object> login(Model model, @RequestBody Map<String,Object> paramMap, HttpSession session){
        model.addAttribute("siteSubInfo", "subWrap");
        Map<String, Object> resultMap = adminService.loginCheck(paramMap, session);
        return resultMap;
    }

    @RequestMapping(value = "/logout.do", method = RequestMethod.GET)
    public String logout(Model model, HttpServletRequest request, HttpServletResponse response, HttpSession session) {
        model.addAttribute("siteSubInfo", "subWrap");
        if (session.getAttribute("userId") != null) {
            log.info("Logout User : {}, Time : {}", session.getAttribute("userId"), adminService.getSysTime());
            this.adminService.adminLogoutMake(null);
            session.removeAttribute("userId");
        }
        return "redirect:/admin/index.do";
    }

    @RequestMapping(value = "/updateAdminInfo.do", method = RequestMethod.GET)
    public String pwChange(Model model, HttpServletRequest request) {
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("subTitle", "관리자 정보변경");
        model.addAttribute("id", request.getSession().getAttribute("userId"));
        return "admin/adminInfo.tiles";
    }

    @RequestMapping(value = {"/popupList.do", "/popupList/{page}.do"}, method = RequestMethod.GET)
    public String popup(Model model,  @PathVariable(required = false) String page,
                        @Param("searchText") String searchText, @Param("SearchType") String searchType) {
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("page", page);
        paramMap.put("searchText", searchText);
        paramMap.put("searchType", searchType);
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("subTitle", "팝업창 관리");
        Map<String, Object> resultMap= this.adminService.getPopupList(paramMap, this.criteria);

        model.addAttribute("popupList", resultMap.get("popupList"));
        model.addAttribute("pageMaker", resultMap.get("pageMaker"));
        model.addAttribute("searchText", searchText);
        model.addAttribute("searchType", searchType);

        return "admin/popupList.tiles";
    }

    @RequestMapping(value = {"/writePopup.do"}, method = RequestMethod.GET)
    public String popup(Model model) {
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("subTitle", "팝업창 관리");
        return "admin/popupWrite.tiles";
    }


    @RequestMapping(value = {"/noticeList.do", "/noticeList/{page}.do"}, method = RequestMethod.GET)
    public String getNoticeList(Model model, @PathVariable(required = false) String page, @RequestParam HashMap<String, String> paramMap) {
        paramMap.put("boardId", "1");
        paramMap.put("page", page);
        Map<String, Object> resultMap = adminNoticeService.selectBoardList(paramMap, this.criteria);
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("subTitle", "공지사항 관리");
        model.addAttribute("noticeList", resultMap.get("noticeList"));
        model.addAttribute("pageMaker", resultMap.get("pageMaker"));
        model.addAttribute("searchText", paramMap.get("searchText"));
        model.addAttribute("searchType", paramMap.get("searchType"));
        return "admin/noticeList.tiles";
    }

    @RequestMapping(value = "/noticeView/{boardNo}.do", method = RequestMethod.GET)
    public String view(Model model, @PathVariable HashMap<String, String> paramMap,
                       @Param("searchText") String searchText, @Param("searchType") String searchType) {
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("subTitle", "공지사항 관리");
        paramMap.put("boardId", "1");
        this.adminNoticeService.updateNoticeReadCount(paramMap);
        paramMap.put("searchText", searchText);
        paramMap.put("searchType", searchType);
        NoticeVO result = this.adminNoticeService.selectBoardView(paramMap);
        model.addAttribute("notice", result);
        model.addAttribute("searchText", searchText);
        model.addAttribute("searchType", searchType);
        return "admin/noticeDetail.tiles";
    }

    @RequestMapping(value = "/noticeWrite.do", method = RequestMethod.GET)
    public String write(Model model) {
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("subTitle", "공지사항 글쓰기");
        return "admin/noticeWrite.tiles";
    }

    @RequestMapping(value = "/insertNotice.do", method = RequestMethod.POST)
    public String insertNotice(HttpServletRequest request,
                               @RequestParam List<MultipartFile> attachFile,
                               @RequestParam Map<String, String> paramMap) {
        paramMap.put("boardId", "1");
        String userId = (String)request.getSession().getAttribute("userId");
        this.adminNoticeService.insertBoard(attachFile, userId, paramMap);
        return "redirect:/admin/noticeList.do";
    }

    @RequestMapping(value = "/deleteNotice/{boardNo}.do", method = RequestMethod.GET)
    public String noticeDelete(Model model, @PathVariable HashMap<String, Object> paramMap) {
        paramMap.put("boardId", "1");
        this.adminNoticeService.deleteNotice(paramMap);
        return "redirect:/admin/noticeList.do";
    }

    @RequestMapping(value = "/editNotice/{boardNo}.do", method = RequestMethod.GET)
    public String noticeEdit(Model model, @PathVariable HashMap<String, String> paramMap) {
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("subTitle", "공지사항 수정");
        paramMap.put("boardId", "1");
        model.addAttribute("noticeEdit", this.adminNoticeService.selectBoardView(paramMap));
        return "admin/noticeEdit.tiles";
    }

    @RequestMapping(value = "/updateNotice.do", method = RequestMethod.POST)
    public String updateNotice(Model model, HttpServletRequest request, HttpServletResponse response,
                               @RequestParam Map<String, String> paramMap,
                               @RequestParam List<MultipartFile> attachFile,
                               @RequestParam List<String> attachFileName) {
        model.addAttribute("siteSubInfo", "subWrap");
        paramMap.put("boardId", "1");
        this.adminNoticeService.updateBoard(attachFile, paramMap, attachFileName);
        if (request.getParameter("boardNo") != null) {
            String boardNo = request.getParameter("boardNo");
            return "redirect:/admin/noticeView/" + boardNo + ".do";
        }
        else {
            return "redirect:/admin/noticeList.do";
        }
    }

    @RequestMapping(value = "/editPopup/{popupId}.do", method = RequestMethod.GET)
    public String editPopup(Model model, @PathVariable String popupId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("popupId", popupId);
        model.addAttribute("subTitle", "팝업창 관리");
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("popup", this.adminService.getPopup(paramMap));
        return "admin/popupEdit.tiles";
    }

    @RequestMapping(value = "/popupDetail/{popupId}.do", method = RequestMethod.GET)
    public String popupDetail(Model model, @PathVariable String popupId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("popupId", popupId);
        model.addAttribute("subTitle", "팝업창 관리");
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("popup", this.adminService.getPopup(paramMap));
        return "admin/popupDetail.tiles";
    }

    @RequestMapping(value = "/popupInsert.do", method = RequestMethod.POST)
    public String popupInsert(Model model, HttpServletRequest request, HttpServletResponse response,
                              @RequestParam("popupImg") MultipartFile file,
                              @RequestParam Map<String, Object> paramMap) {
        Map<String, Object> resultMap = this.adminNoticeService.uploadFiles(file, true);
        Boolean isWriteSuccess = (Boolean) resultMap.get("isWriteSuccess");
        String fileUuid = (String) resultMap.get("fileId");
        String fileName = (String) resultMap.get("fileName");

        if (isWriteSuccess) {
            paramMap.put("postFrom", paramMap.get("postFrom").toString().replace("-", ""));
            paramMap.put("postTo", paramMap.get("postTo").toString().replace("-", ""));
            paramMap.put("imgId", fileUuid);
            paramMap.put("imgName", fileName);

            this.adminService.insertPopup(paramMap);
        }

        return "redirect:/admin/popupList.do";
    }

    @RequestMapping(value = "/updatePopupUseYN.do", method = RequestMethod.POST)
    @ResponseBody
    public int updatePopupUseYN(Model model, @RequestParam Map<String, Object> paramMap) {
        return this.adminService.updatePopupUseYN(paramMap);
    }

    @RequestMapping(value = "/deletePopup.do", method = RequestMethod.POST)
    @ResponseBody
    public int removePopup(Model model, HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
        return this.adminService.deletePopup(paramMap);
    }

    @RequestMapping(value = "/updatePopup.do", method = RequestMethod.POST)
    public String updatePopup(Model model, HttpServletRequest request, @RequestParam Map<String, Object> paramMap,
                              @RequestParam("popupImg") MultipartFile file) {
        this.adminService.updatePopup(paramMap, file);
        return "redirect:/admin/popupList.do";
    }

    @ResponseBody
    @RequestMapping(value = "/checkPrePw.do", method = RequestMethod.POST)
    public Map<String, Object> checkPrePw(@RequestParam Map<String, Object> paramMap, HttpSession session) {
        String userId = (String) session.getAttribute("userId");
        paramMap.put("id", userId);
        return this.adminService.checkPrePw(paramMap);
    }

    @RequestMapping(value = "/status.do", method = RequestMethod.GET)
    public String stats(Model model, HttpServletRequest request, HttpServletResponse response) {
        model.addAttribute("siteSubInfo", "subWrap");
        model.addAttribute("subTitle", "접속통계");
        NumberFormat nf = NumberFormat.getInstance();
        nf.setMinimumIntegerDigits(2);

        Calendar cal = Calendar.getInstance();

        model.addAttribute("thisYear", Integer.toString(cal.get(Calendar.YEAR)));
        model.addAttribute("thisMonth", nf.format(cal.get(Calendar.MONTH) + 1));
        model.addAttribute("thisDate", nf.format(cal.get(Calendar.DATE)));
        model.addAttribute("lastDate", "31");
        model.addAttribute("thisHour", nf.format(cal.get(Calendar.HOUR_OF_DAY)));
        return "admin/statistics.tiles";
    }

    @RequestMapping(value = "/getStatsList.do", method = RequestMethod.POST)
    public @ResponseBody List<StatsVO> getStatsList(@RequestParam Map<String, Object> paramMap) {
        List<StatsVO> result = null;
        if (paramMap.get("dateType") != null && paramMap.get("date") != null) {
            String dateType = (String)paramMap.get("dateType");
            String date     = (String)paramMap.get("date");
            switch (dateType) {
                case "hhStats":
                    paramMap.put("statDate", date);
                    result = this.adminService.getHHStatus(paramMap);
                    break;
                case "ddStats":
                    paramMap.put("statMonth", date);
                    result = this.adminService.getDDStatus(paramMap);
                    break;
                case "mnStats":
                    paramMap.put("statYear", date);
                    result = this.adminService.getMMStatus(paramMap);
                    break;
                default:
                    log.error("DateType is Unexpected value : {}", dateType);
                    //throw new IllegalStateException("DateType is Unexpected value: " + dateType);
            }
        }
        return result;
    }

    /* Naver editor 사진첨부하기 설정*/
    @RequestMapping(value = "/noticeImgupload.do", method = RequestMethod.POST)
    public @ResponseBody String noticeImgUpload(
            Model model,
            HttpServletRequest request,
            HttpServletResponse response
    ) {
        String sFileInfo = "";
        String filename = request.getHeader("file-name");

        String filePath = IMAGE_FILE_PATH;
        File file = new File(filePath);
        file.setExecutable(false, true);
        file.setReadable(true);
        file.setWritable(false, true);

        if (!file.exists()) {
            file.mkdirs();
        }

        String realFileNm;
        realFileNm = UUID.randomUUID().toString().replace("-", "") + filename.substring(filename.lastIndexOf("."));
        String rlFileNm = filePath + File.separator + realFileNm;
        InputStream is = null;
        OutputStream os = null;
        try{
            is = request.getInputStream();
            os = new FileOutputStream(rlFileNm);
            int numRead;
            byte b[] = new byte[Integer.parseInt(request.getHeader("file-size"))];
            if (is != null) {
                while ((numRead = is.read(b, 0, b.length)) != -1) {
                    os.write(b, 0, numRead);
                }
                is.close();
            }
            os.flush();
            os.close();
        } catch (IOException e) {
            log.error("noticeImgupload() IO Exception");
        }

        sFileInfo += "&bNewLine=true";
        sFileInfo += "&sFileName=" + filename;
        sFileInfo += "&sFileURL=" + "/upload/" + realFileNm;

        return sFileInfo;
    }

    @RequestMapping(value = "/noticeImguploadSingle.do", method = RequestMethod.POST)
    public String noticeImguploadSingle(
            Model model,
            HttpServletRequest request,
            HttpServletResponse response,
            @RequestParam("Filedata") MultipartFile file
    ) {

        String callback = request.getParameter("callback");
        String callbackFunc = request.getParameter("callback_func");

        File uploadFileHome = new File(IMAGE_FILE_PATH);
        uploadFileHome.setExecutable(false, true);
        uploadFileHome.setReadable(true);
        uploadFileHome.setWritable(false, true);

        String fileName;
        String fileUuid;
        String fileResult = "";
        fileName = file.getOriginalFilename();
        if (!"".equals(fileName) && fileName != null) {
            if (fileName.endsWith(".jsp") || fileName.endsWith(".js") || fileName.endsWith(".html") || fileName.endsWith(".htm")) {
                log.error("/admin/insertNotice.do, Check the file types....");
                fileResult = "&errstr=error";
            }
            else {
                String fileExe = fileName.substring(fileName.lastIndexOf("."));

                fileUuid = UUID.randomUUID().toString().replace("-", "") + fileExe;

                File uploadImgFile = new File(uploadFileHome, fileUuid);
                if (uploadImgFile != null) {
                    fileResult = "&bNewLine=true&sFileName=" + fileName + "&sFileURL=/upload/" + fileUuid;

                    try {
                        if (file.getSize() <= 200000000) {
                            file.transferTo(uploadImgFile);
                        } else {
                            log.error("/admin/noticeImguploadSingle.do, PopupImage is Too Large Size(Limit Size 200000000)");
                        }
                    } catch (IllegalStateException | IOException e) {
                        log.error("/admin/noticeImguploadSingle.do, can not transfetTo uploadImgFile...");
                    }
                }
            }
        } else{
            fileResult = "&errstr=error";
        }

        return "redirect:" + callback + "?callback_func=" + callbackFunc + fileResult;
    }

}