package incheon.ags.dss.regen.web;

import java.util.Map;
import java.util.List;
import java.util.HashMap;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import incheon.com.cmm.api.DefaultApiResponse;
import incheon.ags.dss.regen.service.UrbTrgtClsfService;
import incheon.ags.dss.regen.vo.UrbTrgtClsfMstVO;
import incheon.ags.dss.regen.vo.UrbTrgtClsfDtlVO;

import org.egovframe.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;

// Swagger Imports
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 도시재생 - 대상분류 컨트롤러
 * @author hj
 * @since 2025.11.28
 */
@Tag(name = "도시재생-대상분류", description = "도시재생 대상분류 관련 API")
@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping("/api/v1/dss/urb/trgtClsf")
public class UrbTrgtClsfApiController {

    private final UrbTrgtClsfService service;

    /**
     * 대상분류 마스터 목록 조회
     */
    @Operation(summary = "대상분류 마스터 목록 조회", description = "대상분류 마스터 목록을 페이징 처리하여 조회합니다.")
    @GetMapping("/list.do")
    public ResponseEntity<DefaultApiResponse> selectUrbTrgtClsfMstList(
            @Parameter(description = "검색 조건 및 페이징 정보")
            @ModelAttribute UrbTrgtClsfMstVO searchVO) throws Exception {

        PaginationInfo paginationInfo = new PaginationInfo();
        paginationInfo.setCurrentPageNo(searchVO.getPageIndex() > 0 ? searchVO.getPageIndex() : 1);
        paginationInfo.setRecordCountPerPage(searchVO.getRecordCountPerPage() > 0 ? searchVO.getRecordCountPerPage() : 10);
        paginationInfo.setPageSize(10);
        searchVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
        searchVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());

        if (searchVO.getZoneNo() == null) {
            return ResponseEntity.badRequest().body(DefaultApiResponse.error(400, "zoneNo 파라미터가 필요합니다.", ""));
        }

        List<UrbTrgtClsfMstVO> list = service.selectUrbTrgtClsfMstList(searchVO);
        int totalCount = service.selectUrbTrgtClsfMstListCnt(searchVO);
        paginationInfo.setTotalRecordCount(totalCount);

        Map<String, Object> result = new HashMap<>();
        result.put("list", list);
        result.put("paging", paginationInfo);

