package incheon.cmm.g2f.TaskLayer.web;

import incheon.cmm.g2f.TaskLayer.service.G2FTaskLayerService;
import incheon.cmm.g2f.TaskLayer.vo.G2TaskLayerVO;
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.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

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

@Slf4j
@Controller
@RequestMapping("/cmm/g2f/taskLayer")
public class G2FTaskLayerController {

    private final G2FTaskLayerService taskLayerService;

    public G2FTaskLayerController(G2FTaskLayerService taskLayerService) {
        this.taskLayerService = taskLayerService;
    }

    /**
     * 목록 조회
     */
    @GetMapping("/taskList.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) {

        // 1. 총 개수 조회
        int totalCount = taskLayerService.getTotalCount(searchKeyword, searchType);

        // 2. 페이징 설정 (IAS 표준)
        PaginationInfo paginationInfo = new PaginationInfo();
        paginationInfo.setCurrentPageNo(page);
        paginationInfo.setRecordCountPerPage(size);  // 페이지당 레코드 개수
        paginationInfo.setPageSize(10);              // 페이지 링크 개수
        paginationInfo.setTotalRecordCount(totalCount);

        // 3. 목록 조회
        List<G2TaskLayerVO> list = taskLayerService.getList(searchKeyword, searchType, page, size);

        // 4. Model에 데이터 추가
        model.addAttribute("list", list);
        model.addAttribute("paginationInfo", paginationInfo);  // IAS 표준 페이징 객체
        model.addAttribute("size", size);
        model.addAttribute("searchKeyword", searchKeyword);
        model.addAttribute("searchType", searchType);

        log.info("페이지: {}, 페이지당개수: {}, 총개수: {}, 조회개수: {}",
                page, size, totalCount, list.size());

        return "cmm/g2f/basemap/taskLayer/TaskLayerList";
    }

    /**
     * 생성 폼
     */
    @GetMapping("/create.do")
    public String showCreateForm(Model model) {
        G2TaskLayerVO taskLayer = new G2TaskLayerVO();
        taskLayer.setLyrSrvcPrefix("incheon");
        model.addAttribute("taskLayer", taskLayer);
        
        // 레이어 그룹 코드 목록 조회
        List<Map<String, Object>> groupCodes = taskLayerService.getGroupCodes();
        model.addAttribute("groupCodes", groupCodes);
        
        return "cmm/g2f/basemap/taskLayer/TaskLayerCreate";
    }

    /**
     * 생성 처리
     */
    @PostMapping("/create")
    public String create(@Valid @ModelAttribute("taskLayer") G2TaskLayerVO taskLayer,
                         BindingResult bindingResult, 
                         HttpSession session,
                         RedirectAttributes redirectAttributes,
                         Model model) {
        
        if (bindingResult.hasErrors()) {
            return "cmm/g2f/basemap/taskLayer/TaskLayerCreate";
        }
        
        try {
            LoginVO loginVO = (LoginVO) session.getAttribute("loginVO");
            if (loginVO == null) {
                throw new AuthenticationCredentialsNotFoundException("로그인이 필요합니다.");
            }
            
            taskLayer.setCrtId(loginVO.getUserId());
            taskLayer.setLyrSrvcPrefix("incheon"); // 강제 설정
            
            taskLayerService.create(taskLayer);
            
            model.addAttribute("message", "작업 레이어 등록이 완료되었습니다.");
            model.addAttribute("messageType", "success");
            model.addAttribute("redirectUrl", "/cmm/g2f/taskLayer/taskList.do");
            
            log.info("작업 레이어 등록 성공: {}", taskLayer.getTaskLyrId());
        } catch (DataAccessException | RestClientException e) {
            log.error("작업 레이어 등록 실패", e);
            model.addAttribute("message", "작업 레이어 등록에 실패했습니다");
            model.addAttribute("messageType", "error");
            return "cmm/g2f/basemap/taskLayer/TaskLayerCreate";
        }
        
        return "cmm/g2f/basemap/taskLayer/TaskLayerCreate";
    }

    /**
     * 수정 폼
     */
    @GetMapping("/edit.do")
    public String editForm(@RequestParam("taskLyrId") Integer taskLyrId, Model model) {
        G2TaskLayerVO taskLayer = taskLayerService.getById(taskLyrId);
        List<Map<String, Object>> groupCodes = taskLayerService.getGroupCodes();
        model.addAttribute("groupCodes", groupCodes);
        if (taskLayer == null) {
            log.warn("존재하지 않는 작업 레이어 - ID: {}", taskLyrId);
            return "redirect:/cmm/g2f/taskLayer/taskList.do?error=not_found";
        }
        
        model.addAttribute("taskLayer", taskLayer);
        return "cmm/g2f/basemap/taskLayer/TaskLayerEdit";
    }

