package com.easyagents.skill.model;

import com.easyagents.skill.exception.SkillValidationException;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Skill 元数据容器。
 */
public class SkillMetadata implements Serializable {

    private static final long serialVersionUID = 1L;

    private Map<String, Object> values = new LinkedHashMap<>();

    /**
     * 创建空元数据。
     */
    public SkillMetadata() {
    }

    /**
     * 使用已有键值创建元数据。
     *
     * @param values 元数据键值
     */
    public SkillMetadata(Map<String, Object> values) {
        setValues(values);
    }

    /**
     * 获取元数据键值的递归防御性副本。
     *
     * @return 元数据键值副本
     */
    public Map<String, Object> getValues() {
        return deepCopyMap(values);
    }

    /**
     * 设置元数据键值。
     *
     * @param values 元数据键值
     */
    public void setValues(Map<String, Object> values) {
        this.values = values == null ? new LinkedHashMap<>() : deepCopyMap(values);
    }

    /**
     * 写入一个元数据键值。
     *
     * @param key 元数据键
     * @param value 元数据值
     */
    public void put(String key, Object value) {
        if (key == null || key.isBlank()) {
            throw new SkillValidationException("Skill metadata key must be a non-blank string.");
        }
        values.put(key, deepCopyValue(value));
    }

    /**
     * 读取元数据值。
     *
     * @param key 元数据键
     * @return 元数据值
     */
    public Object get(String key) {
        return deepCopyValue(values.get(key));
    }

    /**
     * 删除一个元数据键。
     *
     * @param key 元数据键
     * @return 被删除值的防御性副本
     */
    public Object remove(String key) {
        return deepCopyValue(values.remove(key));
    }

    /**
     * 判断是否为空。
     *
     * @return 无元数据时为 true
     */
    public boolean isEmpty() {
        return values.isEmpty();
    }

    private static LinkedHashMap<String, Object> deepCopyMap(Map<?, ?> source) {
        LinkedHashMap<String, Object> target = new LinkedHashMap<>();
        for (Map.Entry<?, ?> entry : source.entrySet()) {
            if (!(entry.getKey() instanceof String key) || key.isBlank()) {
                throw new SkillValidationException("Skill metadata keys must be non-blank strings.");
            }
            target.put(key, deepCopyValue(entry.getValue()));
        }
        return target;
    }

    private static Object deepCopyValue(Object value) {
        if (value == null || value instanceof String || value instanceof Boolean
                || value instanceof Byte || value instanceof Short || value instanceof Integer
                || value instanceof Long || value instanceof Float || value instanceof Double
                || value instanceof BigInteger || value instanceof BigDecimal || value instanceof Character) {
            return value;
        }
        if (value instanceof Date date) {
            return new Date(date.getTime());
        }
        if (value instanceof Map<?, ?> map) {
            return deepCopyMap(map);
        }
        if (value instanceof List<?> list) {
            List<Object> copy = new ArrayList<>(list.size());
            list.forEach(item -> copy.add(deepCopyValue(item)));
            return copy;
        }
        throw new SkillValidationException("Unsupported Skill metadata value type: "
                + value.getClass().getName());
    }
}