        return ResponseEntity.ok(DefaultApiResponse.success(result, "대상분류 마스터 목록이 조회되었습니다."));
    }

    /**
     * 대상분류 마스터 등록
     */
    @Operation(summary = "대상분류 마스터 등록", description = "새로운 대상분류 마스터를 등록합니다.")
    @PostMapping("/insertMst.do")
    public ResponseEntity<DefaultApiResponse> insertUrbTrgtClsfMst(
            @Parameter(description = "등록할 대상분류 마스터 정보")
            @RequestBody UrbTrgtClsfMstVO vo) throws Exception {
        if (vo.getZoneNo() == null) {
            return ResponseEntity.badRequest().body(DefaultApiResponse.error(400, "zoneNo 파라미터가 필요합니다.", ""));
        }
        if (vo.getTrgtClsfNm() == null || vo.getTrgtClsfNm().trim().isEmpty()) {
            return ResponseEntity.badRequest().body(DefaultApiResponse.error(400, "trgtClsfNm 파라미터가 필요합니다.", ""));
        }
        service.insertUrbTrgtClsfMst(vo);

        Map<String, Object> result = new HashMap<>();
        result.put("trgtClsfNo", vo.getTrgtClsfNo());
        return ResponseEntity.ok(DefaultApiResponse.success(result, "대상분류 마스터가 성공적으로 등록되었습니다."));
    }

    /**
     * 대상분류 마스터 수정 (명칭 변경)
     */
    @Operation(summary = "대상분류 마스터 수정", description = "기존 대상분류 마스터의 명칭을 수정합니다.")
    @PostMapping("/updateMst.do")
    public ResponseEntity<DefaultApiResponse> updateUrbTrgtClsfMst(
            @Parameter(description = "수정할 대상분류 마스터 정보 (trgtClsfNo, trgtClsfNm)")
            @RequestBody UrbTrgtClsfMstVO vo) throws Exception {

        if (vo.getTrgtClsfNo() == null) {
            return ResponseEntity.badRequest().body(DefaultApiResponse.error(400, "trgtClsfNo 파라미터가 필요합니다.", ""));
        }
        if (vo.getTrgtClsfNm() == null || vo.getTrgtClsfNm().trim().isEmpty()) {
            return ResponseEntity.badRequest().body(DefaultApiResponse.error(400, "trgtClsfNm 파라미터가 필요합니다.", ""));
        }

        service.updateUrbTrgtClsfMst(vo);
        return ResponseEntity.ok(DefaultApiResponse.success(null, "대상분류 마스터가 성공적으로 수정되었습니다."));
    }

    /**
     * 대상분류 마스터 삭제
     */
    @Operation(summary = "대상분류 마스터 삭제", description = "대상분류 마스터를 삭제합니다.")
    @PostMapping("/deleteMst.do")
    public ResponseEntity<DefaultApiResponse> deleteUrbTrgtClsfMst(
            @Parameter(description = "삭제할 대상분류 마스터 정보 (trgtClsfNo)")
            @RequestBody UrbTrgtClsfMstVO vo) throws Exception {

        service.deleteUrbTrgtClsfMst(vo);
        return ResponseEntity.ok(DefaultApiResponse.success(null, "대상분류 마스터가 성공적으로 삭제되었습니다."));
    }

    /**
     * 좌표 기준 필지/시설 정보 조회
     */
    @Operation(summary = "좌표 기준 필지/시설 정보 조회", description = "주어진 경위도 좌표를 기준으로 필지 또는 시설 정보를 조회합니다.")
    @GetMapping("/parcelByPoint.do")
    public ResponseEntity<DefaultApiResponse> selectUrbTrgtParcelByPoint(
            @Parameter(description = "경위도 좌표 (lon, lat)")
            @RequestParam Map<String, Object> param) throws Exception {

        UrbTrgtClsfDtlVO resultVO = service.selectUrbTrgtParcelByPoint(param);
        return ResponseEntity.ok(DefaultApiResponse.success(resultVO, "좌표 기준 필지/시설 정보가 조회되었습니다."));
    }

    /**
     * 대상분류 상세 등록
     */
    @Operation(summary = "대상분류 상세 등록", description = "대상분류 상세 정보를 등록합니다.")
    @PostMapping("/insertDtl.do")
    public ResponseEntity<DefaultApiResponse> insertUrbTrgtClsfDtl(
            @Parameter(description = "등록할 대상분류 상세 정보")
            @RequestBody UrbTrgtClsfDtlVO vo) throws Exception {

        service.insertUrbTrgtClsfDtl(vo);
        return ResponseEntity.ok(DefaultApiResponse.success(null, "대상분류 상세 정보가 성공적으로 등록되었습니다."));
    }

    /**
     * 대상분류 상세 목록 조회 (페이징)
     */
    @Operation(summary = "대상분류 상세 목록 조회", description = "특정 대상분류 번호(trgtClsfNo)에 해당하는 상세 목록을 페이징하여 조회합니다.")
    @GetMapping("/dtlList.do")
    public ResponseEntity<DefaultApiResponse> selectUrbTrgtClsfDtlList(
            @Parameter(description = "검색 조건 및 페이징 정보 (trgtClsfNo, pageIndex 등)")
            @ModelAttribute UrbTrgtClsfDtlVO searchVO) throws Exception {

        PaginationInfo paginationInfo = new PaginationInfo();
        paginationInfo.setCurrentPageNo(searchVO.getPageIndex() > 0 ? searchVO.getPageIndex() : 1);
        paginationInfo.setRecordCountPerPage(searchVO.getRecordCountPerPage() > 0 ? searchVO.getRecordCountPerPage() : 20); // 한 번에 가져올 개수
        paginationInfo.setPageSize(1); // 스크롤 페이징에서는 크게 의미 없음

        searchVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
        searchVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());

        List<UrbTrgtClsfDtlVO> list = service.selectUrbTrgtClsfDtlList(searchVO);
        int totalCount = service.selectUrbTrgtClsfDtlListCnt(searchVO);

        Map<String, Object> result = new HashMap<>();
        result.put("list", list);
        result.put("totalCount", totalCount);
        result.put("currentPage", paginationInfo.getCurrentPageNo());

        boolean hasNext = (paginationInfo.getFirstRecordIndex() + list.size()) < totalCount;
        result.put("hasNext", hasNext);

        return ResponseEntity.ok(DefaultApiResponse.success(result, "대상분류 상세 목록이 조회되었습니다."));
    }

    /**
     * 대상분류 상세 단건 삭제 (상세번호 기준)
     */
    @Operation(summary = "대상분류 상세 단건 삭제", description = "특정 상세 결과(trgtClsfDtlNo) 하나를 삭제합니다.")
    @PostMapping("/deleteDtlItem.do")
    public ResponseEntity<DefaultApiResponse> deleteUrbTrgtClsfDtlItem(
            @Parameter(description = "삭제할 상세 번호 (trgtClsfDtlNo)")
            @RequestBody Map<String, Integer> param) throws Exception { // 단일 Integer 파라미터는 Map으로 받거나, VO에 담아서 처리

        Integer trgtClsfDtlNo = param.get("trgtClsfDtlNo");
        if (trgtClsfDtlNo == null) {
            return ResponseEntity.badRequest().body(DefaultApiResponse.error(400, "trgtClsfDtlNo 파라미터가 필요합니다.", ""));
        }
        service.deleteUrbTrgtClsfDtlItem(trgtClsfDtlNo);
        return ResponseEntity.ok(DefaultApiResponse.success(null, "해당 대상분류 상세 항목이 삭제되었습니다."));
    }

    /**
     * 대상분류 번호 기준 상세 전체 삭제
     */
    @Operation(summary = "대상분류 번호 기준 상세 전체 삭제", description = "특정 대상분류 번호(trgtClsfNo)에 해당하는 모든 상세 항목을 삭제합니다.")
    @PostMapping("/deleteDtlByClsfNo.do")
    public ResponseEntity<DefaultApiResponse> deleteUrbTrgtClsfDtlByClsfNo(
            @Parameter(description = "삭제할 대상분류 번호 (trgtClsfNo)")
            @RequestBody UrbTrgtClsfDtlVO vo) throws Exception {

        service.deleteUrbTrgtClsfDtlByClsfNo(vo);
        return ResponseEntity.ok(DefaultApiResponse.success(null, "해당 대상분류의 모든 상세 항목이 삭제되었습니다."));
    }

    /**
     * 접근도 분석 실행
     * - acei.js에서 호출하는 엔드포인트
     */
    @Operation(summary = "접근도 분석 실행", description = "선택된 대상집합에 대해 접근도 분석을 실행합니다.")
    @PostMapping("/runAnalysis.do")
    public ResponseEntity<DefaultApiResponse> runAccessibilityAnalysis(
            @Parameter(description = "분석 실행 정보 (trgtClsfNo, zoneNo, LOGIN_USER_ID 등)")
            @RequestBody UrbTrgtClsfDtlVO vo) throws Exception {

        if (vo.getTrgtClsfNo() == null) {
            return ResponseEntity.badRequest().body(DefaultApiResponse.error(400, "trgtClsfNo 파라미터가 필요합니다.", ""));
        }
        if (vo.getZoneNo() == null) {
            return ResponseEntity.badRequest().body(DefaultApiResponse.error(400, "zoneNo 파라미터가 필요합니다.", ""));
        }

        int dtlCnt = service.selectUrbTrgtClsfDtlListCnt(vo);
        if (dtlCnt <= 0) {
            return ResponseEntity.badRequest().body(DefaultApiResponse.error(400, "지번목록이 없으면 분석을 실행할 수 없습니다.", ""));
        }

        int fcltAnlsNo = service.runAccessibilityAnalysis(vo);
        
        Map<String, Object> result = new HashMap<>();
        result.put("fcltAnlsNo", fcltAnlsNo);

        return ResponseEntity.ok(DefaultApiResponse.success(result, "접근도 분석이 성공적으로 시작되었습니다."));
    }
}
