package incheon.ags.drm.web;

import incheon.ags.drm.service.DrmBbsService;
import incheon.ags.drm.vo.DrmBbsCmntVO;
import incheon.ags.drm.vo.DrmBbsVO;
import incheon.ags.mrb.analysis.web.SpatialAnalysisController;
import incheon.com.cmm.context.RequestContext;
import incheon.com.security.annotation.RequirePermission;
import incheon.com.security.util.SecurityUtil;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.RequiredArgsConstructor;
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/drm")
@RequiredArgsConstructor
public class DrmBbsController {

    private static final Logger logger = LoggerFactory.getLogger(SpatialAnalysisController.class);
    private final DrmBbsService drmBbsService;

    /* 게시판 이동 */
    @GetMapping("/showBbsPop.do")
    @RequirePermission(system = "DRM", permissions = "PERM_MENU_ACCESS")
    public String showBbsPop(@RequestParam Long id, ModelMap model) throws Exception {
        DrmBbsVO drmBbsVO = drmBbsService.selectBbsShp(id);
        model.addAttribute("result", drmBbsVO);

        boolean bbsPermission = false;
        // 공지사항
        if (id == 1 && SecurityUtil.hasRole("DRM", "ROLE_DRM_ADMIN")) { bbsPermission = true; }
        // 자료실
        else if (id == 2 && (SecurityUtil.hasRole("DRM", "ROLE_DRM_ADMIN") || SecurityUtil.hasRole("DRM", "ROLE_DRM_TASK"))) { bbsPermission = true; }
        // 질의응답
        else if (id == 3) { bbsPermission = true; }
        model.addAttribute("bbsPermission", bbsPermission);

        return "ags/drm/bbs/drmBbsManage";
    }

