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

import com.infoepoch.pms.agent.common.utils.SnowFlake;
import com.infoepoch.pms.agent.config.JsonUtils;
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.apache.commons.collections4.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 智能体字段实体。
 * <p>
 * 代表智能体表单中的一个数据字段（如"请假天数"、"事由"），
 * 定义了该字段的类型、是否必填、追问话术（label）等元数据。
 * 子 ReactAgent 根据这些字段定义进行多轮追问。
 * </p>
 */
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class AgentField {

    /**
     * 字段标识名最大长度。
     */
    private static final int FIELD_NAME_MAX_LENGTH = 100;
    /**
     * 字段显示标签最大长度。
     */
    private static final int FIELD_LABEL_MAX_LENGTH = 100;
    /**
     * 字段类型字符串最大长度。
     */
    private static final int FIELD_TYPE_MAX_LENGTH = 20;
    /**
     * 日期格式最大长度。
     */
    private static final int DATE_FORMAT_MAX_LENGTH = 30;

    private String id;

    /**
     * 所属智能体（多对一，懒加载）。
     */
    private Agent agent;

    /**
     * 智能体id
     */
    private String agentId;

    /**
     * 字段标识名，英文，如 leave_days。
     */
    private String fieldName;

    /**
     * 字段显示标签，中文，如"请假天数"，用于追问话术。
     */
    private String fieldLabel;

    /**
     * 字段类型：text / number / date / enum。
     */
    private String fieldType;

    /**
     * 日期格式，仅 date 类型有效，如 yyyy-MM-dd，可选。
     */
    private String dateFormat;

    /**
     * 枚举选项列表，仅 enum 类型有效，可选。
     */
    private List<String> enumOptions;

    /**
     * 枚举选项json
     */
    private String enumOptionsJson;

    /**
     * 是否必填。
     */
    private boolean required = true;

    /**
     * 字段说明，可选，用于补充追问上下文。
     */
    private String description;

    /**
     * 排序序号，越小越先追问。
     */
    private int sortOrder = 0;

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

    /**
     * 仓储还原
     */
    public AgentField(String id, String agentId, String fieldName, String fieldLabel, String fieldType, String dateFormat, String enumOptionsJson, boolean required, String description, int sortOrder, LocalDateTime createdAt) {
        this.id = id;
        this.agentId = agentId;
        this.fieldName = fieldName;
        this.fieldLabel = fieldLabel;
        this.fieldType = fieldType;
        this.dateFormat = dateFormat;
        this.enumOptionsJson = enumOptionsJson;
        this.required = required;
        this.description = description;
        this.sortOrder = sortOrder;
        this.createdAt = createdAt;
        //还原枚举
        if (StringUtils.hasText(enumOptionsJson)){
            enumOptions = JsonUtils.jsonToList(enumOptionsJson, String.class);
        }
    }

    /**
     * 创建智能体字段。
     *
     * @param agent       所属智能体，不能为 null
     * @param fieldName   字段标识名，必填，最长 100 字符
     * @param fieldLabel  字段显示标签，必填，最长 100 字符
     * @param fieldType   字段类型（text/number/date/enum），必填，最长 20 字符
     * @param dateFormat  日期格式，可选，最长 30 字符
     * @param enumOptions 枚举选项，可选
     * @param required    是否必填
     * @param description 字段说明，可选
     * @param sortOrder   排序序号
     */
    public AgentField(Agent agent, String fieldName, String fieldLabel, String fieldType,
                      String dateFormat, List<String> enumOptions, boolean required,
                      String description, int sortOrder) {
        if (agent == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "所属智能体不能为空");
        }
        this.id = SnowFlake.instant().nextId().toString();
        this.agent = agent;
        this.agentId = agent.getId();
        this.fieldName = normalizeFieldName(fieldName);
        this.fieldLabel = normalizeFieldLabel(fieldLabel);
        this.fieldType = normalizeFieldType(fieldType);
        this.dateFormat = normalizeOptional(dateFormat, DATE_FORMAT_MAX_LENGTH, "日期格式");
        this.enumOptions = enumOptions;
        this.required = required;
        this.description = description == null ? null : description.trim();
        this.sortOrder = sortOrder;
        this.createdAt = LocalDateTime.now();
    }

    public static AgentField restore(String id,
                                     Agent agent,
                                     String fieldName,
                                     String fieldLabel,
                                     String fieldType,
                                     String dateFormat,
                                     List<String> enumOptions,
                                     boolean required,
                                     String description,
                                     int sortOrder,
                                     LocalDateTime createdAt) {
        AgentField field = new AgentField();
        field.id = id;
        field.agent = agent;
        field.agentId = agent == null ? null : agent.getId();
        field.fieldName = fieldName;
        field.fieldLabel = fieldLabel;
        field.fieldType = fieldType;
        field.dateFormat = dateFormat;
        field.enumOptions = enumOptions;
        field.required = required;
        field.description = description;
        field.sortOrder = sortOrder;
        field.createdAt = createdAt;
        return field;
    }

    public void setAgent(Agent agent) {
        this.agent = agent;
        this.agentId = agent == null ? null : agent.getId();
    }

    /**
     * 修改字段配置（不可修改所属智能体和创建时间）。
     *
     * @param fieldName   新字段标识名，必填，最长 100 字符
     * @param fieldLabel  新字段显示标签，必填，最长 100 字符
     * @param fieldType   新字段类型，必填，最长 20 字符
     * @param dateFormat  新日期格式，可选，最长 30 字符
     * @param enumOptions 新枚举选项，可选
     * @param required    是否必填
     * @param description 新字段说明，可选
     * @param sortOrder   新排序序号
     */
    public void modify(String fieldName, String fieldLabel, String fieldType,
                       String dateFormat, List<String> enumOptions, boolean required,
                       String description, int sortOrder) {
        this.fieldName = normalizeFieldName(fieldName);
        this.fieldLabel = normalizeFieldLabel(fieldLabel);
        this.fieldType = normalizeFieldType(fieldType);
        this.dateFormat = normalizeOptional(dateFormat, DATE_FORMAT_MAX_LENGTH, "日期格式");
        this.enumOptions = enumOptions;
        this.required = required;
        this.description = description == null ? null : description.trim();
        this.sortOrder = sortOrder;
    }

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

    /**
     * 规范化并校验字段显示标签。
     *
     * @param fieldLabel 原始字段显示标签
     * @return 规范化后的字段显示标签
     */
    private String normalizeFieldLabel(String fieldLabel) {
        if (!StringUtils.hasText(fieldLabel)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "字段显示标签不能为空");
        }
        String normalized = fieldLabel.trim();
        if (normalized.length() > FIELD_LABEL_MAX_LENGTH) {
            throw new BusinessException(ResultCode.PARAM_ERROR,
                    "字段显示标签长度不能超过 " + FIELD_LABEL_MAX_LENGTH + " 个字符");
        }
        return normalized;
    }

    /**
     * 规范化并校验字段类型。
     *
     * @param fieldType 原始字段类型
     * @return 规范化后的字段类型
     */
    private String normalizeFieldType(String fieldType) {
        if (!StringUtils.hasText(fieldType)) {
            throw new BusinessException(ResultCode.PARAM_ERROR, "字段类型不能为空");
        }
        String normalized = fieldType.trim().toLowerCase();
        if (normalized.length() > FIELD_TYPE_MAX_LENGTH) {
            throw new BusinessException(ResultCode.PARAM_ERROR,
                    "字段类型长度不能超过 " + FIELD_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;
    }

    public String getEnumOptionsJson() {
        if (CollectionUtils.isNotEmpty(enumOptions)) {
            return JsonUtils.toJson(enumOptions);
        }
        return enumOptionsJson;
    }
}
