package incheon.uis.ums.web;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import incheon.com.cmm.api.DefaultApiResponse;
import incheon.com.security.util.SecurityUtil;
import incheon.uis.ucf.model.UisDefaultModel;
import incheon.uis.ums.mapper.ConstructionSeqMapper;
import incheon.uis.ums.service.DynamicModelService;
import incheon.uis.ums.service.UisAccessService;
import incheon.uis.ums.service.UisFacilityService;
import incheon.uis.ums.service.UisTaskLyrService;
import incheon.uis.ums.util.UisConstructionNumberGenerator;
import incheon.uis.ums.vo.UisTaskLyrVO;
import lombok.extern.slf4j.Slf4j;

/**
 * UIS 대장 및 시설물 관리를 위한 통합 컨트롤러
 * UisBaseController를 상속받아 동적으로 타입을 처리하는 방식으로 구현
 *
 * @author 이재룡
 * @since 2025.09.02
 * @version 2.0.0
 */
@RestController
@RequestMapping("/api/uis")
@Slf4j
public class UisFacilityMngmtController extends UisBaseController {

	private final UisFacilityService facilityService;
	private final UisTaskLyrService uisTaskLyrService;
	private final UisAccessService uisAccessService;

	/**
	 * 생성자 - 의존성 주입
	 *
	 * @param constructionSeqMapper 건설 순번 매퍼
	 * @param constructionNumberGenerator 건설 번호 생성기
	 * @param facilityService 시설물 서비스
	 */
	public UisFacilityMngmtController(ConstructionSeqMapper constructionSeqMapper
			, UisConstructionNumberGenerator constructionNumberGenerator
			, UisFacilityService facilityService
			, DynamicModelService dynamicModelService
			, UisTaskLyrService uisTaskLyrService
			, UisAccessService uisAccessService) {
		super(constructionSeqMapper, constructionNumberGenerator, dynamicModelService);
		this.facilityService = facilityService;
		this.uisTaskLyrService = uisTaskLyrService;
		this.uisAccessService = uisAccessService;
	}


	/**
	 * 기존 UisBaseController의 createRequestModel 호환성 유지
	 */
	protected Object createRequestModel(String typeId, HttpServletRequest request, boolean isNew) throws Exception {
		return super.createRequestModel(typeId, request, isNew);
	}

