package com.infoepoch.pms.agent.platform.model.domain;

import com.infoepoch.pms.agent.config.JsonUtils;
import com.infoepoch.pms.agent.common.utils.SnowFlake;
import com.infoepoch.pms.agent.platform.shared.exception.BusinessException;
import com.infoepoch.pms.agent.platform.shared.response.ResultCode;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * AI 模型供应商实体。
 * <p>
 * 代表一个第三方大模型服务提供商（如阿里云 DashScope、OpenAI 等），
 * 持有该供应商的接入凭据（API Key），通过 AES-256-GCM 加密存储。
 * </p>
 */
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class AiModelProvider {

    /**
     * 供应商名称最大长度。
     */
    private static final int NAME_MAX_LENGTH = 100;
    /**
     * 供应商类型最大长度。
     */
    private static final int TYPE_MAX_LENGTH = 50;
    /**
     * 基础地址最大长度。
     */
    private static final int URL_MAX_LENGTH = 500;
    /**
     * API Key 最大长度。
     */
    private static final int API_KEY_MAX_LENGTH = 500;
    /**
     * Header 名称最大长度。
     */
    private static final int HEADER_NAME_MAX_LENGTH = 100;
    /**
     * Header 值最大长度。
     */
    private static final int HEADER_VALUE_MAX_LENGTH = 500;
    /**
     * 描述最大长度。
     */
    private static final int DESC_MAX_LENGTH = 500;

    /**
     * 主键
     */
    private String id;

    /**
     * 供应商显示名称，全局唯一。
     */
    private String name;

    /**
     * 供应商类型，用于区分接入协议。
     */
    private String type;

    /**
     * API 基础地址，可选。
     */
    private String baseUrl;

    /**
     * API Key，AES-256-GCM 加密存储，明文对 Service 层透明。
     */
    private String apiKey;

    /**
     * 自定义请求头，JSON 格式存储，可选。
     */
    private Map<String, String> customHeaders;

    /**
     * 自定义请求头 json字符串
     */
    private String customHeadersJson;

    /**
     * 供应商描述，可选。
     */
    private String description;

    /**
     * 是否启用。禁用后该供应商下的模型配置不可被使用。
     */
    private boolean active = true;

    /**
     * 创建人 ID，预留字段。
     */
    private String createdUserId;

    /**
     * 最后更新人 ID，预留字段。
     */
    private String updatedUserId;

    /**
     * 记录创建时间。
     */
    private LocalDateTime createdAt;

    /**
     * 记录最后更新时间。
     */
    private LocalDateTime updatedAt;

    /**
     * 仓储还原
     */
    public AiModelProvider(String id, String name, String type, String baseUrl, String apiKey, String customHeadersJson, String description, boolean active, String createdUserId, String updatedUserId, LocalDateTime createdAt, LocalDateTime updatedAt) {
        this.id = id;
        this.name = name;
        this.type = type;
        this.baseUrl = baseUrl;
        this.apiKey = apiKey;
        this.customHeadersJson = customHeadersJson;
        this.description = description;
        this.active = active;
        this.createdUserId = createdUserId;
        this.updatedUserId = updatedUserId;
        this.createdAt = createdAt;
        this.updatedAt = updatedAt;
        //还原customHeadersJson
        if (StringUtils.hasText(customHeadersJson)){
            this.customHeaders = JsonUtils.jsonToMapString(customHeadersJson);
        }
    }

    /**
     * 创建模型供应商。
     *
     * @param name        供应商名称，必填，最长 100 字符
     * @param type        供应商类型，必填，最长 50 字符
     * @param baseUrl     API 基础地址，可选，最长 500 字符
     * @param apiKey      API Key，可选，最长 500 字符
     * @param customHeaders 自定义请求头，可选
     * @param description 描述，可选，最长 500 字符
     */
    public AiModelProvider(String name, String type,
                           String baseUrl, String apiKey,
                           Map<String, String> customHeaders, String description) {
        LocalDateTime now = LocalDateTime.now();
        this.id = SnowFlake.instant().nextId().toString();
        this.name = normalizeName(name);
        this.type = normalizeType(type);
        this.baseUrl = normalizeOptional(baseUrl, URL_MAX_LENGTH, "baseUrl");
        this.apiKey = normalizeOptional(apiKey, API_KEY_MAX_LENGTH, "apiKey");
        this.customHeaders = normalizeCustomHeaders(customHeaders);
        this.customHeadersJson = JsonUtils.objectToJson(this.customHeaders);
        this.description = normalizeOptional(description, DESC_MAX_LENGTH, "描述");
        this.createdAt = now;
        this.updatedAt = now;
    }

    public static AiModelProvider restore(String id,
                                          String name,
                                          String type,
                                          String baseUrl,
                                          String apiKey,
                                          Map<String, String> customHeaders,
                                          String description,
                                          boolean active,
                                          String createdUserId,
                                          String updatedUserId,
                                          LocalDateTime createdAt,
                                          LocalDateTime updatedAt) {
        AiModelProvider provider = new AiModelProvider();
        provider.id = id;
        provider.name = name;
        provider.type = type;
        provider.baseUrl = baseUrl;
        provider.apiKey = apiKey;
        provider.customHeaders = customHeaders;
        provider.customHeadersJson = JsonUtils.objectToJson(customHeaders);
        provider.description = description;
        provider.active = active;
        provider.createdUserId = createdUserId;
        provider.updatedUserId = updatedUserId;
        provider.createdAt = createdAt;
        provider.updatedAt = updatedAt;
        return provider;
    }

    public void assignId(String id) {
        this.id = id;
    }

    /**
     * 修改供应商信息。
     * <p>apiKey 传 {@code null} 表示不修改原值。</p>
     * <p>customHeaders 传 {@code null} 表示不修改原值。</p>
     *
     * @param name        新名称，必填，最长 100 字符
     * @param baseUrl     新基础地址，可选，最长 500 字符
     * @param apiKey      新 API Key，传 {@code null} 则保留原值
     * @param customHeaders 新自定义请求头，传 {@code null} 则保留原值
     * @param description 新描述，可选，最长 500 字符
     */
    public void modify(String name, String baseUrl, String apiKey,
                       Map<String, String> customHeaders, String description) {
        this.name = normalizeName(name);
        this.baseUrl = normalizeOptional(baseUrl, URL_MAX_LENGTH, "baseUrl");
        if (apiKey != null) {
            this.apiKey = normalizeOptional(apiKey, API_KEY_MAX_LENGTH, "apiKey");
        }
        if (customHeaders != null) {
            this.customHeaders = normalizeCustomHeaders(customHeaders);
            this.customHeadersJson = JsonUtils.objectToJson(this.customHeaders);
        }
        this.description = normalizeOptional(description, DESC_MAX_LENGTH, "描述");
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 切换启用/禁用状态。
     */
    public void toggleActive() {
        this.active = !this.active;
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 规范化并校验供应商名称。
     *
     * @param name 原始名称
     * @return 规范化后的名称
     */
    private String normalizeName(String name) {
        if (!StringUtils.hasText(name)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "供应商名称不能为空");
        }
        String normalized = name.trim();
        if (normalized.length() > NAME_MAX_LENGTH) {
            throw new BusinessException(ResultCode.PARAM_ERROR,
                    "供应商名称长度不能超过 " + NAME_MAX_LENGTH + " 个字符");
        }
        return normalized;
    }

    /**
     * 规范化并校验供应商类型。
     *
     * @param type 原始类型
     * @return 规范化后的类型
     */
    private String normalizeType(String type) {
        if (!StringUtils.hasText(type)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "供应商类型不能为空");
        }
        String normalized = type.trim();
        if (normalized.length() > TYPE_MAX_LENGTH) {
            throw new BusinessException(ResultCode.PARAM_ERROR,
                    "供应商类型长度不能超过 " + TYPE_MAX_LENGTH + " 个字符");
        }
        return normalized;
    }

    /**
     * 规范化并校验可选字符串字段。
     *
     * @param value     原始值
     * @param maxLength 最大长度
     * @param fieldName 字段名（用于异常提示）
     * @return 规范化结果，空字符串归一化为 null
     */
    private String normalizeOptional(String value, int maxLength, String fieldName) {
        if (value == null) {
            return null;
        }
        String normalized = value.trim();
        if (normalized.length() > maxLength) {
            throw new BusinessException(ResultCode.PARAM_ERROR,
                    fieldName + " 长度不能超过 " + maxLength + " 个字符");
        }
        return normalized.isEmpty() ? null : normalized;
    }

    /**
     * 规范化并校验自定义请求头。
     *
     * @param customHeaders 原始自定义请求头
     * @return 规范化结果，空 Map 归一化为 null
     */
    private Map<String, String> normalizeCustomHeaders(Map<String, String> customHeaders) {
        if (customHeaders == null || customHeaders.isEmpty()) {
            return null;
        }
        Map<String, String> normalizedHeaders = new LinkedHashMap<>();
        for (Map.Entry<String, String> entry : customHeaders.entrySet()) {
            String normalizedKey = normalizeRequiredHeaderName(entry.getKey());
            String normalizedValue = normalizeRequiredHeaderValue(entry.getValue(), normalizedKey);
            normalizedHeaders.put(normalizedKey, normalizedValue);
        }
        return normalizedHeaders.isEmpty() ? null : normalizedHeaders;
    }

    /**
     * 规范化并校验必填 Header 名称。
     *
     * @param headerName 原始 Header 名称
     * @return 规范化后的 Header 名称
     */
    private String normalizeRequiredHeaderName(String headerName) {
        if (!StringUtils.hasText(headerName)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "自定义 Header 名称不能为空");
        }
        String normalized = headerName.trim();
        if (normalized.length() > HEADER_NAME_MAX_LENGTH) {
            throw new BusinessException(ResultCode.PARAM_ERROR,
                    "自定义 Header 名称长度不能超过 " + HEADER_NAME_MAX_LENGTH + " 个字符");
        }
        return normalized;
    }

    /**
     * 规范化并校验必填 Header 值。
     *
     * @param headerValue 原始 Header 值
     * @param headerName Header 名称
     * @return 规范化后的 Header 值
     */
    private String normalizeRequiredHeaderValue(String headerValue, String headerName) {
        if (!StringUtils.hasText(headerValue)) {
            throw new BusinessException(ResultCode.PARAM_ERROR,
                    "自定义 Header [" + headerName + "] 的值不能为空");
        }
        String normalized = headerValue.trim();
        if (normalized.length() > HEADER_VALUE_MAX_LENGTH) {
            throw new BusinessException(ResultCode.PARAM_ERROR,
                    "自定义 Header [" + headerName + "] 的值长度不能超过 " + HEADER_VALUE_MAX_LENGTH + " 个字符");
        }
        return normalized;
    }

    public String getCustomHeadersJson() {
        if (customHeaders != null && !customHeaders.isEmpty()) {
            return JsonUtils.objectToJson(customHeaders);
        }
        return "";
    }
}