    /* 게시글 목록 조회 */
    @GetMapping("/bbsCttList.do")
    public ResponseEntity<Map<String, Object>> selectBbsCttList (
            @RequestParam(defaultValue = "1") int page,
            @RequestParam Long bbsShpId,
            @RequestParam(required = false) String searchBbscttTtl,
            @RequestParam(required = false) String sortKey,
            @RequestParam(required = false) String sortDirection
    ) {
        Map<String, Object> response = new HashMap<>();

        if (page < 1) {
            page = 1;
        }

        String safeSortDir = "DESC";
        if ("ASC".equalsIgnoreCase(sortDirection) || "DESC".equalsIgnoreCase(sortDirection)) {
            safeSortDir = sortDirection.toUpperCase();
        }

        try {
            DrmBbsVO drmBbsVO = new DrmBbsVO();
            drmBbsVO.setPageIndex(page);
            drmBbsVO.setBbsShpId(bbsShpId);
            drmBbsVO.setBbsCttTtl(searchBbscttTtl);
            drmBbsVO.setSortKey(sortKey);
            drmBbsVO.setSortDirection(sortDirection);
            drmBbsVO.setPageSize(5);

            PaginationInfo paginationInfo = new PaginationInfo();
            paginationInfo.setCurrentPageNo(page);
            paginationInfo.setRecordCountPerPage(drmBbsVO.getRecordCountPerPage());
            paginationInfo.setPageSize(drmBbsVO.getPageSize());

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

            List<DrmBbsVO> resultList = drmBbsService.selectBbsCttList(drmBbsVO);
            int totalCount = drmBbsService.selectBbsCttListCnt(drmBbsVO);

            if (resultList == null) {
                resultList = new ArrayList<>();
            }

            paginationInfo.setTotalRecordCount(totalCount);

            response.put("result", resultList);
            response.put("totalCount", totalCount);
            response.put("paginationInfo", paginationInfo);

            return ResponseEntity.ok(response);

        } catch (NullPointerException e) {
            logger.error("시스템 오류가 발생했습니다: {}", "데이터 처리 중 예기치 못한 참조 오류", e);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();

        } catch (Exception e) {
            logger.error("시스템 오류가 발생했습니다: {}", "게시글 목록 조회", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /* 게시글 등록 */
    @PostMapping("/bbsCttRegister.do")
    public ResponseEntity<Map<String, Object>> registerBbs (
            @RequestBody DrmBbsVO drmBbsVO,
            @RequestPart(value = "file", required = false) List<MultipartFile> attachedFiles
    ) {
        Map<String, Object> response = new HashMap<>();
        try {
            if (drmBbsVO.getBbsShpId() == null) {
                return ResponseEntity.badRequest().build();
            }

            if (drmBbsVO.getBbsCttTtl() == null || drmBbsVO.getBbsCttTtl().trim().isEmpty()) {
                response.put("message", "제목은 필수 항목입니다.");
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
            }

            if (attachedFiles != null && !attachedFiles.isEmpty()) {
                for (MultipartFile file : attachedFiles) {
                    if (file.getSize() > 100 * 1024 * 1024) {
                        response.put("message", "파일 용량이 초과되었습니다.");
                        return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE).body(response);
                    }
                }
            }

            drmBbsService.registerBbsCtt(drmBbsVO, attachedFiles);
            response.put("success", true);
            return ResponseEntity.ok(response);

        } catch (DataIntegrityViolationException e) {
            logger.warn("시스템 오류가 발생했습니다: {}", "데이터 제약조건 위반", e);
            response.put("message", "잘못된 데이터 요청입니다.");
            return ResponseEntity.status(HttpStatus.CONFLICT).body(response);

        } catch (Exception e) {
            logger.error("시스템 오류가 발생했습니다: {}", "게시글 등록", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /* 게시글 상세 조회 */
    @GetMapping("/bbsCttDetail.do")
    public ResponseEntity<Map<String, Object>> selectBbsCttDetail (@RequestParam Long bbsCttId) {
        Map<String, Object> response = new HashMap<>();
        try {
            if (bbsCttId == null || bbsCttId <= 0) {
                return ResponseEntity.badRequest().build();
            }
            DrmBbsVO resultVO = drmBbsService.selectBbsCttDetail(bbsCttId);

            if (resultVO == null) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
            }
            response.put("result", resultVO);
            response.put("userId", RequestContext.getCurrentUserId());
            return ResponseEntity.ok(response);

        } catch (DataAccessException e) {
            // SQL 오류나 DB 연결 문제 (Spring의 DB 관련 공통 예외)
            logger.error("시스템 오류가 발생했습니다: {}", "데이터베이스 접근 오류", e);
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build();

        } catch (NullPointerException e) {
            // 객체 참조 오류 (데이터 매핑 실패 등)
            logger.error("시스템 오류가 발생했습니다: {}", "데이터 처리 중 널 참조 발생", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();

        } catch (RuntimeException e) {
            // 그 외 예상치 못한 런타임 오류
            logger.error("시스템 오류가 발생했습니다: {}", "조회 중 알 수 없는 런타임 오류", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();

        } catch (Exception e) {
            logger.error("시스템 오류가 발생했습니다: {}", "게시글 상세 조회", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /* 게시글 댓글 등록 */
    @PostMapping("/bbsCmntRegister.do")
    public ResponseEntity<Map<String, Object>> registerBbsCmnt (@RequestBody DrmBbsCmntVO drmBbsCmntVO) {
        Map<String, Object> response = new HashMap<>();
        try {
            if (drmBbsCmntVO.getCmntCn() == null || drmBbsCmntVO.getCmntCn().trim().isEmpty()) {
                response.put("message", "댓글 내용은 필수 항목입니다.");
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
            }

            drmBbsService.registerBbsCmnt(drmBbsCmntVO);
            response.put("success", true);
            return ResponseEntity.ok(response);

        } catch (IllegalArgumentException e) {
            // 입력값이 잘못된 경우
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(Map.of("message", e));

        } catch (AccessDeniedException e) {
            // 권한이 없는 경우 (Spring Security 또는 커스텀 예외)
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("message", "수정 권한이 없습니다."));

        } catch (IOException e) {
            // 파일 업로드 중 발생하는 입출력 오류
            logger.error("파일 저장 중 오류 발생", e);
            return ResponseEntity.status(HttpStatus.INSUFFICIENT_STORAGE).build();

        } catch (DataIntegrityViolationException e) {
            // DB 제약 조건(Unique key, Not Null 등) 위반
            logger.error("데이터 제약조건 위반 오류", e);
            return ResponseEntity.status(HttpStatus.CONFLICT).build();

        } catch (Exception e) {
            logger.error("시스템 오류가 발생했습니다: {}", "게시글 댓글 등록", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /* 게시글 댓글 삭제 */
    @PostMapping("/bbsCmntDelete.do")
    public ResponseEntity<Map<String, Object>> deleteCmnt (@RequestParam Long cmntId) {
        Map<String, Object> response = new HashMap<>();
        try {
            if (cmntId == null) return ResponseEntity.badRequest().build();

            drmBbsService.deleteBbsCmnt(cmntId);
            response.put("success", true);
            return ResponseEntity.ok(response);

        } catch (DataAccessException e) {
            // DB 접속 불능, SQL 문법 오류 등 데이터 계층 예외
            logger.error("시스템 오류가 발생했습니다: {}", "DB 오류 발생", e);
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build();

        } catch (Exception e) {
            logger.error("시스템 오류가 발생했습니다: {}", "게시글 댓글 삭제", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /* 게시글 수정 */
    @PostMapping("/bbsCttUpdate.do")
    public ResponseEntity<Map<String, Object>> updateBbsCtt (
            @RequestBody DrmBbsVO drmBbsVO,
            @RequestPart(value = "uploadFiles", required = false) List<MultipartFile> uploadFiles
            ) {
        Map<String, Object> response = new HashMap<>();
        try {
            if (drmBbsVO.getBbsCttId() == null) {
                return ResponseEntity.badRequest().build();
            }

            if (drmBbsVO.getBbsCttTtl() == null || drmBbsVO.getBbsCttTtl().trim().isEmpty()) {
                response.put("message", "제목은 필수 항목입니다.");
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
            }

            drmBbsService.updateBbsCtt(drmBbsVO, uploadFiles);
            response.put("success", true);
            return ResponseEntity.ok(response);

        } catch (IllegalArgumentException e) {
            // 입력값이 잘못된 경우
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(Map.of("message", e));

        } catch (AccessDeniedException e) {
            // 권한이 없는 경우 (Spring Security 또는 커스텀 예외)
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of("message", "수정 권한이 없습니다."));

        } catch (IOException e) {
            // 파일 업로드 중 발생하는 입출력 오류
            logger.error("파일 저장 중 오류 발생", e);
            return ResponseEntity.status(HttpStatus.INSUFFICIENT_STORAGE).build();

        } catch (DataIntegrityViolationException e) {
            // DB 제약 조건(Unique key, Not Null 등) 위반
            logger.error("데이터 제약조건 위반 오류", e);
            return ResponseEntity.status(HttpStatus.CONFLICT).build();

        } catch (Exception e) {
            logger.error("시스템 오류가 발생했습니다: {}", "게시글 수정", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    @PostMapping("/bbsCttDelete.do")
    public ResponseEntity<Map<String, Object>> deleteBbsCtt (@RequestParam Long bbsCttId) {
        Map<String, Object> response = new HashMap<>();
        try {
            if (bbsCttId == null) return ResponseEntity.badRequest().build();

            drmBbsService.deleteBbsCtt(bbsCttId);
            response.put("success", true);
            return ResponseEntity.ok(response);

        } catch (DataAccessException e) {
            // DB 접속 불능, SQL 문법 오류 등 데이터 계층 예외
            logger.error("시스템 오류가 발생했습니다: {}", "DB 오류 발생", e);
            response.put("message", "게시글 삭제 중 오류 발생");
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build();

        } catch (Exception e) {
            logger.error("시스템 오류가 발생했습니다: {}", "게시글 삭제", e);
            response.put("message", "게시글 삭제 중 오류 발생");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }
}