package incheon.cmm.ahm.flight.web;

import incheon.cmm.ahm.flight.service.G2fFlightService;
import incheon.cmm.ahm.flight.vo.G2fFlightVO;
import incheon.com.cmm.api.DefaultApiResponse;
import incheon.com.security.vo.LoginVO;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;
import org.springframework.dao.DataAccessException;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Controller
@RequestMapping("/cmm/ahm/flight")
public class G2fFlightController {

    private final G2fFlightService flightService;

    public G2fFlightController(G2fFlightService flightService) {
        this.flightService = flightService;
    }

    @GetMapping("/flightList.do")
    public String list(Model model,
                       @RequestParam(value = "page", defaultValue = "1") int page,
                       @RequestParam(value = "size", defaultValue = "10") int size,
                       @RequestParam(value = "searchKeyword", required = false) String searchKeyword,
                       @RequestParam(value = "searchType", required = false) String searchType) {

        PaginationInfo paginationInfo = new PaginationInfo();
        paginationInfo.setCurrentPageNo(page);
        paginationInfo.setRecordCountPerPage(size);
        paginationInfo.setPageSize(10);

        int total = flightService.getTotalCount(searchKeyword, searchType);
        paginationInfo.setTotalRecordCount(total);

        List<G2fFlightVO> list = flightService.getList(searchKeyword, searchType, page, size);

        model.addAttribute("paginationInfo", paginationInfo);
        model.addAttribute("list", list);
        model.addAttribute("total", total);
        model.addAttribute("totalCount", total);
        model.addAttribute("page", page);
        model.addAttribute("size", size);
        model.addAttribute("searchKeyword", searchKeyword);
        model.addAttribute("searchType", searchType);
        model.addAttribute("totalPages", (int) Math.ceil((double) total / size));
        model.addAttribute("thumbnail", new HashMap<String, String>());

        return "cmm/ahm/flight/flightList";
    }

    @GetMapping("/create.do")
    public String showCreateForm(Model model) {
        model.addAttribute("flight", new G2fFlightVO());
        return "cmm/ahm/flight/flightCreate";
    }

    @PostMapping("/create")
    public String create(@Valid @ModelAttribute("flight") G2fFlightVO poi,
                         BindingResult bindingResult,
                         HttpSession session,
                         Model model) {  // Model 추가
        if (bindingResult.hasErrors()) {
            return "cmm/ahm/flight/flightCreate";
        }

        try {
            LoginVO loginVO = (LoginVO) session.getAttribute("loginVO");
            if (loginVO == null) {
                log.warn("로그인되지 않은 사용자의 등록 시도");
                loginVO = new LoginVO();
                loginVO.setUserNm("관리자");
                loginVO.setUserId("admin");
            }

            poi.setCrtId(loginVO.getUserId());
            flightService.create(poi);

            model.addAttribute("message", "항공영상이 등록되었습니다.");
            model.addAttribute("messageType", "success");
            model.addAttribute("redirectUrl", "/cmm/ahm/flight/flightList.do");

            log.info("항공영상 등록 성공: {}", poi.getFlightPhotoLyrId());
        } catch (DataAccessException e) {
            log.error("항공영상 등록 실패", e);

            model.addAttribute("message", "항공영상 등록에 실패했습니다.");
            model.addAttribute("messageType", "error");
        }

        return "cmm/ahm/flight/flightCreate";
    }

    @GetMapping("/edit.do")
    public String editForm(@RequestParam Integer nfId, Model model) {
        G2fFlightVO poi = flightService.getById(nfId);

        if (poi == null) {
            log.warn("존재하지 않는 항공영상 - ID: {}", nfId);
            return "redirect:/cmm/ahm/flight/flightList.do";
        }

        model.addAttribute("poi", poi);
        return "cmm/ahm/flight/flightEdit";
    }

 // edit 메서드 수정
    @PostMapping("/edit")
    public String edit(@RequestParam Integer nfId,
                       @Valid @ModelAttribute("poi") G2fFlightVO poi,
                       BindingResult bindingResult,
                       HttpSession session,
                       Model model) {  // Model 추가
        if (bindingResult.hasErrors()) {
            return "cmm/ahm/flight/flightEdit";
        }

        try {
            LoginVO loginVO = (LoginVO) session.getAttribute("loginVO");
            if (loginVO == null) {
                log.warn("로그인되지 않은 사용자의 수정 시도");
                loginVO = new LoginVO();
                loginVO.setUserNm("관리자");
                loginVO.setUserId("admin");
            }

            poi.setCrtId(loginVO.getUserId());
            poi.setFlightPhotoLyrId(nfId);
            flightService.update(poi);
            
            model.addAttribute("message", "항공영상이 수정되었습니다.");
            model.addAttribute("messageType", "success");
            model.addAttribute("redirectUrl", "/cmm/ahm/flight/flightList.do");
            
            log.info("항공영상 수정 성공: {}", nfId);
        } catch (DataAccessException e) {
            log.error("항공영상 수정 실패: {}", nfId, e);
            
            model.addAttribute("message", "항공영상 수정에 실패했습니다.");
            model.addAttribute("messageType", "error");
        }

        return "cmm/ahm/flight/flightEdit";
    }

    @PostMapping("/delete")
    public String delete(@RequestParam Integer nfId) {
        try {
            log.info("삭제 요청 - ID: {}", nfId);
            flightService.delete(nfId);
            return "redirect:/cmm/ahm/flight/flightList.do";
        } catch (DataAccessException e) {
            log.error("삭제 실패 - ID: {}", nfId, e);
            return "redirect:/cmm/ahm/flight/flightList.do";
        }
    }

