package incheon.uis.gisu.web;

import incheon.uis.gisu.service.GisuService;
import incheon.uis.gisu.vo.GisuDownloadCheckResult;
import incheon.uis.gisu.vo.TaskLayerVO;
import incheon.com.cmm.context.RequestContext;
import incheon.com.security.vo.LoginVO;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Controller
@RequestMapping("/api/uis/gisu")
public class GisuController {

    private final GisuService gisuService;

    public GisuController(GisuService gisuService) {
        this.gisuService = gisuService;
    }

    // 1) 최초 모달(신청목록 + 신청 버튼) JSP
    @GetMapping("/applyPopup.do")
    public String openApplyPopup() {
        return "/uis/popup/gisuApplyPopup";
    }

    // 2) 내가 신청한 목록 JSON (페이징)
    @GetMapping("/myList.do")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> myList(
            @RequestParam(value = "pageIndex", defaultValue = "1") int pageIndex,
            @RequestParam(value = "pageSize", defaultValue = "10") int pageSize
    ) {
        LoginVO user = RequestContext.getCurrentUser();
        Map<String, Object> res = new HashMap<>();

        try {

            if (user == null) {
                log.warn("기수 신청 목록 조회 실패 - 로그인 정보 없음");
                res.put("success", false);
                res.put("message", "로그인이 필요합니다.");
                res.put("data", Collections.emptyList());
                res.put("totalCount", 0);
                res.put("hasNext", false);
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(res);
            }

            String userUnqId = user.getUserUnqId();

            // 페이징 처리
            Map<String, Object> pagingResult = gisuService.getMyGisuListWithPaging(userUnqId, pageIndex, pageSize);

            res.put("success", true);
            res.put("data", pagingResult.get("list"));
            res.put("totalCount", pagingResult.get("totalCount"));
            res.put("hasNext", pagingResult.get("hasNext"));
        } catch (IllegalArgumentException e) {
            log.warn("기수 신청 목록 조회 실패 - 잘못된 인자: pageIndex={}, pageSize={}, error={}", 
                pageIndex, pageSize, e.getMessage());
            res.put("success", false);
            res.put("message", "잘못된 요청입니다.");
            res.put("data", Collections.emptyList());
            res.put("totalCount", 0);
            res.put("hasNext", false);
        } catch (Exception e) {
            log.error("기수 신청 목록 조회 중 예상치 못한 오류 발생: pageIndex={}, pageSize={}", 
                pageIndex, pageSize, e);
            res.put("success", false);
            res.put("message", "목록 조회 중 오류가 발생했습니다.");
            res.put("data", Collections.emptyList());
            res.put("totalCount", 0);
            res.put("hasNext", false);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(res);
        }

        try {
            String userUnqId = user.getUserUnqId();

            Map<String, Object> pagingResult =
                    gisuService.getMyGisuListWithPaging(userUnqId, pageIndex, pageSize);

            res.put("success", true);
            res.put("data", pagingResult.get("list"));
            res.put("totalCount", pagingResult.get("totalCount"));
            res.put("hasNext", pagingResult.get("hasNext"));
            return ResponseEntity.ok(res);

        } catch (Exception e) {
            res.put("success", false);
            res.put("message", "목록 조회 중 오류가 발생했습니다.");
            res.put("data", Collections.emptyList());
            res.put("totalCount", 0);
            res.put("hasNext", false);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(res);
        }
    }

    // 3) 대상 레이어 목록 JSON
    @GetMapping("/layers.do")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> layers() {
        Map<String, Object> res = new HashMap<>();
        try {
            List<TaskLayerVO> list = gisuService.getAvailableTaskLayers();
            res.put("success", true);
            res.put("data", list);
            return ResponseEntity.ok(res);

        } catch (Exception e) {
            res.put("success", false);
            res.put("message", "레이어 목록 조회 중 오류가 발생했습니다.");
            res.put("data", Collections.emptyList());
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(res);
        }
    }

