package com.erp.controller;

import com.erp.dto.ApiResponse;
import com.erp.service.CommonService;
import com.erp.service.ScreenManagementService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/api/screen-management")
@RequiredArgsConstructor
@Slf4j
public class ScreenManagementController {

    private final ScreenManagementService service;
    private final CommonService commonService;

    // ─── 화면 목록 / 단건 ─────────────────────────────────────

    @GetMapping("/screens")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getScreens(
            @RequestAttribute("company_code") String companyCode,
            @RequestParam Map<String, Object> params) {
        params.put("company_code", params.getOrDefault("company_code", companyCode));
        // 권한 확인: 최고 관리자가 아니면 자사 companyCode만 허용
        String targetCode = (String) params.get("company_code");
        if (!"*".equals(companyCode) && !companyCode.equals(targetCode)) {
            return ResponseEntity.status(403)
                    .body(ApiResponse.error("다른 회사의 화면을 조회할 권한이 없습니다."));
        }
        return ResponseEntity.ok(ApiResponse.success(service.getScreens(params)));
    }

    @GetMapping("/screens/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getScreen(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable("id") Integer screenId) {
        Map<String, Object> screen = service.getScreenById(screenId);
        if (screen == null) {
            return ResponseEntity.status(404).body(ApiResponse.error("화면을 찾을 수 없습니다."));
        }
        return ResponseEntity.ok(ApiResponse.success(screen));
    }

    @GetMapping("/screens/{id}/menu")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getScreenMenu(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable("id") Integer screenId) {
        Map<String, Object> menuInfo = service.getMenuByScreen(screenId, companyCode);
        return ResponseEntity.ok(ApiResponse.success(menuInfo));
    }

    // ─── 화면 생성 / 수정 ──────────────────────────────────────