    /**
     * 중복 검사 API (등록용) - 상세 정보 포함
     */
    @GetMapping("/api/v1/check-duplicate")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> checkDuplicate(
            @RequestParam(required = false) String lyrSrvcPrefix,
            @RequestParam String lyrSrvcNm,
            @RequestParam(required = false) String lyrSrvcMatrixNm,
            @RequestParam String extn,
            @RequestParam String cntm
    		) {

        Map<String, Object> response = new HashMap<>();

        try {
            // 필수 파라미터 체크
            if (lyrSrvcNm == null || lyrSrvcNm.trim().isEmpty() ||
                    extn == null || extn.trim().isEmpty()) {
                response.put("isDuplicate", false);
                response.put("message", "필수 파라미터가 누락되었습니다.");
                return ResponseEntity.badRequest().body(response);
            }

            // Trim 및 빈 문자열 처리
            String prefix = lyrSrvcPrefix != null && !lyrSrvcPrefix.trim().isEmpty() ? lyrSrvcPrefix.trim() : null;
            String name = lyrSrvcNm.trim();
            String matrix = lyrSrvcMatrixNm != null && !lyrSrvcMatrixNm.trim().isEmpty() ? lyrSrvcMatrixNm.trim() : null;
            String extension = extn.trim();
            String srid = cntm.trim();

            // 서비스에서 중복 검사 및 상세 정보 조회
            Map<String, Object> result = flightService.checkDuplicateWithDetails(prefix, name, matrix, extension, srid);

            if ((Boolean) result.get("isDuplicate")) {
                G2fFlightVO existingData = (G2fFlightVO) result.get("existingData");
                @SuppressWarnings("unchecked")
                Map<String, String> duplicateFields = (Map<String, String>) result.get("duplicateFields");

                response.put("isDuplicate", true);
                response.put("message", "이미 등록된 항공영상입니다.");
                
                // 중복된 데이터 정보
                Map<String, Object> conflictInfo = new HashMap<>();
                conflictInfo.put("existingId", existingData.getFlightPhotoLyrId());
                conflictInfo.put("existingName", existingData.getFlightPhotoLyrNm());
                conflictInfo.put("conflictFields", duplicateFields);
                
                response.put("conflict", conflictInfo);
                
            } else {
                response.put("isDuplicate", false);
                response.put("message", "등록 가능합니다.");
                
                @SuppressWarnings("unchecked")
                Map<String, String> checkedFields = (Map<String, String>) result.get("checkedFields");
                response.put("checkedFields", checkedFields);
            }

            return ResponseEntity.ok(response);

        } catch (DataAccessException e) {
            log.error("중복 검사 중 오류 발생", e);
            response.put("isDuplicate", false);
            response.put("message", "중복 검사 중 오류가 발생했습니다");
            return ResponseEntity.internalServerError().body(response);
        }
    }

    /**
     * 중복 검사 API (수정용) - 상세 정보 포함
     */
    @GetMapping("/api/v1/check-duplicate-for-update")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> checkDuplicateForUpdate(
            @RequestParam Integer nfId,
            @RequestParam(required = false) String lyrSrvcPrefix,
            @RequestParam String lyrSrvcNm,
            @RequestParam(required = false) String lyrSrvcMatrixNm,
            @RequestParam String extn,
            @RequestParam String cntm
    		) {

        Map<String, Object> response = new HashMap<>();

        try {
            if (nfId == null || lyrSrvcNm == null || lyrSrvcNm.trim().isEmpty() ||
                    extn == null || extn.trim().isEmpty()) {
                response.put("isDuplicate", false);
                response.put("message", "필수 파라미터가 누락되었습니다.");
                return ResponseEntity.badRequest().body(response);
            }

            String prefix = lyrSrvcPrefix != null && !lyrSrvcPrefix.trim().isEmpty() ? lyrSrvcPrefix.trim() : null;
            String name = lyrSrvcNm.trim();
            String matrix = lyrSrvcMatrixNm != null && !lyrSrvcMatrixNm.trim().isEmpty() ? lyrSrvcMatrixNm.trim() : null;
            String extension = extn.trim();
            String srid = cntm.trim();
            Map<String, Object> result = flightService.checkDuplicateWithDetailsForUpdate(nfId, prefix, name, matrix, extension, srid);

            if ((Boolean) result.get("isDuplicate")) {
                G2fFlightVO existingData = (G2fFlightVO) result.get("existingData");
                @SuppressWarnings("unchecked")
                Map<String, String> duplicateFields = (Map<String, String>) result.get("duplicateFields");

                response.put("isDuplicate", true);
                response.put("message", "이미 등록된 항공영상입니다.");
                
                Map<String, Object> conflictInfo = new HashMap<>();
                conflictInfo.put("existingId", existingData.getFlightPhotoLyrId());
                conflictInfo.put("existingName", existingData.getFlightPhotoLyrNm());
                conflictInfo.put("conflictFields", duplicateFields);
                response.put("conflict", conflictInfo);
            } else {
                response.put("isDuplicate", false);
                response.put("message", "수정 가능합니다.");
                
                @SuppressWarnings("unchecked")
                Map<String, String> checkedFields = (Map<String, String>) result.get("checkedFields");
                response.put("checkedFields", checkedFields);
            }

            return ResponseEntity.ok(response);

        } catch (DataAccessException e) {
            log.error("중복 검사 중 오류 발생", e);
            response.put("isDuplicate", false);
            response.put("message", "중복 검사 중 오류가 발생했습니다");
            return ResponseEntity.internalServerError().body(response);
        }
    }

    @GetMapping(value = "/api/v1/flight", produces = "application/json")
    @ResponseBody
    public ResponseEntity<DefaultApiResponse<List<G2fFlightVO>>> pois() throws IOException {
        return ResponseEntity.ok(DefaultApiResponse.success(flightService.getList()));
    }
}