package com.erp.controller;

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

import java.util.Map;

/**
 * 데이터 흐름 관계도(Dataflow Diagram) API
 *
 * GET    /api/dataflow-diagrams            — 목록 조회 (페이지네이션)
 * GET    /api/dataflow-diagrams/:diagramId — 단건 조회
 * POST   /api/dataflow-diagrams            — 생성
 * PUT    /api/dataflow-diagrams/:diagramId — 수정
 * DELETE /api/dataflow-diagrams/:diagramId — 삭제
 * POST   /api/dataflow-diagrams/:diagramId/copy — 복제
 */
@RestController
@RequestMapping("/api/dataflow-diagrams")
@RequiredArgsConstructor
@Slf4j
public class DataflowDiagramController {

    private final DataflowDiagramService service;

    // ─────────────────────────────────────────────────────────
    // GET /api/dataflow-diagrams
    // ─────────────────────────────────────────────────────────

    @GetMapping
    public ResponseEntity<ApiResponse<Map<String, Object>>> getDataflowDiagrams(
            @RequestAttribute("company_code") String companyCode,
            @RequestParam Map<String, Object> params) {

        params.put("company_code", companyCode);
        return ResponseEntity.ok(ApiResponse.success(service.getDataflowDiagrams(params)));
    }

    // ─────────────────────────────────────────────────────────
    // GET /api/dataflow-diagrams/:diagramId
    // ─────────────────────────────────────────────────────────