    // 4) 신청 등록
    @PostMapping("/apply.do")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> apply(
            @RequestParam("usePurps") String usePurps,
            @RequestParam("taskLyrs") List<String> taskLyrs
    ) {
        Map<String, Object> res = new HashMap<>();
        try {
            LoginVO user = RequestContext.getCurrentUser();
            if (user == null) {
                log.warn("기수 신청 등록 실패 - 로그인 정보 없음");
                res.put("success", false);
                res.put("message", "로그인이 필요합니다.");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(res);
            }

            if (usePurps == null || usePurps.trim().isEmpty()) {
                log.warn("기수 신청 등록 실패 - 사용목적 없음: userUnqId={}", user.getUserUnqId());
                res.put("success", false);
                res.put("message", "사용목적을 입력해주세요.");
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(res);
            }

            String userUnqId = user.getUserUnqId();
            Long idn = gisuService.registerGisu(userUnqId, usePurps, taskLyrs);

            res.put("success", true);
            res.put("idn", idn);
            res.put("message", "공개제한 데이터 사용 신청이 등록되었습니다.");
        } catch (IllegalArgumentException e) {
            log.warn("기수 신청 등록 실패 - 잘못된 인자: usePurps={}, error={}", usePurps, e.getMessage());
            res.put("success", false);
            res.put("message", e.getMessage() != null && !e.getMessage().isEmpty() ? 
                e.getMessage() : "잘못된 요청입니다.");
        } catch (IllegalStateException e) {
            log.warn("기수 신청 등록 실패 - 비즈니스 규칙 위반: usePurps={}, error={}", usePurps, e.getMessage());
            res.put("success", false);
            res.put("message", e.getMessage() != null && !e.getMessage().isEmpty() ? 
                e.getMessage() : "신청 처리 중 오류가 발생했습니다.");
        } catch (Exception e) {
            log.error("기수 신청 등록 중 예상치 못한 오류 발생: usePurps={}", usePurps, e);
            res.put("success", false);
            res.put("message", "신청 등록 중 오류가 발생했습니다.");
        }
        return ResponseEntity.status(HttpStatus.OK).body(res);
    }

