package com.erp.controller;

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

@RestController
@RequestMapping("/api/digital-twin")
@RequiredArgsConstructor
@Slf4j
public class DigitalTwinController {

    private final DigitalTwinService digitalTwinService;

    // ========== 레이아웃 관리 API ==========

    /** GET /layouts → 레이아웃 목록 */
    @GetMapping("/layouts")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getDigitalTwinLayoutList(
            @RequestAttribute("company_code") String companyCode,
            @RequestParam Map<String, Object> params) {
        params.put("company_code", companyCode);
        return ResponseEntity.ok(ApiResponse.success(digitalTwinService.getDigitalTwinLayoutList(params)));
    }

    /** GET /layouts/:id → 레이아웃 상세 (객체 포함) */
    @GetMapping("/layouts/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getDigitalTwinLayoutInfo(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Long id) {
        Map<String, Object> params = new HashMap<>();
        params.put("company_code", companyCode);
        params.put("id", id);
        Map<String, Object> result = digitalTwinService.getDigitalTwinLayoutInfo(params);
        if (result == null) {
            return ResponseEntity.status(404).body(ApiResponse.error("레이아웃을 찾을 수 없습니다."));
        }
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** POST /layouts → 레이아웃 생성 */
    @PostMapping("/layouts")
    public ResponseEntity<ApiResponse<Map<String, Object>>> createDigitalTwinLayout(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute(value = "user_id", required = false) String userId,
            @RequestBody Map<String, Object> body) {
        body.put("company_code", companyCode);
        body.put("created_by", userId);
        Map<String, Object> result = digitalTwinService.createDigitalTwinLayout(body);
        return ResponseEntity.status(201).body(ApiResponse.success(result));
    }

    /** PUT /layouts/:id → 레이아웃 수정 */
    @PutMapping("/layouts/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> updateDigitalTwinLayout(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute(value = "user_id", required = false) String userId,
            @PathVariable Long id,
            @RequestBody Map<String, Object> body) {
        body.put("company_code", companyCode);
        body.put("updated_by", userId);
        body.put("id", id);
        Map<String, Object> result = digitalTwinService.updateDigitalTwinLayout(body);
        if (result == null) {
            return ResponseEntity.status(404).body(ApiResponse.error("레이아웃을 찾을 수 없습니다."));
        }
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** DELETE /layouts/:id → 레이아웃 삭제 */
    @DeleteMapping("/layouts/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> deleteDigitalTwinLayout(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Long id) {
        Map<String, Object> params = new HashMap<>();
        params.put("company_code", companyCode);
        params.put("id", id);
        boolean deleted = digitalTwinService.deleteDigitalTwinLayout(params);
        if (!deleted) {
            return ResponseEntity.status(404).body(ApiResponse.error("레이아웃을 찾을 수 없습니다."));
        }
        return ResponseEntity.ok(ApiResponse.success(null, "레이아웃이 삭제되었습니다."));
    }

    // ========== 매핑 템플릿 API ==========

    /** GET /mapping-templates → 매핑 템플릿 목록 */
    @GetMapping("/mapping-templates")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getDigitalTwinTemplateList(
            @RequestAttribute("company_code") String companyCode,
            @RequestParam Map<String, Object> params) {
        params.put("company_code", companyCode);
        return ResponseEntity.ok(ApiResponse.success(digitalTwinService.getDigitalTwinTemplateList(params)));
    }

    /** GET /mapping-templates/:id → 매핑 템플릿 상세 */
    @GetMapping("/mapping-templates/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getDigitalTwinTemplateInfo(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Long id) {
        Map<String, Object> params = new HashMap<>();
        params.put("company_code", companyCode);
        params.put("id", id);
        Map<String, Object> result = digitalTwinService.getDigitalTwinTemplateInfo(params);
        if (result == null) {
            return ResponseEntity.status(404).body(ApiResponse.error("매핑 템플릿을 찾을 수 없습니다."));
        }
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** POST /mapping-templates → 매핑 템플릿 생성 */
    @PostMapping("/mapping-templates")
    public ResponseEntity<ApiResponse<Map<String, Object>>> createDigitalTwinTemplate(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute(value = "user_id", required = false) String userId,
            @RequestBody Map<String, Object> body) {
        if (body.get("name") == null || body.get("external_db_connection_id") == null || body.get("config") == null) {
            return ResponseEntity.status(400).body(ApiResponse.error("필수 필드가 누락되었습니다. (name, externalDbConnectionId, config)"));
        }
        body.put("company_code", companyCode);
        body.put("created_by", userId);
        Map<String, Object> result = digitalTwinService.createDigitalTwinTemplate(body);
        return ResponseEntity.status(201).body(ApiResponse.success(result));
    }

    // ========== 외부 DB 데이터 조회 API ==========

    /** POST /data/hierarchy → 전체 계층 데이터 조회 */
    @PostMapping("/data/hierarchy")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getHierarchyData(
            @RequestBody Map<String, Object> body) {
        if (body.get("external_db_connection_id") == null || body.get("hierarchy_config") == null) {
            return ResponseEntity.status(400).body(
                    ApiResponse.error("외부 DB 연결 ID와 계층 구조 설정이 필요합니다."));
        }
        Map<String, Object> result = digitalTwinService.getHierarchyData(body);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** POST /data/children → 특정 부모의 하위 데이터 조회 */
    @PostMapping("/data/children")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getChildrenData(
            @RequestBody Map<String, Object> body) {
        if (body.get("external_db_connection_id") == null || body.get("hierarchy_config") == null
                || body.get("parent_level") == null || body.get("parent_key") == null) {
            return ResponseEntity.status(400).body(ApiResponse.error("필수 파라미터가 누락되었습니다."));
        }
        List<Map<String, Object>> result = digitalTwinService.getChildrenData(body);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** GET /data/tables/:connectionId → 테이블 목록 */
    @GetMapping("/data/tables/{connectionId}")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getExternalTables(
            @PathVariable Long connectionId) {
        List<Map<String, Object>> result = digitalTwinService.getExternalTables(connectionId);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** GET /data/table-preview/:connectionId/:tableName → 테이블 미리보기 */
    @GetMapping("/data/table-preview/{connectionId}/{tableName}")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getTablePreview(
            @PathVariable Long connectionId,
            @PathVariable String tableName) {
        List<Map<String, Object>> result = digitalTwinService.getTablePreview(connectionId, tableName);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** GET /data/warehouses → 창고 목록 (레거시) */
    @GetMapping("/data/warehouses")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getWarehouses(
            @RequestParam Long externalDbConnectionId,
            @RequestParam String tableName) {
        if (externalDbConnectionId == null) {
            return ResponseEntity.status(400).body(ApiResponse.error("외부 DB 연결 ID가 필요합니다."));
        }
        List<Map<String, Object>> result = digitalTwinService.getWarehouses(externalDbConnectionId, tableName);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** GET /data/areas → 구역 목록 (레거시) */
    @GetMapping("/data/areas")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getAreas(
            @RequestParam Long externalDbConnectionId,
            @RequestParam String warehouseKey,
            @RequestParam String tableName) {
        List<Map<String, Object>> result = digitalTwinService.getAreas(externalDbConnectionId, tableName, warehouseKey);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** GET /data/locations → 위치 목록 (레거시) */
    @GetMapping("/data/locations")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getLocations(
            @RequestParam Long externalDbConnectionId,
            @RequestParam String areaKey,
            @RequestParam String tableName) {
        List<Map<String, Object>> result = digitalTwinService.getLocations(externalDbConnectionId, tableName, areaKey);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** GET /data/materials → 자재 목록 (레거시) */
    @GetMapping("/data/materials")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getMaterials(
            @RequestParam Long externalDbConnectionId,
            @RequestParam String locaKey,
            @RequestParam String tableName,
            @RequestParam String locationKeyColumn,
            @RequestParam(required = false) String layerColumn) {
        List<Map<String, Object>> result = digitalTwinService.getMaterials(
                externalDbConnectionId, tableName, locaKey, locationKeyColumn, layerColumn);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /** POST /data/material-counts → 자재 개수 (여러 Location, 레거시) */
    @PostMapping("/data/material-counts")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getMaterialCounts(
            @RequestBody Map<String, Object> body) {
        if (body.get("external_db_connection_id") == null || body.get("location_keys") == null
                || body.get("table_name") == null) {
            return ResponseEntity.status(400).body(ApiResponse.error("필수 파라미터가 누락되었습니다."));
        }
        List<Map<String, Object>> result = digitalTwinService.getMaterialCounts(body);
        return ResponseEntity.ok(ApiResponse.success(result));
    }
}
