package com.erp.service;

import com.erp.common.BaseService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@RequiredArgsConstructor
@Slf4j
public class ButtonActionStandardService extends BaseService {

    private static final String NS = "buttonActionStandard.";

    private final ObjectMapper objectMapper;

    /**
     * 버튼 액션 목록 조회 (동적 필터)
     */
    public List<Map<String, Object>> getButtonActions(Map<String, Object> params) {
        List<Map<String, Object>> rows = sqlSession.selectList(NS + "selectButtonActions", params);
        rows.forEach(this::parseJsonFields);
        return rows;
    }

    /**
     * 버튼 액션 단건 조회
     */
    public Map<String, Object> getButtonAction(Map<String, Object> params) {
        Map<String, Object> row = sqlSession.selectOne(NS + "selectButtonActionByType", params);
        if (row != null) parseJsonFields(row);
        return row;
    }

    /**
     * 버튼 액션 생성 (중복 체크 포함)
     */
    @Transactional
    public Map<String, Object> createButtonAction(Map<String, Object> params) {
        // 중복 체크
        Map<String, Object> existing = sqlSession.selectOne(NS + "selectButtonActionByType", params);
        if (existing != null) {
            throw new IllegalArgumentException("이미 존재하는 액션 타입입니다: " + params.get("action_type"));
        }

        // JSON 필드 직렬화
        serializeJsonField(params, "validation_rules");
        serializeJsonField(params, "action_config");

        // 기본값 설정
        params.putIfAbsent("category", "general");
        params.putIfAbsent("default_variant", "default");
        params.putIfAbsent("confirmation_required", false);
        params.putIfAbsent("sort_order", 0);
        params.putIfAbsent("is_active", "Y");

        sqlSession.insert(NS + "insertButtonAction", params);

        // 삽입된 행 조회 후 반환 (actionType 키로 조회)
        params.put("action_type", params.get("action_type"));
        Map<String, Object> created = sqlSession.selectOne(NS + "selectButtonActionByType", params);
        if (created != null) parseJsonFields(created);
        return created;
    }

    /**
     * 버튼 액션 수정 (존재 확인 + 동적 업데이트)
     */
    @Transactional
    public Map<String, Object> updateButtonAction(Map<String, Object> params) {
        // 존재 여부 확인
        Map<String, Object> existing = sqlSession.selectOne(NS + "selectButtonActionByType", params);
        if (existing == null) {
            return null;
        }

        // JSON 필드 직렬화
        serializeJsonField(params, "validation_rules");
        serializeJsonField(params, "action_config");

        sqlSession.update(NS + "updateButtonAction", params);

        Map<String, Object> updated = sqlSession.selectOne(NS + "selectButtonActionByType", params);
        if (updated != null) parseJsonFields(updated);
        return updated;
    }

    /**
     * 버튼 액션 삭제 (존재 확인 포함)
     */
    @Transactional
    public boolean deleteButtonAction(Map<String, Object> params) {
        Map<String, Object> existing = sqlSession.selectOne(NS + "selectButtonActionByType", params);
        if (existing == null) {
            return false;
        }
        sqlSession.delete(NS + "deleteButtonAction", params);
        return true;
    }

    /**
     * 정렬 순서 일괄 업데이트 (트랜잭션)
     */
    @Transactional
    public void updateSortOrder(List<Map<String, Object>> items, String userId) {
        for (Map<String, Object> item : items) {
            item.put("updated_by", userId);
            sqlSession.update(NS + "updateSortOrderItem", item);
        }
    }

    /**
     * 카테고리 목록 조회 (카운트 포함)
     */
    public List<Map<String, Object>> getCategories(Map<String, Object> params) {
        List<Map<String, Object>> rows = sqlSession.selectList(NS + "selectCategories", params);
        // count 필드를 Integer로 변환
        rows.forEach(row -> {
            Object cnt = row.get("count");
            if (cnt instanceof Number n) {
                row.put("count", n.intValue());
            } else if (cnt instanceof String s) {
                row.put("count", Integer.parseInt(s));
            }
        });
        return rows;
    }

    // ── JSON 필드 직렬화/역직렬화 헬퍼 ──────────────────────────────────────────

    /**
     * Java Object → JSON String (INSERT/UPDATE용)
     */
    private void serializeJsonField(Map<String, Object> params, String key) {
        Object val = params.get(key);
        if (val != null && !(val instanceof String)) {
            try {
                params.put(key, objectMapper.writeValueAsString(val));
            } catch (Exception e) {
                log.warn("JSON 직렬화 실패 [{}]: {}", key, e.getMessage());
            }
        }
    }

    /**
     * JSON String → Java Object (SELECT 결과 후처리용)
     * resultType="map"은 DB 컬럼명 그대로 snake_case 반환
     */
    private void parseJsonFields(Map<String, Object> row) {
        for (String snakeKey : List.of("validation_rules", "action_config")) {
            Object val = row.get(snakeKey);
            if (val instanceof String s && !s.isBlank()) {
                try {
                    row.put(snakeKey, objectMapper.readValue(s, Object.class));
                } catch (Exception ignored) {
                    // 파싱 실패 시 원문 String 유지
                }
            }
        }
    }
}