    // ZIP 다운로드 (스트리밍이라 기존 유지)
    @GetMapping("/downloadZip.do")
    public void downloadZip(@RequestParam("idn") Long idn,
                            HttpServletResponse response) {
        try {
            LoginVO user = RequestContext.getCurrentUser();
            if (user == null) {
                log.warn("ZIP 다운로드 실패 - 로그인 정보 없음: idn={}", idn);
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                return;
            }

            String userUnqId = user.getUserUnqId();
            Path zipPath = gisuService.createZipForApprovedGisu(idn, userUnqId);

            String fileName = zipPath.getFileName().toString();
            String encoded = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");

            response.setContentType("application/zip");
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + encoded + "\"");

            Files.copy(zipPath, response.getOutputStream());
            response.flushBuffer();

        } catch (IllegalStateException e) {
            log.warn("ZIP 다운로드 실패 - 비즈니스 규칙 위반: idn={}, error={}", idn, e.getMessage());
            try {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("다운로드할 수 없는 상태입니다.");
            } catch (IOException ioException) {
                log.error("응답 작성 중 오류 발생", ioException);
            }
        } catch (IllegalArgumentException e) {
            log.warn("ZIP 다운로드 실패 - 잘못된 인자: idn={}, error={}", idn, e.getMessage());
            try {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("잘못된 요청입니다.");
            } catch (IOException ioException) {
                log.error("응답 작성 중 오류 발생", ioException);
            }
        } catch (UnsupportedEncodingException e) {
            log.error("ZIP 다운로드 실패 - 인코딩 오류: idn={}", idn, e);
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("파일명 인코딩 중 오류가 발생했습니다.");
            } catch (IOException ioException) {
                log.error("응답 작성 중 오류 발생", ioException);
            }
        } catch (IOException e) {
            log.error("ZIP 다운로드 실패 - 파일 처리 오류: idn={}", idn, e);
            try {
                if (!response.isCommitted()) {
                    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                    response.getWriter().write("파일 다운로드 중 오류가 발생했습니다.");
                }
            } catch (IOException ioException) {
                log.error("응답 작성 중 오류 발생", ioException);
            }
        } catch (Exception e) {
            log.error("ZIP 다운로드 중 예상치 못한 오류 발생: idn={}", idn, e);
            try {
                if (!response.isCommitted()) {
                    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                    response.getWriter().write("다운로드 처리 중 오류가 발생했습니다.");
                }
            } catch (IOException ioException) {
                log.error("응답 작성 중 오류 발생", ioException);
            }
        }
    }

    @PostMapping("/downloadCheck.do")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> downloadCheck(@RequestParam("idn") Long idn) {

        LoginVO user = RequestContext.getCurrentUser();
        Map<String, Object> res = new HashMap<>();

        try {
            if (user == null) {
                log.warn("다운로드 가능 여부 확인 실패 - 로그인 정보 없음: idn={}", idn);
                res.put("success", false);
                res.put("message", "로그인이 필요합니다.");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(res);
            }

            String userUnqId = user.getUserUnqId();
            GisuDownloadCheckResult chk = gisuService.checkDownloadAvailable(idn, userUnqId);

            res.put("success", chk.isSuccess());
            res.put("message", chk.getMessage());
        } catch (IllegalArgumentException e) {
            log.warn("다운로드 가능 여부 확인 실패 - 잘못된 인자: idn={}, error={}", idn, e.getMessage());
            res.put("success", false);
            res.put("message", "잘못된 요청입니다.");
        } catch (IllegalStateException e) {
            log.warn("다운로드 가능 여부 확인 실패 - 비즈니스 규칙 위반: idn={}, error={}", idn, e.getMessage());
            res.put("success", false);
            res.put("message", e.getMessage() != null && !e.getMessage().isEmpty() ? 
                e.getMessage() : "다운로드 가능 여부 확인 중 오류가 발생했습니다.");
        } catch (Exception e) {
            log.error("다운로드 가능 여부 확인 중 예상치 못한 오류 발생: idn={}", idn, e);
            res.put("success", false);
            res.put("message", "다운로드 가능 여부 확인 중 오류가 발생했습니다.");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(res);
        }
        return ResponseEntity.status(HttpStatus.OK).body(res);
    }

    @PostMapping("/myDetailLayers.do")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> myDetailLayers(@RequestParam("idn") Long idn) {

        Map<String, Object> res = new HashMap<>();
        try {
            LoginVO user = RequestContext.getCurrentUser();
            if (user == null) {
                log.warn("기수 상세 레이어 목록 조회 실패 - 로그인 정보 없음: idn={}", idn);
                res.put("success", false);
                res.put("message", "로그인이 필요합니다.");
                res.put("data", Collections.emptyList());
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(res);
            }

            List<TaskLayerVO> list = gisuService.getGisuLayers(idn);
            res.put("success", true);
            res.put("data", list);
        } catch (IllegalArgumentException e) {
            log.warn("기수 상세 레이어 목록 조회 실패 - 잘못된 인자: idn={}, error={}", idn, e.getMessage());
            res.put("success", false);
            res.put("message", "잘못된 요청입니다.");
            res.put("data", Collections.emptyList());
        } catch (Exception e) {
            log.error("기수 상세 레이어 목록 조회 중 예상치 못한 오류 발생: idn={}", idn, e);
            res.put("success", false);
            res.put("message", "레이어 목록 조회 중 오류가 발생했습니다.");
            res.put("data", Collections.emptyList());
        }
        return ResponseEntity.status(HttpStatus.OK).body(res);
    }
}