    @PostMapping("/screens")
    public ResponseEntity<ApiResponse<Map<String, Object>>> createScreen(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @RequestBody Map<String, Object> body) {
        try {
            Map<String, Object> screen = service.createScreen(body, companyCode, userId);
            return ResponseEntity.status(201).body(ApiResponse.success(screen, "화면이 생성되었습니다."));
        } catch (IllegalStateException e) {
            return ResponseEntity.status(409).body(ApiResponse.error("화면 코드가 이미 존재합니다."));
        } catch (Exception e) {
            log.error("화면 생성 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 생성에 실패했습니다."));
        }
    }

    @PutMapping("/screens/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> updateScreen(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable("id") Integer screenId,
            @RequestBody Map<String, Object> body) {
        try {
            Map<String, Object> screen = service.updateScreen(screenId, body, companyCode, userId);
            if (screen == null) return ResponseEntity.status(404).body(ApiResponse.error("화면을 찾을 수 없습니다."));
            return ResponseEntity.ok(ApiResponse.success(screen, "화면이 수정되었습니다."));
        } catch (Exception e) {
            log.error("화면 수정 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 수정에 실패했습니다."));
        }
    }

    @PutMapping("/screens/{id}/info")
    public ResponseEntity<ApiResponse<Map<String, Object>>> updateScreenInfo(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable("id") Integer screenId,
            @RequestBody Map<String, Object> body) {
        try {
            Map<String, Object> screen = service.updateScreenInfo(screenId, body, companyCode, userId);
            if (screen == null) return ResponseEntity.status(404).body(ApiResponse.error("화면을 찾을 수 없습니다."));
            return ResponseEntity.ok(ApiResponse.success(screen, "화면 정보가 수정되었습니다."));
        } catch (Exception e) {
            log.error("화면 정보 수정 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 정보 수정에 실패했습니다."));
        }
    }

    @PatchMapping("/screens/{screenId}/table-name")
    public ResponseEntity<ApiResponse<Map<String, Object>>> updateScreenTableName(
            @RequestAttribute("user_id") String userId,
            @PathVariable Integer screenId,
            @RequestBody Map<String, Object> body) {
        String tableName = (String) body.get("table_name");
        Map<String, Object> screen = service.updateScreenTableName(screenId, tableName, userId);
        if (screen == null) return ResponseEntity.status(404).body(ApiResponse.error("화면을 찾을 수 없습니다."));
        return ResponseEntity.ok(ApiResponse.success(screen));
    }

    // ─── 의존성 / 연결 모달 ────────────────────────────────────

    @GetMapping("/screens/{id}/dependencies")
    public ResponseEntity<ApiResponse<Map<String, Object>>> checkScreenDependencies(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable("id") Integer screenId) {
        Map<String, Object> deps = service.checkScreenDependencies(screenId, companyCode);
        return ResponseEntity.ok(ApiResponse.success(deps));
    }

    @GetMapping("/screens/{id}/linked-modals")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> detectLinkedScreens(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable("id") Integer screenId) {
        List<Map<String, Object>> linked = service.detectLinkedScreens(screenId, companyCode);
        return ResponseEntity.ok(ApiResponse.success(linked));
    }

    // ─── 삭제 ──────────────────────────────────────────────────

    @DeleteMapping("/screens/{id}")
    public ResponseEntity<ApiResponse<Void>> deleteScreen(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable("id") Integer screenId,
            @RequestParam(required = false) String deleteReason) {
        try {
            service.softDeleteScreen(screenId, userId, companyCode, deleteReason);
            return ResponseEntity.ok(ApiResponse.success(null, "화면이 삭제되었습니다."));
        } catch (Exception e) {
            log.error("화면 삭제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 삭제에 실패했습니다."));
        }
    }

    @DeleteMapping("/screens/bulk/delete")
    public ResponseEntity<ApiResponse<Void>> bulkDeleteScreens(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @RequestBody Map<String, Object> body) {
        @SuppressWarnings("unchecked")
        List<Integer> screenIds = (List<Integer>) body.get("screen_ids");
        try {
            service.bulkSoftDeleteScreens(screenIds, userId, companyCode);
            return ResponseEntity.ok(ApiResponse.success(null, screenIds.size() + "개 화면이 삭제되었습니다."));
        } catch (Exception e) {
            log.error("화면 일괄 삭제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 일괄 삭제에 실패했습니다."));
        }
    }

    // ─── 중복 체크 ─────────────────────────────────────────────

    @PostMapping("/screens/check-duplicate-name")
    public ResponseEntity<ApiResponse<Map<String, Object>>> checkDuplicateScreenName(
            @RequestAttribute("company_code") String companyCode,
            @RequestBody Map<String, Object> body) {
        String screenName = (String) body.get("screen_name");
        String targetCode = body.containsKey("company_code") ? (String) body.get("company_code") : companyCode;
        boolean isDuplicate = service.checkDuplicateScreenName(screenName, targetCode);
        return ResponseEntity.ok(ApiResponse.success(Map.of("is_duplicate", isDuplicate)));
    }

    // ─── 복사 ──────────────────────────────────────────────────

    @PostMapping("/screens/{id}/copy")
    public ResponseEntity<ApiResponse<Map<String, Object>>> copyScreen(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable("id") Integer screenId,
            @RequestBody(required = false) Map<String, Object> body) {
        try {
            String newName = body != null ? (String) body.get("new_name") : null;
            Map<String, Object> screen = service.copyScreen(screenId, newName, companyCode, userId);
            return ResponseEntity.status(201).body(ApiResponse.success(screen, "화면이 복사되었습니다."));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(404).body(ApiResponse.error(e.getMessage()));
        } catch (Exception e) {
            log.error("화면 복사 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 복사에 실패했습니다."));
        }
    }

    @PostMapping("/screens/{id}/copy-with-modals")
    public ResponseEntity<ApiResponse<Map<String, Object>>> copyScreenWithModals(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable("id") Integer screenId,
            @RequestBody Map<String, Object> body) {
        try {
            Map<String, Object> result = service.copyScreenWithModals(screenId, body, companyCode, userId);
            return ResponseEntity.status(201).body(ApiResponse.success(result, "화면과 모달이 복사되었습니다."));
        } catch (Exception e) {
            log.error("화면 + 모달 복사 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 복사에 실패했습니다."));
        }
    }

    // ─── 휴지통 ────────────────────────────────────────────────

    @GetMapping("/screens/trash/list")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getDeletedScreens(
            @RequestAttribute("company_code") String companyCode,
            @RequestParam Map<String, Object> params) {
        params.put("company_code", companyCode);
        Map<String, Object> result = service.getDeletedScreens(params);
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> list = (List<Map<String, Object>>) result.get("data");
        return ResponseEntity.ok(ApiResponse.success(list));
    }

    @PostMapping("/screens/{id}/restore")
    public ResponseEntity<ApiResponse<Map<String, Object>>> restoreScreen(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable("id") Integer screenId) {
        try {
            Map<String, Object> screen = service.restoreScreen(screenId, userId, companyCode);
            return ResponseEntity.ok(ApiResponse.success(screen, "화면이 복원되었습니다."));
        } catch (IllegalStateException e) {
            return ResponseEntity.status(409).body(ApiResponse.error("화면 코드가 이미 사용 중입니다."));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(404).body(ApiResponse.error(e.getMessage()));
        } catch (Exception e) {
            log.error("화면 복원 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 복원에 실패했습니다."));
        }
    }

    @DeleteMapping("/screens/{id}/permanent")
    public ResponseEntity<ApiResponse<Void>> permanentDeleteScreen(
            @PathVariable("id") Integer screenId) {
        try {
            service.permanentDeleteScreen(screenId);
            return ResponseEntity.ok(ApiResponse.success(null, "화면이 영구 삭제되었습니다."));
        } catch (Exception e) {
            log.error("화면 영구 삭제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 영구 삭제에 실패했습니다."));
        }
    }

    @DeleteMapping("/screens/trash/bulk")
    public ResponseEntity<ApiResponse<Void>> bulkPermanentDeleteScreens(
            @RequestBody Map<String, Object> body) {
        @SuppressWarnings("unchecked")
        List<Integer> screenIds = (List<Integer>) body.get("screen_ids");
        try {
            service.bulkPermanentDeleteScreens(screenIds);
            return ResponseEntity.ok(ApiResponse.success(null, screenIds.size() + "개 화면이 영구 삭제되었습니다."));
        } catch (Exception e) {
            log.error("화면 일괄 영구 삭제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 일괄 영구 삭제에 실패했습니다."));
        }
    }

    // ─── 화면 코드 생성 ────────────────────────────────────────

    @GetMapping("/generate-screen-code/{companyCode}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> generateScreenCode(
            @PathVariable String companyCode) {
        try {
            String code = service.generateScreenCode(companyCode);
            return ResponseEntity.ok(ApiResponse.success(Map.of("screen_code", code)));
        } catch (Exception e) {
            log.error("화면 코드 생성 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 코드 생성에 실패했습니다."));
        }
    }

    @PostMapping("/generate-screen-codes")
    public ResponseEntity<ApiResponse<Map<String, Object>>> generateMultipleScreenCodes(
            @RequestBody Map<String, Object> body) {
        String companyCode = (String) body.get("company_code");
        int count = body.get("count") != null ? Integer.parseInt(body.get("count").toString()) : 1;
        try {
            List<String> codes = service.generateMultipleScreenCodes(companyCode, count);
            return ResponseEntity.ok(ApiResponse.success(Map.of("screen_codes", codes)));
        } catch (Exception e) {
            log.error("화면 코드 일괄 생성 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("화면 코드 생성에 실패했습니다."));
        }
    }

    // ─── 테이블 관리 ───────────────────────────────────────────

    @GetMapping("/tables")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getTables() {
        return ResponseEntity.ok(ApiResponse.success(service.getTables()));
    }

    @GetMapping("/tables/{tableName}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getTableInfo(
            @PathVariable String tableName) {
        Map<String, Object> info = service.getTableInfo(tableName);
        if (info == null) return ResponseEntity.status(404).body(ApiResponse.error("테이블을 찾을 수 없습니다."));
        return ResponseEntity.ok(ApiResponse.success(info));
    }

    @GetMapping("/tables/{tableName}/columns")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getTableColumns(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable String tableName) {
        return ResponseEntity.ok(ApiResponse.success(service.getTableColumns(tableName, companyCode)));
    }

    // ─── 레이아웃 V1 ───────────────────────────────────────────

    @PostMapping("/screens/{screenId}/layout")
    public ResponseEntity<ApiResponse<Void>> saveLayout(
            @RequestAttribute("user_id") String userId,
            @PathVariable Integer screenId,
            @RequestBody Map<String, Object> body) {
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> components = (List<Map<String, Object>>) body.get("components");
        if (components == null) components = List.of();
        try {
            service.saveLayout(screenId, components, userId);
            return ResponseEntity.ok(ApiResponse.success(null, "레이아웃이 저장되었습니다."));
        } catch (Exception e) {
            log.error("레이아웃 저장 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("레이아웃 저장에 실패했습니다."));
        }
    }

    @GetMapping("/screens/{screenId}/layout")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getLayout(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId) {
        return ResponseEntity.ok(ApiResponse.success(service.getLayout(screenId, companyCode)));
    }

    @GetMapping("/screens/{screenId}/layout-v1")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getLayoutV1(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId) {
        Map<String, Object> result = service.getLayoutV1WithTransform(screenId, companyCode);
        if (result == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    // ─── 레이아웃 V2 ───────────────────────────────────────────

    @GetMapping("/screens/{screenId}/layout-v2")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getLayoutV2(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId,
            @RequestParam(required = false) Integer layerId) {
        Map<String, Object> layout = service.getLayoutV2(screenId, companyCode, layerId);
        return ResponseEntity.ok(ApiResponse.success(layout));
    }

    @PostMapping("/screens/{screenId}/layout-v2")
    public ResponseEntity<ApiResponse<Void>> saveLayoutV2(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable Integer screenId,
            @RequestBody Map<String, Object> body) {
        try {
            service.saveLayoutV2(screenId, body, companyCode, userId);
            return ResponseEntity.ok(ApiResponse.success(null, "레이아웃 V2가 저장되었습니다."));
        } catch (Exception e) {
            log.error("레이아웃 V2 저장 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("레이아웃 저장에 실패했습니다."));
        }
    }

    // ─── POP 레이아웃 ──────────────────────────────────────────

    @GetMapping("/screens/{screenId}/layout-pop")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getLayoutPop(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId) {
        return ResponseEntity.ok(ApiResponse.success(service.getLayoutPop(screenId, companyCode)));
    }

    @PostMapping("/screens/{screenId}/layout-pop")
    public ResponseEntity<ApiResponse<Void>> saveLayoutPop(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable Integer screenId,
            @RequestBody Map<String, Object> body) {
        try {
            service.saveLayoutPop(screenId, body, companyCode, userId);
            return ResponseEntity.ok(ApiResponse.success(null, "POP 레이아웃이 저장되었습니다."));
        } catch (Exception e) {
            log.error("POP 레이아웃 저장 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("POP 레이아웃 저장에 실패했습니다."));
        }
    }

    @DeleteMapping("/screens/{screenId}/layout-pop")
    public ResponseEntity<ApiResponse<Void>> deleteLayoutPop(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId) {
        service.deleteLayoutPop(screenId, companyCode);
        return ResponseEntity.ok(ApiResponse.success(null, "POP 레이아웃이 삭제되었습니다."));
    }

    @GetMapping("/pop-layout-screen-ids")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getScreenIdsWithPopLayout(
            @RequestAttribute("company_code") String companyCode) {
        return ResponseEntity.ok(ApiResponse.success(service.getScreenIdsWithPopLayout(companyCode)));
    }

    // ─── 레이어 관리 ───────────────────────────────────────────

    @GetMapping("/screens/{screenId}/layers")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getScreenLayers(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId) {
        return ResponseEntity.ok(ApiResponse.success(service.getScreenLayers(screenId, companyCode)));
    }

    @GetMapping("/screens/{screenId}/layers/{layerId}/layout")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getLayerLayout(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId,
            @PathVariable Integer layerId) {
        Map<String, Object> layout = service.getLayerLayout(screenId, layerId, companyCode);
        return ResponseEntity.ok(ApiResponse.success(layout));
    }

    @DeleteMapping("/screens/{screenId}/layers/{layerId}")
    public ResponseEntity<ApiResponse<Void>> deleteLayer(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId,
            @PathVariable Integer layerId) {
        boolean deleted = service.deleteLayer(screenId, layerId, companyCode);
        if (!deleted) return ResponseEntity.status(404).body(ApiResponse.error("레이어를 찾을 수 없습니다."));
        return ResponseEntity.ok(ApiResponse.success(null, "레이어가 삭제되었습니다."));
    }

    @PutMapping("/screens/{screenId}/layers/{layerId}/condition")
    public ResponseEntity<ApiResponse<Void>> updateLayerCondition(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId,
            @PathVariable Integer layerId,
            @RequestBody Map<String, Object> body) {
        service.updateLayerCondition(screenId, layerId, body, companyCode);
        return ResponseEntity.ok(ApiResponse.success(null, "레이어 조건이 업데이트되었습니다."));
    }

    // ─── Zone 관리 ─────────────────────────────────────────────

    @GetMapping("/screens/{screenId}/zones")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getScreenZones(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId) {
        return ResponseEntity.ok(ApiResponse.success(service.getScreenZones(screenId, companyCode)));
    }

    @PostMapping("/screens/{screenId}/zones")
    public ResponseEntity<ApiResponse<Map<String, Object>>> createZone(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId,
            @RequestBody Map<String, Object> body) {
        try {
            Map<String, Object> result = service.createZone(screenId, body, companyCode);
            return ResponseEntity.status(201).body(ApiResponse.success(result, "Zone이 생성되었습니다."));
        } catch (Exception e) {
            log.error("Zone 생성 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("Zone 생성에 실패했습니다."));
        }
    }

    @PutMapping("/zones/{zoneId}")
    public ResponseEntity<ApiResponse<Void>> updateZone(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer zoneId,
            @RequestBody Map<String, Object> body) {
        boolean updated = service.updateZone(zoneId, body, companyCode);
        if (!updated) return ResponseEntity.status(404).body(ApiResponse.error("Zone을 찾을 수 없습니다."));
        return ResponseEntity.ok(ApiResponse.success(null, "Zone이 수정되었습니다."));
    }

    @DeleteMapping("/zones/{zoneId}")
    public ResponseEntity<ApiResponse<Void>> deleteZone(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer zoneId) {
        boolean deleted = service.deleteZone(zoneId, companyCode);
        if (!deleted) return ResponseEntity.status(404).body(ApiResponse.error("Zone을 찾을 수 없습니다."));
        return ResponseEntity.ok(ApiResponse.success(null, "Zone이 삭제되었습니다."));
    }

    @PostMapping("/screens/{screenId}/zones/{zoneId}/layers")
    public ResponseEntity<ApiResponse<Map<String, Object>>> addLayerToZone(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId,
            @PathVariable Integer zoneId,
            @RequestBody(required = false) Map<String, Object> body) {
        if (body == null) body = Map.of();
        try {
            Map<String, Object> result = service.addLayerToZone(screenId, zoneId, body, companyCode);
            return ResponseEntity.status(201).body(ApiResponse.success(result, "레이어가 추가되었습니다."));
        } catch (Exception e) {
            log.error("레이어 추가 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("레이어 추가에 실패했습니다."));
        }
    }

    // ─── 메뉴-화면 할당 ────────────────────────────────────────

    @PostMapping("/screens/{screenId}/assign-menu")
    public ResponseEntity<ApiResponse<Map<String, Object>>> assignScreenToMenu(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable Integer screenId,
            @RequestBody Map<String, Object> body) {
        try {
            Map<String, Object> result = service.assignScreenToMenu(screenId, body, companyCode, userId);
            return ResponseEntity.status(201).body(ApiResponse.success(result, "메뉴에 화면이 할당되었습니다."));
        } catch (IllegalStateException e) {
            return ResponseEntity.status(409).body(ApiResponse.error("이미 할당된 메뉴입니다."));
        } catch (Exception e) {
            log.error("메뉴 할당 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("메뉴 할당에 실패했습니다."));
        }
    }

    @GetMapping("/menus/{menuObjid}/screens")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getScreensByMenu(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable String menuObjid) {
        return ResponseEntity.ok(ApiResponse.success(service.getScreensByMenu(menuObjid, companyCode)));
    }

    @DeleteMapping("/screens/{screenId}/menus/{menuObjid}")
    public ResponseEntity<ApiResponse<Void>> unassignScreenFromMenu(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId,
            @PathVariable String menuObjid) {
        try {
            service.unassignScreenFromMenu(screenId, menuObjid, companyCode);
            return ResponseEntity.ok(ApiResponse.success(null, "메뉴 할당이 해제되었습니다."));
        } catch (Exception e) {
            log.error("메뉴 할당 해제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("메뉴 할당 해제에 실패했습니다."));
        }
    }

    @PostMapping("/admin/cleanup-deleted-screen-menu-assignments")
    public ResponseEntity<ApiResponse<Map<String, Object>>> cleanupDeletedScreenMenuAssignments() {
        int count = service.cleanupDeletedMenuAssignments();
        return ResponseEntity.ok(ApiResponse.success(Map.of("count", count), count + "개 메뉴 할당이 정리되었습니다."));
    }

    // ─── 탭 참조 업데이트 ──────────────────────────────────────

    @PostMapping("/screens/update-tab-references")
    public ResponseEntity<ApiResponse<Void>> updateTabScreenReferences(
            @RequestBody Map<String, Object> body) {
        try {
            service.updateTabScreenReferences(body);
            return ResponseEntity.ok(ApiResponse.success(null, "탭 참조가 업데이트되었습니다."));
        } catch (Exception e) {
            log.error("탭 참조 업데이트 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("탭 참조 업데이트에 실패했습니다."));
        }
    }

    // ─── 복제 작업 ─────────────────────────────────────────────

    @PostMapping("/copy-menu-assignments")
    public ResponseEntity<ApiResponse<Map<String, Object>>> copyScreenMenuAssignments(
            @RequestBody Map<String, Object> body) {
        try {
            int count = service.copyScreenMenuAssignments(body);
            return ResponseEntity.ok(ApiResponse.success(Map.of("count", count)));
        } catch (Exception e) {
            log.error("메뉴 할당 복제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("메뉴 할당 복제에 실패했습니다."));
        }
    }

    @PostMapping("/copy-code-category")
    public ResponseEntity<ApiResponse<Map<String, Object>>> copyCodeInfoAndCodes(
            @RequestBody Map<String, Object> body) {
        try {
            int count = service.copyCodeInfoAndCodes(body);
            return ResponseEntity.ok(ApiResponse.success(Map.of("count", count)));
        } catch (Exception e) {
            log.error("코드 카테고리 복제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("코드 카테고리 복제에 실패했습니다."));
        }
    }

    @PostMapping("/copy-category-mapping")
    public ResponseEntity<ApiResponse<Map<String, Object>>> copyCategoryMapping(
            @RequestBody Map<String, Object> body) {
        try {
            int count = service.copyCategoryMapping(body);
            return ResponseEntity.ok(ApiResponse.success(Map.of("count", count)));
        } catch (Exception e) {
            log.error("카테고리 매핑 복제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("카테고리 매핑 복제에 실패했습니다."));
        }
    }

    @PostMapping("/copy-table-type-columns")
    public ResponseEntity<ApiResponse<Map<String, Object>>> copyTableTypeColumns(
            @RequestBody Map<String, Object> body) {
        try {
            int count = service.copyTableTypeColumns(body);
            return ResponseEntity.ok(ApiResponse.success(Map.of("count", count)));
        } catch (Exception e) {
            log.error("테이블 타입 컬럼 복제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("테이블 타입 컬럼 복제에 실패했습니다."));
        }
    }

    @PostMapping("/copy-cascading-relation")
    public ResponseEntity<ApiResponse<Map<String, Object>>> copyCascadingRelation(
            @RequestBody Map<String, Object> body) {
        try {
            int count = service.copyCascadingRelation(body);
            return ResponseEntity.ok(ApiResponse.success(Map.of("count", count)));
        } catch (Exception e) {
            log.error("연쇄관계 복제 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("연쇄관계 복제에 실패했습니다."));
        }
    }

    // ─── POP 화면 배포 ─────────────────────────────────────────

    @GetMapping("/screens/{screenId}/pop-links")
    public ResponseEntity<ApiResponse<Map<String, Object>>> analyzePopScreenLinks(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Integer screenId) {
        return ResponseEntity.ok(ApiResponse.success(service.analyzePopScreenLinks(screenId, companyCode)));
    }

    @PostMapping("/deploy-pop-screens")
    public ResponseEntity<ApiResponse<Map<String, Object>>> deployPopScreens(
            @RequestAttribute("user_id") String userId,
            @RequestBody Map<String, Object> body) {
        try {
            Map<String, Object> result = service.deployPopScreens(body, userId);
            return ResponseEntity.ok(ApiResponse.success(result, "POP 화면 배포가 완료되었습니다."));
        } catch (Exception e) {
            log.error("POP 화면 배포 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("POP 화면 배포에 실패했습니다."));
        }
    }
}