    /**
     * 수정 처리
     */
    @PostMapping("/edit")
    public String edit(@RequestParam("taskLyrId") Integer taskLyrId,
                       @Valid @ModelAttribute("taskLayer") G2TaskLayerVO taskLayer,
                       BindingResult bindingResult, 
                       HttpSession session,
                       Model model) {
        
        if (bindingResult.hasErrors()) {
            return "cmm/g2f/basemap/taskLayer/TaskLayerEdit";
        }
        
        try {
            LoginVO loginVO = (LoginVO) session.getAttribute("loginVO");
            if (loginVO == null) {
                throw new AuthenticationCredentialsNotFoundException("로그인이 필요합니다.");
            }
            
            taskLayer.setTaskLyrId(taskLyrId);
            taskLayer.setChgId(loginVO.getUserId());
            
            taskLayerService.update(taskLayer);
            
            model.addAttribute("message", "작업 레이어 수정이 완료되었습니다.");
            model.addAttribute("messageType", "success");
            model.addAttribute("redirectUrl", "/cmm/g2f/taskLayer/taskList.do");
            
            log.info("작업 레이어 수정 성공: {}", taskLyrId);
        } catch (DataAccessException e) {
            log.error("작업 레이어 수정 실패", e);
            model.addAttribute("message", "작업 레이어 수정에 실패했습니다");
            model.addAttribute("messageType", "error");
            
            // 에러 발생 시 기존 데이터 다시 로드
            G2TaskLayerVO originalData = taskLayerService.getById(taskLyrId);
            model.addAttribute("taskLayer", originalData);
            return "cmm/g2f/basemap/taskLayer/TaskLayerEdit";
        }
        
        return "cmm/g2f/basemap/taskLayer/TaskLayerEdit";
    }

    /**
     * 삭제 처리
     */
    @PostMapping("/delete")
    public String delete(@RequestParam("taskLyrId") Integer taskLyrId,
                        RedirectAttributes redirectAttributes) {
        try {
            log.info("작업 레이어 삭제 요청 - ID: {}", taskLyrId);
            taskLayerService.delete(taskLyrId);
            
            redirectAttributes.addFlashAttribute("message", "작업 레이어가 삭제되었습니다.");
            redirectAttributes.addFlashAttribute("messageType", "success");
            
            log.info("작업 레이어 삭제 성공: {}", taskLyrId);
        } catch (DataAccessException | RestClientException e) {
            log.error("작업 레이어 삭제 실패 - ID: {}", taskLyrId, e);
            
            redirectAttributes.addFlashAttribute("message", "작업 레이어 삭제에 실패했습니다");
            redirectAttributes.addFlashAttribute("messageType", "error");
        }
        return "redirect:/cmm/g2f/taskLayer/taskList.do";
    }
    
    @GetMapping("/verifyPhysicalName")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> verifyPhysicalName(
            @RequestParam("lyrPhysNm") String lyrPhysNm,
            @RequestParam("lyrSrvcNm") String lyrSrvcNm
    ) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 1. 기본 형식 확인
            if (!lyrPhysNm.contains(".")) {
                result.put("success", false);
                result.put("errors", List.of("형식 오류: 스키마명.테이블명 형식이어야 합니다."));
                return ResponseEntity.ok(result);
            }

            String[] parts = lyrPhysNm.split("\\.");
            String schema = parts[0].trim();
            String tableNm = parts[1].trim();

            log.info("물리명 검증 시작: schema={}, table={}, service={}", schema, tableNm, lyrSrvcNm);

            // 2. 서비스 호출 (Map 반환)
            Map<String, Object> serviceResult =
                    taskLayerService.verifyGeometryTable(schema, tableNm, lyrSrvcNm, lyrPhysNm);

            return ResponseEntity.ok(serviceResult);

        } catch (DataAccessException | RestClientException e) {
            log.error("물리명 검증 중 예외 발생", e);
            result.put("success", false);
            result.put("errors", List.of("검증 중 오류 발생"));
            return ResponseEntity.internalServerError().body(result);
        }
    }

    /**
     * 작업 레이어 목록 JSON API
     */
    @GetMapping(value = "/api/v1/taskLayer", produces = "application/json")
    @ResponseBody
    public ResponseEntity<DefaultApiResponse<List<G2TaskLayerVO>>> getTaskLayers() {
        return ResponseEntity.ok(DefaultApiResponse.success(taskLayerService.getList()));
    }
    @PostMapping("/update")
    public String update(@RequestParam("taskLyrId") Integer taskLyrId,
                       @Valid @ModelAttribute("taskLayer") G2TaskLayerVO taskLayer,
                       BindingResult bindingResult, 
                       HttpSession session,
                       Model model) {
        
        if (bindingResult.hasErrors()) {
            return "cmm/g2f/basemap/taskLayer/TaskLayerEdit";
        }
        
        try {
            LoginVO loginVO = (LoginVO) session.getAttribute("loginVO");
            if (loginVO == null) {
                throw new AuthenticationCredentialsNotFoundException("로그인이 필요합니다.");
            }
            
            taskLayer.setTaskLyrId(taskLyrId);
            taskLayer.setChgId(loginVO.getUserId());
            
            taskLayerService.Metaupdate(taskLayer);
            
            model.addAttribute("message", "작업 레이어 수정이 완료되었습니다.");
            model.addAttribute("messageType", "success");
            model.addAttribute("redirectUrl", "/cmm/g2f/taskLayer/taskList.do");
            
            log.info("작업 레이어 수정 성공: {}", taskLyrId);
        } catch (DataAccessException e) {
            log.error("작업 레이어 수정 실패", e);
            model.addAttribute("message", "작업 레이어 수정에 실패했습니다");
            model.addAttribute("messageType", "error");
            
            // 에러 발생 시 기존 데이터 다시 로드
            G2TaskLayerVO originalData = taskLayerService.getById(taskLyrId);
            model.addAttribute("taskLayer", originalData);
            return "cmm/g2f/basemap/taskLayer/TaskLayerEdit";
        }
        
        return "cmm/g2f/basemap/taskLayer/TaskLayerEdit";
    }
}