package incheon.sgp.por.web;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.egovframe.rte.fdl.cryptography.EgovCryptoService;
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import incheon.ags.por.service.PorBoardFileService;
import incheon.ags.por.service.PorBoardService;
import incheon.ags.por.util.PorFileUtils;
import incheon.ags.por.vo.PorBoardFileVO;
import incheon.ags.por.vo.PorBoardVO;
import incheon.ags.por.vo.PorFileVO;
import incheon.com.cmm.EgovWebUtil;
import incheon.com.cmm.api.DefaultApiResponse;
import incheon.com.cmm.service.EgovFileMngService;
import incheon.com.cmm.service.FileVO;
import lombok.RequiredArgsConstructor;

/**
 * @ClassName : PorController.java
 * @Description : 공간정보포털 컨트롤러
 *
 * @author : 관리자
 * @since : 2025. 07. 17
 * @version : 1.0
 *
 *          <pre>
 * << 개정이력(Modification Information) >>
 *
 *   수정일              수정자               수정내용
 *  -------------  ------------   ---------------------
 *   2023. 10. 10    관리자               최초 생성
 *   2024. 12. 19    관리자               패널 기반 플랫폼으로 전면 개편
 *   2025. 07. 17    관리자               공간정보포털로 전환
 *          </pre>
 *
 */
@Controller("PorSgpBoardController")
@RequestMapping("/sgp/por")
@RequiredArgsConstructor
public class PorBoardController {
	
	private final PorBoardService porBoardService;
	private final PorBoardFileService porBoardFileService;
	
	@Resource(name = "EgovFileMngService")
	private EgovFileMngService fileService;
	
	final int NOTICE_RECORD_COUNT_PER_PAGE = 9;
	final int FAQ_RECORD_COUNT_PER_PAGE = 5;
	final int ARCHIVE_RECORD_COUNT_PER_PAGE = 9;
	final int GUIDE_RECORD_COUNT_PER_PAGE = 9;
	
	/**
     * 공지사항 화면
     * @param model
     * @return JSP 페이지
     * @exception Exception
     */
    @GetMapping("/notice/list.do")
    public String noticeList(
    		@RequestParam(defaultValue = "1") int page
    		, @ModelAttribute PorBoardVO porBoardVO
    		, ModelMap model
		) throws Exception {
    	
    	porBoardVO.setPstKndCd("BBS001");
    	porBoardVO.setPrvtYn(false);
    	
    	int totalCount = porBoardService.selectBoardListCount(porBoardVO);
    	
    	// 페이징정보
    	PaginationInfo paginationInfo = new PaginationInfo();
    	paginationInfo.setTotalRecordCount(totalCount);
    	paginationInfo.setCurrentPageNo(page);
    	// paginationInfo.setRecordCountPerPage(porBoardVO.getRecordCountPerPage());
    	paginationInfo.setRecordCountPerPage(NOTICE_RECORD_COUNT_PER_PAGE);
    	paginationInfo.setPageSize(porBoardVO.getPageSize());

    	porBoardVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
    	porBoardVO.setLastIndex(paginationInfo.getLastRecordIndex());
    	porBoardVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());
    	
    	// 실데이터 조회
    	List<PorBoardVO> boardList = porBoardService.selectBoardList(porBoardVO);
    	
    	model.addAttribute("boardList", boardList);
    	model.addAttribute("paginationInfo", paginationInfo);
    	
