package com.gzzm.lobster.memory;

import com.gzzm.lobster.common.MemoryCategory;
import com.gzzm.lobster.common.MemoryStatus;
import net.cyan.thunwind.annotation.ColumnDescription;
import net.cyan.thunwind.annotation.Entity;
import net.cyan.thunwind.annotation.Index;
import net.cyan.thunwind.annotation.Lazy;

import java.util.Date;

/**
 * PersonalMemory —— 个人记忆条目 / Personal memory entry.
 *
 * <p>按 Claude Code 的「索引 + 正文」两层模型：
 * <ul>
 *   <li>{@code name}：短标题，索引行的显示文本</li>
 *   <li>{@code description}：一句话"钩子"，用于在未来对话中判断相关性</li>
 *   <li>{@code content}：完整正文（可选），按需由 {@code memory_read} 工具拉取</li>
 * </ul>
 *
 * <p>Two-layer model inspired by Claude Code: index rows live in context,
 * full bodies are read on demand.
 *
 * <p>严格按 userId 隔离，绝不跨用户注入。
 * Strictly isolated by userId — never injected across users.
 */
@Entity(table = "AI_PERSONAL_MEMORY", keys = "memoryId")
@Index(name = "uk_ai_personal_memory_user_name", unique = true, columns = {"userId", "name"})
public class PersonalMemory {

    @ColumnDescription(type = "varchar(40)")
    private String memoryId;

    @Index
    @ColumnDescription(type = "varchar(40)", nullable = false)
    private String userId;

    /** 分类（枚举字段不加 @ColumnDescription，默认值在 MemoryService.write 内赋）。 */
    private MemoryCategory category;

    /** 短标题：索引行的显示文本。 */
    @ColumnDescription(type = "varchar(80)", nullable = false)
    private String name;

    /** 一句话钩子：未来对话中用于判断相关性——索引段常驻上下文的核心字段。 */
    @ColumnDescription(type = "varchar(200)", nullable = false)
    private String description;

    /**
     * 完整正文，可选。feedback/project 推荐结构化为：
     * 规则/事实 + Why + How to apply 三段。
     *
     * <p>{@link Lazy} 让 {@code listIndex}/{@code search} 在渲染索引段时不加载正文，
     * 避免 120 行 × 2KB 的无效传输；真正需要正文的 {@link MemoryService#read}
     * 才触发一次 DB 取值。thunwind 支持关闭 session 后的惰性加载。
     */
    @Lazy
    @ColumnDescription(type = "varchar(2000)")
    private String content;

    /** explicit_user_write / assistant_confirmed_write / imported_preference / derived_summary */
    @ColumnDescription(type = "varchar(40)")
    private String sourceType;

    /** 状态（枚举字段不加 @ColumnDescription，默认值在 MemoryService.write 内赋）。 */
    private MemoryStatus status;

    private Date createTime;
    private Date updateTime;
    private Date lastAccessedAt;

    public PersonalMemory() {}

    public String getMemoryId() { return memoryId; }
    public void setMemoryId(String memoryId) { this.memoryId = memoryId; }
    public String getUserId() { return userId; }
    public void setUserId(String userId) { this.userId = userId; }
    public MemoryCategory getCategory() { return category; }
    public void setCategory(MemoryCategory category) { this.category = category; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
    public String getSourceType() { return sourceType; }
    public void setSourceType(String sourceType) { this.sourceType = sourceType; }
    public MemoryStatus getStatus() { return status; }
    public void setStatus(MemoryStatus status) { this.status = status; }
    public Date getCreateTime() { return createTime; }
    public void setCreateTime(Date createTime) { this.createTime = createTime; }
    public Date getUpdateTime() { return updateTime; }
    public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; }
    public Date getLastAccessedAt() { return lastAccessedAt; }
    public void setLastAccessedAt(Date lastAccessedAt) { this.lastAccessedAt = lastAccessedAt; }
}
