package incheon.ags.mrb.chart.web;

import incheon.ags.mrb.chart.web.dto.ChartQueryParams;
import incheon.ags.mrb.chart.service.ChartDataService;
import incheon.cmm.g2f.layer.mapper.G2FLayerMapper;
import incheon.com.cmm.api.DefaultApiResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;

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

@RestController
@RequestMapping("/ags/mrb/chart")
public class ChartApiController {

    private final static Logger logger = LoggerFactory.getLogger(ChartApiController.class);

    @Autowired
    private ChartDataService chartDataService;

    @Autowired
    private G2FLayerMapper g2fLayerMapper;

    @PostMapping("/api/data.do")
    public ResponseEntity<List<Map<String, Object>>> getChartData(@RequestBody ChartQueryParams params) {
        List<Map<String, Object>> results = chartDataService.getChartData(params);
        return ResponseEntity.ok(results);
    }

    @PostMapping("/api/save.do")
    public ResponseEntity<Map<String, Object>> saveChart(@RequestBody Map<String, Object> request)
            throws JsonProcessingException {
        Map<String, Object> chartConfig = (Map<String, Object>) request.get("chartConfig");
        logger.debug("Received chartConfig: {}", chartConfig);
        int chartId = chartDataService.saveChartConfig(chartConfig);
        return ResponseEntity.ok(Map.of("chartId", chartId));
    }

    @GetMapping("/api/load.do")
    public ResponseEntity<Map<String, Object>> loadChart(@RequestParam int chartId)
            throws JsonMappingException, JsonProcessingException {
        Map<String, Object> data = chartDataService.loadChartConfig(chartId);
        if (data == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(data);
    }

    @GetMapping("/api/list.do")
    public ResponseEntity<List<Map<String, Object>>> listCharts() {
        List<Map<String, Object>> charts = chartDataService.getChartList();
        logger.debug("Received charts: {}", charts);
        return ResponseEntity.ok(charts);
    }

    @PostMapping("/api/delete.do")
    public ResponseEntity<Map<String, Object>> deleteChart(@RequestBody Map<String, Integer> request) {
        Integer chartId = request.get("chartId");
        if (chartId == null) {
            return ResponseEntity.badRequest().body(Map.of("error", "chartId is required"));
        }
        try {
            chartDataService.deleteChartConfig(chartId);
            return ResponseEntity.ok(Map.of("message", "Chart deleted successfully"));
        } catch (IllegalArgumentException e) {
            logger.error(e.getMessage(), e);
            return ResponseEntity.status(500).body(Map.of("error", "No chart found with chartId: " + chartId));
        }
    }

    /**
     * 테이블 컬럼 정보 조회 API
     * 
     * @param tableName 물리 테이블명 (예: public.incheon_bus_stations,
     *                  icext.tl_scco_ctprvn)
     * @return 컬럼 정보 리스트 (column_name, data_type, is_nullable 등)
     */
    @GetMapping("/api/columns")
    public ResponseEntity<DefaultApiResponse<List<Map<String, Object>>>> getTableColumns(
            @RequestParam String tableName) {
        try {
            List<Map<String, Object>> columns = chartDataService.getTableColumns(tableName);
            return ResponseEntity.ok(DefaultApiResponse.success(columns));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400, e.getMessage(), "INVALID_TABLE_NAME"));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500, "테이블 컬럼 조회 실패: " + tableName, "SERVER_ERROR"));
        }
    }

    /**
     * layerId로 테이블 컬럼 정보 조회 API
     * G2FLayerService 로직을 활용하여 물리 테이블명 조회 후 컬럼 정보 반환
     * 
     * @param layerId   레이어 ID
     * @param layerType 레이어 타입 (TASK 또는 USER)
     * @return 컬럼 정보 리스트 (column_name, data_type, is_nullable 등)
     */
    @GetMapping("/api/columns/by-layer")
    public ResponseEntity<DefaultApiResponse<List<Map<String, Object>>>> getTableColumnsByLayerId(
            @RequestParam String layerId,
            @RequestParam String layerType) {
        try {
            // 1. 레이어 메타데이터 조회 (G2FLayerService 코드 활용)
            Map<String, Object> layerMeta = null;
            if ("TASK".equals(layerType)) {
                layerMeta = g2fLayerMapper.selectTaskLayerMetadata(layerId);
            } else if ("USER".equals(layerType)) {
                layerMeta = g2fLayerMapper.selectUserLayerMetadata(layerId);
            } else {
                throw new IllegalArgumentException("레이어 타입은 TASK 또는 USER만 가능합니다: " + layerType);
            }

            if (layerMeta == null) {
                throw new IllegalArgumentException("레이어를 찾을 수 없습니다: " + layerId);
            }

            // 2. 물리명 추출
            String lyrPhysNm = (String) layerMeta.get("lyr_phys_nm");
            if (lyrPhysNm == null || !lyrPhysNm.contains(".")) {
                throw new IllegalArgumentException("레이어 물리명이 유효하지 않습니다: " + lyrPhysNm);
            }

            // 3. 기존 서비스 메서드 호출 (Service는 안 건드림!)
            List<Map<String, Object>> columns = chartDataService.getTableColumns(lyrPhysNm);
            return ResponseEntity.ok(DefaultApiResponse.success(columns));

        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest()
                    .body(DefaultApiResponse.error(400,
                            "레이어 컬럼 조회 실패: layerId: " + layerId + ", layerType: " + layerType, "INVALID_LAYER"));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ResponseEntity.status(500)
                    .body(DefaultApiResponse.error(500,
                            "레이어 컬럼 조회 실패: layerId: " + layerId + ", layerType: " + layerType, "SERVER_ERROR"));
        }
    }
}