    @GetMapping("/{diagramId}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getDataflowDiagramById(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable("diagram_id") String diagramIdStr) {

        int diagramId = parseId(diagramIdStr);
        if (diagramId < 0) {
            return ResponseEntity.status(400)
                    .body(ApiResponse.error("유효하지 않은 관계도 ID입니다."));
        }

        Map<String, Object> diagram = service.getDataflowDiagramById(diagramId, companyCode);
        if (diagram == null) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.error("관계도를 찾을 수 없습니다."));
        }
        return ResponseEntity.ok(ApiResponse.success(diagram));
    }

    // ─────────────────────────────────────────────────────────
    // POST /api/dataflow-diagrams
    // ─────────────────────────────────────────────────────────

    @PostMapping
    public ResponseEntity<ApiResponse<Map<String, Object>>> createDataflowDiagram(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @RequestBody Map<String, Object> body) {

        if (body.get("diagram_name") == null || body.get("relationships") == null) {
            return ResponseEntity.status(400)
                    .body(ApiResponse.error("관계도 이름과 관계 정보는 필수입니다."));
        }

        try {
            Map<String, Object> created = service.createDataflowDiagram(body, companyCode, userId);
            return ResponseEntity.status(201)
                    .body(ApiResponse.success(created, "관계도가 성공적으로 생성되었습니다."));
        } catch (DataIntegrityViolationException e) {
            if (isDuplicateNameError(e)) {
                return ResponseEntity.status(409)
                        .body(ApiResponse.error("중복된 이름입니다."));
            }
            log.error("관계도 생성 실패 (제약 위반)", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("관계도 생성 중 오류가 발생했습니다."));
        } catch (Exception e) {
            log.error("관계도 생성 실패", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("관계도 생성 중 오류가 발생했습니다."));
        }
    }

    // ─────────────────────────────────────────────────────────
    // PUT /api/dataflow-diagrams/:diagramId
    // ─────────────────────────────────────────────────────────

    @PutMapping("/{diagramId}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> updateDataflowDiagram(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable("diagram_id") String diagramIdStr,
            @RequestBody Map<String, Object> body) {

        int diagramId = parseId(diagramIdStr);
        if (diagramId < 0) {
            return ResponseEntity.status(400)
                    .body(ApiResponse.error("유효하지 않은 관계도 ID입니다."));
        }

        try {
            Map<String, Object> updated =
                    service.updateDataflowDiagram(diagramId, body, companyCode, userId);
            if (updated == null) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("관계도를 찾을 수 없습니다."));
            }
            return ResponseEntity.ok(ApiResponse.success(updated, "관계도가 성공적으로 수정되었습니다."));
        } catch (DataIntegrityViolationException e) {
            if (isDuplicateNameError(e)) {
                return ResponseEntity.status(409)
                        .body(ApiResponse.error("중복된 이름입니다."));
            }
            log.error("관계도 수정 실패 (제약 위반)", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("관계도 수정 중 오류가 발생했습니다."));
        } catch (Exception e) {
            log.error("관계도 수정 실패", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("관계도 수정 중 오류가 발생했습니다."));
        }
    }

    // ─────────────────────────────────────────────────────────
    // DELETE /api/dataflow-diagrams/:diagramId
    // ─────────────────────────────────────────────────────────

    @DeleteMapping("/{diagramId}")
    public ResponseEntity<ApiResponse<Void>> deleteDataflowDiagram(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable("diagram_id") String diagramIdStr) {

        int diagramId = parseId(diagramIdStr);
        if (diagramId < 0) {
            return ResponseEntity.status(400)
                    .body(ApiResponse.error("유효하지 않은 관계도 ID입니다."));
        }

        try {
            boolean deleted = service.deleteDataflowDiagram(diagramId, companyCode);
            if (!deleted) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("관계도를 찾을 수 없습니다."));
            }
            return ResponseEntity.ok(ApiResponse.success(null, "관계도가 성공적으로 삭제되었습니다."));
        } catch (Exception e) {
            log.error("관계도 삭제 실패", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("관계도 삭제 중 오류가 발생했습니다."));
        }
    }

    // ─────────────────────────────────────────────────────────
    // POST /api/dataflow-diagrams/:diagramId/copy
    // ─────────────────────────────────────────────────────────

    @PostMapping("/{diagramId}/copy")
    public ResponseEntity<ApiResponse<Map<String, Object>>> copyDataflowDiagram(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute("user_id") String userId,
            @PathVariable("diagram_id") String diagramIdStr,
            @RequestBody(required = false) Map<String, Object> body) {

        int diagramId = parseId(diagramIdStr);
        if (diagramId < 0) {
            return ResponseEntity.status(400)
                    .body(ApiResponse.error("유효하지 않은 관계도 ID입니다."));
        }

        String newName = (body != null) ? (String) body.get("new_name") : null;

        try {
            Map<String, Object> copied =
                    service.copyDataflowDiagram(diagramId, companyCode, newName, userId);
            if (copied == null) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("복제할 관계도를 찾을 수 없습니다."));
            }
            return ResponseEntity.status(201)
                    .body(ApiResponse.success(copied, "관계도가 성공적으로 복제되었습니다."));
        } catch (Exception e) {
            log.error("관계도 복제 실패", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("관계도 복제 중 오류가 발생했습니다."));
        }
    }

    // ─────────────────────────────────────────────────────────
    // private helpers
    // ─────────────────────────────────────────────────────────

    /** Path variable ID 파싱 (유효하지 않으면 -1) */
    private int parseId(String val) {
        try {
            int id = Integer.parseInt(val);
            return id > 0 ? id : -1;
        } catch (NumberFormatException e) {
            return -1;
        }
    }

    /** DataIntegrityViolationException 이 unique_diagram_name 위반인지 확인 */
    private boolean isDuplicateNameError(DataIntegrityViolationException e) {
        String msg = e.getMessage() != null ? e.getMessage().toLowerCase() : "";
        Throwable cause = e.getCause();
        String causeMsg = (cause != null && cause.getMessage() != null)
                ? cause.getMessage().toLowerCase() : "";
        String combined = msg + " " + causeMsg;
        return combined.contains("23505")
            || combined.contains("unique_diagram_name")
            || combined.contains("duplicate key")
            || combined.contains("unique constraint");
    }
}