	/**
	 * 기존 검색 메서드 (하위 호환성 유지)
	 */
	@GetMapping("/search.do")
	@ResponseBody
	public ResponseEntity<DefaultApiResponse<Map<String, Object>>> searchFacility(HttpServletRequest request) throws Exception {
        SecurityUtil.requirePermission("UIS", "PERM_FUNC_READ");

		try {
            log.info("대장/시설물 검색 요청 시작");

            String typeGb = request.getParameter("typeGb");
            String typeId = "constructions".equals(typeGb)
                ? request.getParameter("ledgerTypeSelect")
                : request.getParameter("facilityTypeSelect");
            typeId = strTypeIdToCamel(typeId);
            
			if (typeId == null || typeId.isEmpty()) {
				return ResponseEntity.badRequest()
					.body(DefaultApiResponse.error(400, "대장/시설물 종류를 선택해주세요.", "BadRequest"));
			}

            log.info("검색 요청 typeId: {}, 파라미터: {}", typeId, request.getParameterMap());

            // 동적 타입 처리 방식 사용
            Object searchVO = createRequestVO(typeId, request);
            List<?> results = facilityService.selectList(searchVO);
            int totalCount = facilityService.selectListTotalCount(searchVO);

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", true);
            resultMap.put("results", results);
            resultMap.put("totalCount", totalCount);

			log.info("시설물검색 완료: {}건 조회됨 / 총 {}건", results != null ? results.size() : 0, totalCount);
			return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
        } catch (RuntimeException e) {
            log.error("시설물검색 중 오류", e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "검색 중 오류가 발생했습니다.", "InternalServerError"));
        }
	}
	

    /**
     * 상세정보 조회
     */
    @GetMapping("/detail.do")
    @ResponseBody
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> getFacilityDetail(
            HttpServletRequest request) throws Exception {
        
        SecurityUtil.requirePermission("UIS", "PERM_FUNC_READ");
        try {
            log.info("상세정보 조회 요청 시작");
            
            final String requestTypeId = request.getParameter("typeId");
            
            // 2025-11-06 seyoung : 사용자 데이터 접근 권한 확인
            if(!uisAccessService.hasAuthrtAccessByTypeId(requestTypeId)) {
                log.warn("접근 권한 없는 사용자입니다.");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "접근 권한이 없습니다", "BadRequest"));
            }
            
            // 현재 선택된 시설물 종류
            final String typeId = strTypeIdToCamel(requestTypeId);
            if (typeId == null || typeId.isEmpty()) {
                log.warn("시설물 종류가 지정되지 않음");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "시설물 종류가 지정되지 않았습니다.", "BadRequest"));
            }
            
            // 키 필드들 확인
            // 2025-09-18 이재룡 : 키 필드는 gid로 통일함
            String gid = request.getParameter("gid");
            
            if (gid == null || gid.isEmpty()) {
                log.warn("조회할 키 값이 지정되지 않음: typeId={}", typeId);
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "조회할 키 값이 지정되지 않았습니다.", "BadRequest"));
            }
            
            log.info("상세정보 조회: typeId={}, gid={}", typeId, gid);
            
            // typeId에 따른 적절한 Model 클래스 생성 (상세조회용)
            // typeId에 따른 Model 클래스명 생성
            Object requestModel = createRequestModel(typeId, request, false);
            
            // 제네릭 서비스 호출 (자동생성된 매퍼 사용)
            Object detail = facilityService.selectDetail(typeId, requestModel);
            ((UisDefaultModel) detail).setTypeId(requestTypeId);
            
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", true);
            resultMap.put("detail", detail);


        	// road/construction.yml 파일에서 대장관리 정보 파싱
            Map<String, Object> ymlData = uisConfigUtils.parseDetailYmlData(requestTypeId);
            String typeGb = (String) ymlData.get("typeGb");
            if(typeGb != null && "facilities".equals(typeGb)) {
	            //TaskLyr 조회
	            UisTaskLyrVO uisTaskLyrVO = new UisTaskLyrVO();
	            uisTaskLyrVO.setLyrSrvcNm(requestTypeId);  
	            UisTaskLyrVO taskLyr = uisTaskLyrService.selectTaskLyr(uisTaskLyrVO);
	            ymlData.put("taskLyrId", taskLyr.getTaskLyrId());
	            ymlData.put("taskLyr", taskLyr);
            }
            
            resultMap.put("ymlData", ymlData);
            
            log.info("상세정보 조회 완료");
            return ResponseEntity.ok(DefaultApiResponse.success(resultMap));

        } catch (RuntimeException e) {
            log.error("상세정보 조회 중 오류 발생", e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "상세정보 조회 중 오류가 발생했습니다.", "InternalServerError"));
        }
    }
    


    /**
     * 상세정보 조회
     */
    @GetMapping("/newDetail.do")
    @ResponseBody
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> getNewDetail(
            HttpServletRequest request) throws Exception {
        
        SecurityUtil.requirePermission("UIS", "PERM_FUNC_READ");
        try {
            log.info("신규등록 조회 요청 시작");
            
            final String requestTypeId = request.getParameter("typeId");

            // 2025-11-06 seyoung : 사용자 데이터 접근 권한 확인
            if(!uisAccessService.hasAuthrtAccessByTypeId(requestTypeId)) {
                log.warn("접근 권한 없는 사용자입니다.");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "접근 권한이 없습니다", "BadRequest"));
            }

            // 현재 선택된 시설물 종류
            final String typeId = strTypeIdToCamel(requestTypeId);
            if (typeId == null || typeId.isEmpty()) {
                log.warn("시설물 종류가 지정되지 않음");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "시설물 종류가 지정되지 않았습니다.", "BadRequest"));
            }
            
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", true);

        	// road/construction.yml 파일에서 대장관리 정보 파싱
            Map<String, Object> ymlData = uisConfigUtils.parseDetailYmlData(requestTypeId);
            String typeGb = (String) ymlData.get("typeGb");
            if(typeGb != null && "facilities".equals(typeGb)) {
	            //TaskLyr 조회
	            UisTaskLyrVO uisTaskLyrVO = new UisTaskLyrVO();
	            uisTaskLyrVO.setLyrSrvcNm(requestTypeId);  
	            UisTaskLyrVO taskLyr = uisTaskLyrService.selectTaskLyr(uisTaskLyrVO);
	            ymlData.put("taskLyrId", taskLyr.getTaskLyrId());
	            ymlData.put("taskLyr", taskLyr);
            }
            resultMap.put("ymlData", ymlData);
            resultMap.put("detail", null);
            
            log.info("신규등록을 위한 yml 조회 완료");
            return ResponseEntity.ok(DefaultApiResponse.success(resultMap));

        } catch (RuntimeException e) {
            log.error("신규등록을 위한 yml 조회 중 오류 발생", e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "신규등록을 위한 yml 조회 중 오류가 발생했습니다.", "InternalServerError"));
        }
    }

    /**
     * 상세 하위 탭 목록 공통 조회
     * 예: /api/uis/construction/detail/{tabId}.do?mngt=..&idn=.. or cidn/cmngt 등
     */
    @GetMapping("/detail/{tabId}")
    @ResponseBody
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> getConstructionDetailTab(
            @PathVariable("tabId") String tabId,
            HttpServletRequest request) throws Exception {
        SecurityUtil.requirePermission("UIS", "PERM_FUNC_READ");
        try {

            // 2025-11-06 seyoung : 사용자 데이터 접근 권한 확인
            if(!uisAccessService.hasAuthrtAccessByTypeId(tabId)) {
                log.warn("접근 권한 없는 사용자입니다.");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "접근 권한이 없습니다", "BadRequest"));
            }

            Map<String, Object> params = new HashMap<>();
            request.getParameterMap().forEach((k, v) -> {
                if (v != null && v.length > 0 && v[0] != null && !v[0].trim().isEmpty()) {
                    params.put(k, v[0].trim());
                }
            });
            
            List<?> results = facilityService.selectDetailTabList(strTypeIdToCamel(tabId), params);
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", true);
            resultMap.put("results", results);
            resultMap.put("totalCount", results != null ? results.size() : 0);
            return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
        } catch (RuntimeException e) {
            log.error("상세 하위 탭 목록 조회 중 오류", e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "하위 목록 조회 중 오류가 발생했습니다.", "InternalServerError"));
        }
    }

    /**
     * 상세정보 페이지 (뷰만 반환)
     */
    @GetMapping("/facilityDetail.do")
    public String facilityDetail(ModelMap model) throws Exception {
        SecurityUtil.requirePermission("UIS", "PERM_FUNC_READ");
        // Tag Layout 방식 - 논리적 뷰 이름만 반환
        return "uis/facility/facilityDetail";
    }

    /**
     * 시설물정보 등록
     */
    @PostMapping("/insert.do")
    @ResponseBody
    @Transactional
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> insertFacility(
            HttpServletRequest request) throws Exception {

        SecurityUtil.requirePermission("UIS", "PERM_FUNC_EDIT");
        try {
            log.info("시설물정보 등록 요청 시작");
            
            String requestTypeId = request.getParameter("typeId");
            String typeId = strTypeIdToCamel(requestTypeId);
            if (typeId == null || typeId.isEmpty()) {
                log.warn("시설물 종류가 지정되지 않음");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "시설물 종류가 지정되지 않았습니다.", "BadRequest"));
            }
            
            //2025-11-06 seyoung : edit 권한 체크
            if(!uisAccessService.hasEditAccessByTypeId(requestTypeId)) {
                log.warn("접근 권한 없는 사용자입니다.");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "접근 권한이 없습니다", "BadRequest"));
            }
            
            // 등록 시에는 useYn="Y" 값 추가 (서버 단에서 추가)
            request.setAttribute("useYn", "Y");
            log.info("등록 요청: typeId={}, 파라미터: {}", typeId, request.getParameterMap());
            
            // typeId에 따른 적절한 Model 클래스 생성 (등록용)
            
            Object requestModel = createRequestModel(typeId, request, true);
            
            // 제네릭 서비스 호출 (자동생성된 매퍼 사용)
            Object result = facilityService.insert(requestModel);
            
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", true);
            resultMap.put("result", result);
            resultMap.put("detail", requestModel);
            
            log.info("시설물정보 등록 완료: typeId={}", typeId);
            return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
        } catch (InvocationTargetException e) {
            Throwable cause = (e.getCause() != null) ? e.getCause() : e;
            log.error("시설물정보 등록 중 내부 메서드 예외 발생", cause);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "등록 중 오류가 발생했습니다.", "InternalServerError"));
        } catch (RuntimeException e) {
            log.error("시설물정보 등록 중 오류 발생", e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "등록 중 오류가 발생했습니다.", "InternalServerError"));
        }
    }

    /**
     * 시설물정보 수정
     */
    @PutMapping("/update.do")
    @ResponseBody
    @Transactional
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> updateFacility(
            HttpServletRequest request) throws Exception {
        
        SecurityUtil.requirePermission("UIS", "PERM_FUNC_EDIT");
        try {
            log.info("시설물정보 수정 요청 시작");
            
            String requestTypeId = request.getParameter("typeId");
            //2025-11-06 seyoung : edit 권한 체크
            if(!uisAccessService.hasEditAccessByTypeId(requestTypeId)) {
                log.warn("접근 권한 없는 사용자입니다.");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "접근 권한이 없습니다", "BadRequest"));
            }
            
            final String typeId = strTypeIdToCamel(requestTypeId);
            if (typeId == null || typeId.isEmpty()) {
                log.warn("시설물 종류가 지정되지 않음");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "시설물 종류가 지정되지 않았습니다.", "BadRequest"));
            }
            
            log.info("수정 요청: typeId={}, 파라미터: {}", typeId, request.getParameterMap());
            
            // typeId에 따른 적절한 Model 클래스 생성 (수정용)
            Object requestModel = createRequestModel(typeId, request, false);
            
            // 제네릭 서비스 호출 (자동생성된 매퍼 사용)
            Object result = facilityService.update(requestModel);
            
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", true);
            resultMap.put("result", result);
            
            log.info("시설물정보 수정 완료: typeId={}", typeId);
            return ResponseEntity.ok(DefaultApiResponse.success(resultMap));

        } catch (RuntimeException e) {
            log.error("시설물정보 수정 중 오류 발생", e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "수정 중 오류가 발생했습니다.", "InternalServerError"));
        }
    }

    /**
     * 시설물정보 삭제
     */
    @DeleteMapping("/delete.do")
    @ResponseBody
    @Transactional
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> deleteFacility(
            HttpServletRequest request) throws Exception {
        
        SecurityUtil.requirePermission("UIS", "PERM_FUNC_EDIT");
        try {
            log.info("시설물정보 삭제 요청 시작");
            
            String requestTypeId = request.getParameter("typeId");
            //2025-11-06 seyoung : edit 권한 체크
            if(!uisAccessService.hasEditAccessByTypeId(requestTypeId)) {
                log.warn("접근 권한 없는 사용자입니다.");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "접근 권한이 없습니다", "BadRequest"));
            }
            
            final String typeId = strTypeIdToCamel(requestTypeId);
            if (typeId == null || typeId.isEmpty()) {
                log.warn("시설물 종류가 지정되지 않음");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "시설물 종류가 지정되지 않았습니다.", "BadRequest"));
            }

            // 삭제 시에는 useYn="N" 값 추가 (서버 단에서 추가)
            request.setAttribute("useYn", "N");
            log.info("삭제 요청: typeId={}, 파라미터: {}", typeId, request.getParameterMap());
            
            // typeId에 따른 적절한 Model 클래스 생성 (삭제용)
            Object requestModel = createRequestModel(typeId, request, false);
            
            // soft delete: use_yn='N' 업데이트 + 이력 테이블에 stts_cd='D' 저장
            Object result = facilityService.delete(requestModel);
            
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("success", true);
            resultMap.put("result", result);
            
            log.info("시설물정보 삭제 완료: typeId={}", typeId);
            return ResponseEntity.ok(DefaultApiResponse.success(resultMap));

        } catch (RuntimeException e) {
            log.error("시설물정보 삭제 중 오류 발생", e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "삭제 중 오류가 발생했습니다.", "InternalServerError"));
        }
    }

    /**
     * 상세정보 조회
     */
    @GetMapping("/searchHistList")
    @ResponseBody
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> getHistList(
            HttpServletRequest request) throws Exception {
        SecurityUtil.requirePermission("UIS", "PERM_FUNC_EDIT");
    	
    	String tableName = request.getParameter("typeId");
    	String gid = request.getParameter("gid");
    	//tableName = "rdl_rdct_l";
    	//String gid = "87542";
    	List<Map<String, Object>> results = facilityService.selectChangeHistoryList(tableName, gid);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("success", true);
        resultMap.put("results", results);

		log.info("이력조회 완료: {}건 조회됨", results != null ? results.size() : 0);
		return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
	}

    /**
     * 연결 팝업 타겟테이블 목록 조회
     * @param request
     * @return
     * @throws Exception
     */
    @GetMapping("/searchConnTargetList")
    @ResponseBody
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> getConnTargetList(
            HttpServletRequest request) throws Exception {
        SecurityUtil.requirePermission("UIS", "PERM_FUNC_EDIT");
    	String tableName = request.getParameter("target");
        Map<String, Object> inputParams = new HashMap<>();
        request.getParameterMap().forEach((k, v) -> {
            if (v != null && v.length > 0 && v[0] != null && !v[0].trim().isEmpty()) {
                inputParams.put(k, v[0].trim());
            }
        });
    	
    	List<Map<String, Object>> results = facilityService.batchTabConnTargetTableSelect(tableName, inputParams);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("success", true);
        resultMap.put("results", results);

		log.info("타겟테이블 목록 조회 완료: {}건 조회됨", results != null ? results.size() : 0);
		return ResponseEntity.ok(DefaultApiResponse.success(resultMap));
	}

    
    /**
     * 연결 팝업 타겟테이블 저장
     * @param request
     * @return
     * @throws Exception
     */
    @PutMapping("/saveConnTarget")
    @ResponseBody
    @Transactional
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> saveConnTarget(
            HttpServletRequest request) throws Exception {

        SecurityUtil.requirePermission("UIS", "PERM_FUNC_EDIT");
        try {
            log.info("연결 테이블 정보 저장 요청 시작");

            final String RELATION_PREFIX = "relation_";
            final String TARGET_PREFIX = "target_";
            // String sourceTableName = (String) request.getParameter("source");
            String relationTableName = (String) request.getParameter("relation");
            String targetTableName = (String) request.getParameter("target");

            boolean isRelation = false;
            if(relationTableName != null && !relationTableName.isEmpty()) {
                isRelation = true;
            } else if(targetTableName != null && !targetTableName.isEmpty()) {
                isRelation = false;
            } else {
                log.warn("연결 테이블이 지정되지 않음");
                return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, "연결 테이블이 지정되지 않았습니다.", "BadRequest"));
            }
            final String tableName = isRelation ? relationTableName : targetTableName;
            
            Map<String, Object> relationParams = new HashMap<>();
            Map<String, Object> targetParams = new HashMap<>();

            request.getParameterMap().forEach((k, v) -> {
                if (v != null && v.length > 0 && v[0] != null && !v[0].trim().isEmpty()) {
                    // 키가 relation_ 로 시작하는 파라미터만 추가
                    if(k.startsWith(RELATION_PREFIX)) {
                        String key = k.substring(RELATION_PREFIX.length());
                        relationParams.put(key, v[0].trim());
                    }
                    // 키가 target_ 로 시작하는 파라미터만 추가
                    if(k.startsWith(TARGET_PREFIX)) {
                        String key = k.substring(TARGET_PREFIX.length());
                        targetParams.put(key, v[0].trim());
                    }
                }
            });

            if(isRelation) {
                /*
                List<Map<String, Object>> result = facilityService.batchTabConnTargetTableInsert(tableName, relationParams);
                if(result.size() == 0) {
                    log.warn("연결 테이블 정보 인서트 실패");
                    return ResponseEntity.badRequest()
                        .body(DefaultApiResponse.error(400, "연결 테이블 정보 인서트 실패", "BadRequest"));
                }
                */
                /** 연결 등록은 공통 등록 로직과 동일하게 사용함. 연결 테이블 정보 저장 시작*/

                String requestTypeId = tableName;
                String typeId = strTypeIdToCamel(requestTypeId);
                HttpServletRequest relationRequest = new HttpServletRequestWrapper(request) {
                    @Override
                    public String getParameter(String name) {
                        Object value = relationParams.get(name);
                        return value != null ? value.toString() : null;
                    }

                    @Override
                    public Map<String, String[]> getParameterMap() {
                        Map<String, String[]> parameterMap = new HashMap<>();
                        relationParams.forEach((key, value) -> {
                            parameterMap.put(key, new String[]{value != null ? value.toString() : ""});
                        });
                        return parameterMap;
                    }

                    @Override
                    public Enumeration<String> getParameterNames() {
                        return Collections.enumeration(relationParams.keySet());
                    }
                };
                
                // 등록 시에는 useYn="Y" 값 추가 (서버 단에서 추가)
                relationRequest.setAttribute("useYn", "Y");
                log.info("등록 요청: typeId={}, 파라미터: {}", typeId, relationRequest.getParameterMap());
                
                // typeId에 따른 적절한 Model 클래스 생성 (등록용)
                
                Object requestModel = createRequestModel(typeId, relationRequest, true);
                
                // 제네릭 서비스 호출 (자동생성된 매퍼 사용)
                Object result = facilityService.insert(requestModel);
                
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("success", true);
                resultMap.put("result", result);
                resultMap.put("detail", requestModel);
                
                log.info("연결정보 등록 완료: typeId={}", typeId);
                return ResponseEntity.ok(DefaultApiResponse.success(resultMap));

                /** 연결 등록은 공통 등록 로직과 동일하게 사용함. 연결 테이블 정보 저장 완료 */
            } else {
                int result = facilityService.batchTabConnTargetTableUpdate(tableName, targetParams);
                if(result == 0) {
                    log.warn("연결 테이블 정보 업데이트 실패");
                    return ResponseEntity.badRequest()
                        .body(DefaultApiResponse.error(400, "연결 테이블 정보 업데이트 실패", "BadRequest"));
                }
                log.info("연결정보 등록 완료: typeId={}", tableName);
                return ResponseEntity.ok(DefaultApiResponse.success(targetParams));
            }
        } catch (RuntimeException e) {
            log.error("연결 테이블 정보 저장 중 오류 발생", e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "연결 테이블 정보 저장 중 오류가 발생했습니다.", "InternalServerError"));
        }
        
    }

    @GetMapping("/hasEditAbleByTypeId")
    @ResponseBody
    public ResponseEntity<DefaultApiResponse<Boolean>> hasEditAbleByTypeId(
            HttpServletRequest request) throws Exception {
        String typeId = request.getParameter("typeId");
        boolean hasEditAble = hasEditAbleByTypeId(typeId);
        return ResponseEntity.ok(DefaultApiResponse.success(hasEditAble));
    }

    /**
     * 특정 카테고리(groupCd) edit 가능 여부 체크
     * @param typeId
     * @return
     */
    private boolean hasEditAbleByTypeId(String typeId) {
        return uisAccessService.hasEditAbleByTypeId(typeId);
    }
}


