package com.erp.controller;

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

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

/**
 * 플로우 전용 외부 DB 연결 컨트롤러
 *
 * GET    /api/flow-external-db                                  - 목록 (?activeOnly=true)
 * GET    /api/flow-external-db/{id}                             - 단건
 * POST   /api/flow-external-db                                  - 생성
 * PUT    /api/flow-external-db/{id}                             - 수정
 * DELETE /api/flow-external-db/{id}                             - 삭제
 * POST   /api/flow-external-db/{id}/test                        - 연결 테스트
 * GET    /api/flow-external-db/{id}/tables                      - 테이블 목록
 * GET    /api/flow-external-db/{id}/tables/{tableName}/columns  - 컬럼 목록
 */
@RestController
@RequestMapping("/api/flow-external-db")
@RequiredArgsConstructor
@Slf4j
public class FlowExternalDbConnectionController {

    private final FlowExternalDbConnectionService service;

    @GetMapping
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getAll(
            @RequestAttribute(value = "company_code", required = false) String companyCode,
            @RequestParam(required = false, defaultValue = "false") String activeOnly) {
        try {
            boolean active = "true".equalsIgnoreCase(activeOnly);
            List<Map<String, Object>> connections = service.findAll(active);
            return ResponseEntity.ok(ApiResponse.success(connections,
                    connections.size() + "개의 외부 DB 연결을 조회했습니다"));
        } catch (Exception e) {
            log.error("외부 DB 연결 목록 조회 오류", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("외부 DB 연결 목록 조회 중 오류가 발생했습니다"));
        }
    }

    @GetMapping("/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getById(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable int id) {
        try {
            Map<String, Object> conn = service.findById(id);
            if (conn == null) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("외부 DB 연결을 찾을 수 없습니다"));
            }
            return ResponseEntity.ok(ApiResponse.success(conn));
        } catch (Exception e) {
            log.error("외부 DB 연결 조회 오류: id={}", id, e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("외부 DB 연결 조회 중 오류가 발생했습니다"));
        }
    }

    @PostMapping
    public ResponseEntity<ApiResponse<Map<String, Object>>> create(
            @RequestAttribute("company_code") String companyCode,
            @RequestBody Map<String, Object> body) {
        // 필수 필드 검증
        if (isBlank(body, "name") || isBlank(body, "db_type") || isBlank(body, "db_type") && isBlank(body, "db_type")
                || isBlank(body, "host") || body.get("port") == null
                || isBlank(body, "database_name") && isBlank(body, "database_name")
                || isBlank(body, "username") || isBlank(body, "password")) {
            return ResponseEntity.status(400)
                    .body(ApiResponse.error("필수 필드가 누락되었습니다"));
        }
        try {
            String userId = companyCode != null ? companyCode : "system";
            Map<String, Object> conn = service.create(body, userId);
            log.info("외부 DB 연결 생성: {}", conn.get("name"));
            return ResponseEntity.status(HttpStatus.CREATED)
                    .body(ApiResponse.success(conn, "외부 DB 연결이 생성되었습니다"));
        } catch (Exception e) {
            log.error("외부 DB 연결 생성 오류", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("외부 DB 연결 생성 중 오류가 발생했습니다"));
        }
    }

    @PutMapping("/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> update(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable int id,
            @RequestBody Map<String, Object> body) {
        try {
            String userId = companyCode != null ? companyCode : "system";
            Map<String, Object> conn = service.update(id, body, userId);
            if (conn == null) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("외부 DB 연결을 찾을 수 없습니다"));
            }
            log.info("외부 DB 연결 수정: id={}, name={}", id, conn.get("name"));
            return ResponseEntity.ok(ApiResponse.success(conn, "외부 DB 연결이 수정되었습니다"));
        } catch (Exception e) {
            log.error("외부 DB 연결 수정 오류: id={}", id, e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("외부 DB 연결 수정 중 오류가 발생했습니다"));
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<ApiResponse<Void>> delete(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable int id) {
        try {
            boolean deleted = service.delete(id);
            if (!deleted) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("외부 DB 연결을 찾을 수 없습니다"));
            }
            log.info("외부 DB 연결 삭제: id={}", id);
            return ResponseEntity.ok(ApiResponse.success(null, "외부 DB 연결이 삭제되었습니다"));
        } catch (Exception e) {
            log.error("외부 DB 연결 삭제 오류: id={}", id, e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("외부 DB 연결 삭제 중 오류가 발생했습니다"));
        }
    }

    @PostMapping("/{id}/test")
    public ResponseEntity<ApiResponse<Void>> testConnection(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable int id) {
        try {
            Map<String, Object> result = service.testConnection(id);
            boolean success = Boolean.TRUE.equals(result.get("success"));
            String  message = (String) result.get("message");
            if (success) {
                log.info("외부 DB 연결 테스트 성공: id={}", id);
                return ResponseEntity.ok(ApiResponse.success(null, message));
            } else {
                log.warn("외부 DB 연결 테스트 실패: id={}, msg={}", id, message);
                return ResponseEntity.status(400).body(ApiResponse.error(message));
            }
        } catch (Exception e) {
            log.error("외부 DB 연결 테스트 오류: id={}", id, e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("외부 DB 연결 테스트 중 오류가 발생했습니다"));
        }
    }

    @GetMapping("/{id}/tables")
    public ResponseEntity<?> getTables(
            @RequestAttribute(value = "company_code", required = false) String companyCode,
            @PathVariable int id) {
        try {
            Map<String, Object> result = service.getTables(id);
            if (Boolean.TRUE.equals(result.get("success"))) {
                return ResponseEntity.ok(result);
            }
            return ResponseEntity.status(400).body(result);
        } catch (Exception e) {
            log.error("외부 DB 테이블 목록 조회 오류: id={}", id, e);
            return ResponseEntity.status(500).body(Map.of(
                    "success", false, "message", "외부 DB 테이블 목록 조회 중 오류가 발생했습니다"));
        }
    }

    @GetMapping("/{id}/tables/{tableName}/columns")
    public ResponseEntity<?> getTableColumns(
            @RequestAttribute(value = "company_code", required = false) String companyCode,
            @PathVariable int id,
            @PathVariable String tableName) {
        try {
            Map<String, Object> result = service.getTableColumns(id, tableName);
            if (Boolean.TRUE.equals(result.get("success"))) {
                return ResponseEntity.ok(result);
            }
            return ResponseEntity.status(400).body(result);
        } catch (Exception e) {
            log.error("외부 DB 컬럼 목록 조회 오류: id={}, table={}", id, tableName, e);
            return ResponseEntity.status(500).body(Map.of(
                    "success", false, "message", "외부 DB 컬럼 목록 조회 중 오류가 발생했습니다"));
        }
    }

    // ── 유효성 헬퍼 ───────────────────────────────────────────────

    private boolean isBlank(Map<String, Object> body, String key) {
        Object v = body.get(key);
        return v == null || v.toString().isBlank();
    }
}
