package com.ga.common.system;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 데이터 변경 이력 저장 (비동기).
 * before/after JSON 비교 → changed_keys 산출 → JSONB INSERT.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DataChangeLogService {

    private final SystemLogMapper logMapper;
    private final ObjectMapper objectMapper;

    @Async("asyncExecutor")
    public void save(Long userId, String menuCode, String tableName, String recordId,
                     String actionType, String beforeJson, String afterJson) {
        try {
            String changedKeys = diffKeys(beforeJson, afterJson);
            logMapper.insertDataChangeLog(userId, menuCode, tableName, recordId, actionType,
                    beforeJson, afterJson, changedKeys);
        } catch (Exception e) {
            log.warn("DataChangeLog save fail: {}", e.getMessage());
        }
    }

    private String diffKeys(String beforeJson, String afterJson) {
        try {
            JsonNode b = objectMapper.readTree(beforeJson == null ? "{}" : beforeJson);
            JsonNode a = objectMapper.readTree(afterJson  == null ? "{}" : afterJson);
            List<String> changed = new ArrayList<>();
            Iterator<String> names = a.fieldNames();
            while (names.hasNext()) {
                String n = names.next();
                JsonNode bv = b.get(n);
                JsonNode av = a.get(n);
                if (bv == null || !bv.equals(av)) changed.add(n);
            }
            return String.join(",", changed);
        } catch (Exception e) {
            return null;
        }
    }
}