    	return "sgp/por/notice/list";
    }

    /**
     * 공지사항 상세 화면
     * @param model
     * @return JSP 페이지
     * @exception Exception
     */
    @GetMapping("/notice/view.do")
    public String noticeView(
    		@ModelAttribute PorBoardVO porBoardVO
    		, ModelMap model
    	) throws Exception {
    	
    	// 데이터 호출
    	PorBoardVO resultVO = porBoardService.selectBoardDetail(porBoardVO);
    	
    	if(resultVO != null) {
    		// 파일 호출
    		PorBoardFileVO fVo = new PorBoardFileVO();
    		fVo.setBbsUnqKey(porBoardVO.getUnqKey());
    		List<PorFileVO> fileList = porBoardFileService.selectBoardFileList(fVo);
    		if(fileList != null && fileList.size() > 0) {
				// 이미지, 일반 파일의 분배(이미지는 IMG로 화면에 출력)
				/*Map<String, Object> fileMap = porBoardFileService.distributeFileList(fileList);
				resultVO.setImgList((List<FileVO>) fileMap.get("imgList"));
				resultVO.setFileList((List<FileVO>) fileMap.get("fileList"));*/
    			resultVO.setPorFileList(fileList);
			}
			resultVO.setPageIndex(porBoardVO.getPageIndex());
    		
    		model.addAttribute("porBoardVO", resultVO);
    		return "sgp/por/notice/view";
    	}else {
    		return "error/error";
    	}
    	
    }
    
    /**
     * 자료실 화면
     * @param model
     * @return JSP 페이지
     * @exception Exception
     */
    @GetMapping("/archive/list.do")
    public String archiveList(
    		@RequestParam(defaultValue = "1") int page
    		, @ModelAttribute PorBoardVO porBoardVO
    		, ModelMap model
    		) throws Exception {
    	
    	porBoardVO.setPstKndCd("BBS002");
    	porBoardVO.setPrvtYn(false);
    	
    	int totalCount = porBoardService.selectBoardListCount(porBoardVO);
    	
    	// 페이징정보
    	PaginationInfo paginationInfo = new PaginationInfo();
    	paginationInfo.setTotalRecordCount(totalCount);
    	paginationInfo.setCurrentPageNo(page);
    	paginationInfo.setRecordCountPerPage(ARCHIVE_RECORD_COUNT_PER_PAGE);
    	paginationInfo.setPageSize(porBoardVO.getPageSize());
    	
    	porBoardVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
    	porBoardVO.setLastIndex(paginationInfo.getLastRecordIndex());
    	porBoardVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());
    	
    	// 실데이터 조회
    	List<PorBoardVO> boardList = porBoardService.selectBoardList(porBoardVO);
    	
    	model.addAttribute("boardList", boardList);
    	model.addAttribute("paginationInfo", paginationInfo);
    	
    	return "sgp/por/archive/list";
    }
    
    /**
     * 자료실 상세 화면
     * @param model
     * @return JSP 페이지
     * @exception Exception
     */
    @GetMapping("/archive/view.do")
    public String archiveView(
    		@ModelAttribute PorBoardVO porBoardVO
    		, ModelMap model
    		) throws Exception {
    	
    	// 데이터 호출
    	PorBoardVO resultVO = porBoardService.selectBoardDetail(porBoardVO);
    	
    	if(resultVO != null) {
    		// 파일 호출
    		PorBoardFileVO fVo = new PorBoardFileVO();
    		fVo.setBbsUnqKey(porBoardVO.getUnqKey());
    		List<PorFileVO> fileList = porBoardFileService.selectBoardFileList(fVo);
    		if(fileList != null && fileList.size() > 0) {
    			resultVO.setPorFileList(fileList);
    		}
    		resultVO.setPageIndex(porBoardVO.getPageIndex());
    		
    		model.addAttribute("porBoardVO", resultVO);
    		return "sgp/por/archive/view";
    	}else {
    		return "error/error";
    	}
    	
    }
    
    
    /**
     * FAQ 화면
     * @param model
     * @return JSP 페이지
     * @exception Exception
     */
    @GetMapping("/faq/list.do")
    public String faqList(
    		@RequestParam(defaultValue = "1") int page
    		, @ModelAttribute PorBoardVO porBoardVO
    		, ModelMap model
    		) throws Exception {
    	
    	porBoardVO.setPstKndCd("BBS003");
    	porBoardVO.setPrvtYn(false);
    	
    	int totalCount = porBoardService.selectBoardListCount(porBoardVO);
    	
    	// 페이징정보
    	PaginationInfo paginationInfo = new PaginationInfo();
    	paginationInfo.setTotalRecordCount(totalCount);
    	paginationInfo.setCurrentPageNo(page);
    	paginationInfo.setRecordCountPerPage(FAQ_RECORD_COUNT_PER_PAGE);
    	paginationInfo.setPageSize(porBoardVO.getPageSize());
    	
    	porBoardVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
    	porBoardVO.setLastIndex(paginationInfo.getLastRecordIndex());
    	porBoardVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());
    	
    	// 실데이터 조회
    	List<PorBoardVO> boardList = porBoardService.selectBoardList(porBoardVO);
    	
    	// 파일정보 호출
    	if(boardList != null && boardList.size() > 0) {
    		boardList.forEach(board -> {
    			PorBoardFileVO fVo = new PorBoardFileVO();
    			fVo.setBbsUnqKey(board.getUnqKey());
    			List<PorFileVO> fileList = null;
    			try {
					fileList = porBoardFileService.selectBoardFileList(fVo);
					if(fileList != null && fileList.size() > 0) {
						Map<String, Object> fileMap = porBoardFileService.distributeFileList(fileList);
						board.setImgList((List<FileVO>) fileMap.get("imgList"));
						board.setPorFileList(fileList);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
    		});
    	}
    	
    	model.addAttribute("boardList", boardList);
    	model.addAttribute("paginationInfo", paginationInfo);
    	
    	return "sgp/por/faq/list";
    }
    
    /**
     * 서비스 길라잡이 화면
     * @param model
     * @return JSP 페이지
     * @exception Exception
     */
    @GetMapping("/guide/list.do")
    public String guideList(
    		@RequestParam(defaultValue = "1") int page
    		, @ModelAttribute PorBoardVO porBoardVO
    		, ModelMap model
    		) throws Exception {
    	
    	porBoardVO.setPstKndCd("BBS006");
    	porBoardVO.setPrvtYn(false);
    	
    	int totalCount = porBoardService.selectBoardListCount(porBoardVO);
    	
    	// 페이징정보
    	PaginationInfo paginationInfo = new PaginationInfo();
    	paginationInfo.setTotalRecordCount(totalCount);
    	paginationInfo.setCurrentPageNo(page);
    	paginationInfo.setRecordCountPerPage(GUIDE_RECORD_COUNT_PER_PAGE);
    	paginationInfo.setPageSize(porBoardVO.getPageSize());
    	
    	porBoardVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
    	porBoardVO.setLastIndex(paginationInfo.getLastRecordIndex());
    	porBoardVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());
    	
    	// 실데이터 조회
    	List<PorBoardVO> boardList = porBoardService.selectBoardList(porBoardVO);
    	
    	model.addAttribute("boardList", boardList);
    	model.addAttribute("paginationInfo", paginationInfo);
    	
    	return "sgp/por/guide/list";
    }
    
    /**
     * 서비스 길라잡이 상세 화면
     * @param model
     * @return JSP 페이지
     * @exception Exception
     */
    @GetMapping("/guide/view.do")
    public String guideView(
    		@ModelAttribute PorBoardVO porBoardVO
    		, ModelMap model
    		) throws Exception {
    	
    	// 데이터 호출
    	PorBoardVO resultVO = porBoardService.selectBoardDetail(porBoardVO);
    	
    	if(resultVO != null) {
    		// 파일 호출
    		PorBoardFileVO fVo = new PorBoardFileVO();
    		fVo.setBbsUnqKey(porBoardVO.getUnqKey());
    		List<PorFileVO> fileList = porBoardFileService.selectBoardFileList(fVo);
    		if(fileList != null && fileList.size() > 0) {
    			resultVO.setPorFileList(fileList);
    		}
    		resultVO.setPageIndex(porBoardVO.getPageIndex());
    		
    		model.addAttribute("porBoardVO", resultVO);
    		return "sgp/por/guide/view";
    	}else {
    		return "error/error";
    	}
    	
    }
    
	@GetMapping(value = "/file.do")
	public void file(
			@ModelAttribute PorFileVO porFileVO
			, HttpServletRequest request
			, HttpServletResponse response) throws Exception {
		

		try {
			PorFileVO vo = porBoardFileService.selectBoardFile(porFileVO);
			if (vo == null) {
				throw new FileNotFoundException("파일 정보를 찾을 수 없습니다.");
			}

			String fileStreCours = EgovWebUtil.filePathBlackList(vo.getAtchFilePathNm());
			String streFileNm = EgovWebUtil.filePathBlackList(vo.getSrvrAtchFileNm());

			File uFile = new File(fileStreCours, streFileNm);
			long fSize = uFile.length();

			if (fSize > 0) {
				String mimetype = "application/x-stuff";

				response.setContentType(mimetype);
				setDisposition(vo.getOrgnlAtchFileNm(), request, response);

				try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(uFile));
					 BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream())) {
					FileCopyUtils.copy(in, out);
					out.flush();
				} catch (FileNotFoundException ex) {
				}
			} else {
				throw new FileNotFoundException("파일이 존재하지 않거나 크기가 0입니다.");
			}

		} catch (IllegalArgumentException e) {
			// Base64 디코딩 실패 등
			throw new FileNotFoundException("잘못된 atchFileId 인코딩입니다.");
		} catch (Exception e) {
			throw e;
		}
	}
	
	/**
	 * Disposition 지정하기.
	 *
	 * @param filename
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	private void setDisposition(String filename, HttpServletRequest request, HttpServletResponse response)
		throws Exception {
		String browser = getBrowser(request);

		String dispositionPrefix = "attachment; filename=";
		String encodedFilename = null;

		if (browser.equals("MSIE")) {
			encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
		} else if (browser.equals("Trident")) { // IE11 문자열 깨짐 방지
			encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
		} else if (browser.equals("Firefox")) {
			encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
		} else if (browser.equals("Opera")) {
			encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
		} else if (browser.equals("Chrome")) {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < filename.length(); i++) {
				char c = filename.charAt(i);
				if (c > '~') {
					sb.append(URLEncoder.encode("" + c, "UTF-8"));
				} else {
					sb.append(c);
				}
			}
			encodedFilename = sb.toString();
		} else {
			//throw new RuntimeException("Not supported browser");
			throw new IOException("Not supported browser");
		}

		response.setHeader("Content-Disposition", dispositionPrefix + encodedFilename);

		if ("Opera".equals(browser)) {
			response.setContentType("application/octet-stream;charset=UTF-8");
		}
	}
	
	private String getBrowser(HttpServletRequest request) {
		String header = request.getHeader("User-Agent");
		if (header.indexOf("MSIE") > -1) {
			return "MSIE";
		} else if (header.indexOf("Trident") > -1) { // IE11 문자열 깨짐 방지
			return "Trident";
		} else if (header.indexOf("Chrome") > -1) {
			return "Chrome";
		} else if (header.indexOf("Opera") > -1) {
			return "Opera";
		}
		return "Firefox";
	}
}