package com.njzscloud.common.core.jackson.serializer;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.njzscloud.common.core.ienum.*;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Arrays;
import java.util.Optional;

@Slf4j
public class DictItemSerializer extends JsonSerializer<String> implements ContextualSerializer {

    private String key;
    private Class<?> ienum;

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (StrUtil.isBlank(value)) {
            gen.writeNull();
        } else {
            JsonStreamContext ctx = gen.getOutputContext();
            gen.writeObject(value);
            String currentName = ctx.getCurrentName();
            Dict<?> dictItem;
            if (StrUtil.isBlank(key)) {
                Object[] enumConstants = ienum.getEnumConstants();
                Optional<Object> first = Arrays.stream(enumConstants).filter(it -> ((Dict<?>) it).getVal().equals(value)).findFirst();
                dictItem = (Dict<?>) first.orElse(DictNone.NOME);
            } else {
                dictItem = SpringUtil.getBean(DictManager.class).get(key, value);
            }
            gen.writeStringField(currentName + "Txt", dictItem.getTxt());
            gen.writeStringField(currentName + "Key", dictItem.getKey());
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        DictKey dictKey = property.getAnnotation(DictKey.class);
        if (dictKey == null) {
            return prov.findValueSerializer(String.class, property);
        }
        String value = dictKey.value();
        Class<?> ienum = dictKey.ienum();
        if (StrUtil.isBlank(value) && (ienum == DictNone.class || Arrays.stream(ienum.getInterfaces()).anyMatch(it -> it != DictStr.class && it != DictInt.class))) {
            return prov.findValueSerializer(String.class, property);
        }
        DictItemSerializer dictItemSerializer = new DictItemSerializer();
        dictItemSerializer.key = value;
        dictItemSerializer.ienum = ienum;
        return dictItemSerializer;
    }
}
