package com.seeyon.apps.src_ydctdatasync.datamap;

import java.util.Map;
import java.util.function.Function;

public abstract class AbstractDataMapMode {
    /**
     * 表级别的前置处理，适用于一张表的整体逻辑
     */
    public abstract void preProcess(Map<String, Object> map);

    /**
     * 返回字段级别的处理逻辑映射，每个字段对应一个处理函数
     * @return 字段与其处理函数的映射
     */
    public abstract Map<String, Function<Object, Object>> getFieldProcessors();

    /**
     * 判断当前模式是否支持
     */
    public abstract boolean support();

    /**
     * 实现记录级别的目标源映射
     * @param target 目标对象
     * @param source 源对象
     */
    public abstract void transfer(Object target, Object source);

    /**
     * 实现记录级别的共有字段的映射
     * @param target 目标对象
     * @param source 源对象
     */
    public abstract void commonAttrTransfer(Object target, Object source);

    /**
     * 数据映射，包含字段级和记录级的处理逻辑
     * @param target 目标对象
     * @param source 源对象
     */
    protected void dataMapping(Object target, Object source) {
        if (source instanceof Map && target instanceof Map) {
            Map<String, Object> sourceMap = (Map<String, Object>) source;
            Map<String, Object> targetMap = (Map<String, Object>) target;
            preProcess(sourceMap); // 表级别前置处理
            Map<String, Function<Object, Object>> sourcefieldProcessors = getFieldProcessors();

            for (Map.Entry<String, Object> entry : sourceMap.entrySet()) {
                String fieldName = entry.getKey();
                Object fieldValue = entry.getValue();
                // 查找字段处理逻辑
                Function<Object, Object> processor = sourcefieldProcessors.getOrDefault(fieldName, this::defaultFieldProcessor);
                Object processedValue = processor.apply(fieldValue);
                sourceMap.put(fieldName, processedValue); // 处理后的值覆盖源值

            }
        }

        transfer(target, source); // 记录级别处理
    }

    /**
     * 默认字段处理逻辑，未定义处理方式的字段调用此方法
     * @param fieldValue 字段值
     * @return 原始字段值（默认不处理）
     */
    protected Object defaultFieldProcessor(Object fieldValue) {
        return fieldValue;
    }
}
