import { Type, Static } from '@sinclair/typebox';
import { AnyAgentTool } from '../common.js';
import { MemoryProvider, MemoryType, MemoryEntry } from '../../memory/provider.js';
import { Repository } from 'typeorm';
import { NetaClawMemoryTypeEntity } from '../../entity/memory_type.js';

const MemoryTypeSchema = Type.String({ description: '记忆类型（如 user, project, feedback, reference 或自定义类型）' });

// --- memory_save ---

const memorySaveParams = Type.Object({
  action: Type.Union([Type.Literal('create'), Type.Literal('update'), Type.Literal('delete')]),
  name: Type.String({ description: '记忆标题' }),
  type: MemoryTypeSchema,
  content: Type.Optional(Type.String({ description: '记忆正文' })),
  description: Type.Optional(Type.String({ description: '一行描述' })),
  id: Type.Optional(Type.Number({ description: '更新/删除时的记忆 ID' })),
  metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown(), { description: '结构化元数据' })),
});

type MemorySaveParams = Static<typeof memorySaveParams>;

export function createMemorySaveTool(
  provider: MemoryProvider,
  agentName: string,
  userId: string,
  memoryTypeRepo?: Repository<NetaClawMemoryTypeEntity>,
): AnyAgentTool {
  return {
    name: 'memory_save',
    label: '保存记忆',
    description: '存储、更新或删除长期记忆。记忆会在未来对话中自动召回。',
    parameters: memorySaveParams,
    async execute(_id: string, params: MemorySaveParams): Promise<string> {
      const BUILTIN = ['user', 'project', 'feedback', 'reference'];
      let validTypes = BUILTIN;
      if (memoryTypeRepo) {
        try {
          const dbTypes = await memoryTypeRepo.find();
          if (dbTypes.length > 0) validTypes = dbTypes.map(t => t.key);
        } catch { /* fallback */ }
      }
      if (!validTypes.includes(params.type)) {
        return `警告: 类型 "${params.type}" 不在已注册类型中 (${validTypes.join(', ')})。请使用 memory_list_types 查看可用类型。`;
      }

      if (params.action === 'create') {
        // 幂等保护：同 agent + user + type + name 已存在时，自动更新最新一条而不是重复创建
        const existingEntries = await provider.list({
          agentName,
          userId,
          type: params.type as MemoryType,
          limit: 100,
        });
        const existing = existingEntries.find(e => e.name === params.name);
        if (existing) {
          const entry = await provider.update(existing.id, {
            name: params.name,
            type: params.type as MemoryType,
            content: params.content,
            description: params.description,
            metadata: params.metadata,
          });
          return `记忆已更新 (id=${entry.id}): ${entry.name}`;
        }

        const entry = await provider.save({
          agentName,
          userId,
          type: params.type as MemoryType,
          name: params.name,
          content: params.content ?? '',
          description: params.description ?? '',
          metadata: params.metadata,
        });
        return `记忆已保存 (id=${entry.id}): ${entry.name}`;
      }
      if (params.action === 'update') {
        if (!params.id) return '错误: 更新操作需要提供 id';
        const entry = await provider.update(params.id, {
          name: params.name,
          type: params.type as MemoryType,
          content: params.content,
          description: params.description,
          metadata: params.metadata,
        });
        return `记忆已更新 (id=${entry.id}): ${entry.name}`;
      }
      if (params.action === 'delete') {
        if (!params.id) return '错误: 删除操作需要提供 id';
        await provider.delete(params.id);
        return `记忆已删除 (id=${params.id})`;
      }
      return '错误: 未知操作';
    },
  };
}

// --- memory_recall ---

const memoryRecallParams = Type.Object({
  query: Type.Optional(Type.String({ description: '搜索关键词，留空则列出所有记忆' })),
  type: Type.Optional(MemoryTypeSchema),
  limit: Type.Optional(Type.Number({ description: '返回条数，默认 5', default: 5 })),
  id: Type.Optional(Type.Number({ description: '按 ID 精确查询' })),
});

type MemoryRecallParams = Static<typeof memoryRecallParams>;

export function createMemoryRecallTool(
  provider: MemoryProvider,
  agentName: string,
  userId: string,
): AnyAgentTool {
  return {
    name: 'memory_recall',
    label: '检索记忆',
    description: '搜索长期记忆中的相关信息。query 留空则列出所有记忆。',
    parameters: memoryRecallParams,
    async execute(_id: string, params: MemoryRecallParams): Promise<string> {
      if (params.id) {
        const entry = await provider.getById(params.id);
        if (!entry) return '未找到该记忆。';
        const meta = entry.metadata ? `\n元数据: ${JSON.stringify(entry.metadata)}` : '';
        return `[${entry.type}] (id=${entry.id}) ${entry.name}\n${entry.content}${meta}`;
      }

      const opts = {
        agentName,
        userId,
        type: params.type as MemoryType | undefined,
        limit: params.limit ?? 5,
      };
      let entries: MemoryEntry[];
      if (!params.query || params.query.trim() === '' || params.query === '*') {
        entries = await provider.list(opts);
      } else {
        try {
          entries = await provider.search(params.query, opts);
        } catch {
          entries = await provider.list(opts);
        }
      }
      if (entries.length === 0) return '未找到相关记忆。';
      return entries.map(e => {
        const meta = e.metadata ? `\n元数据: ${JSON.stringify(e.metadata)}` : '';
        return `[${e.type}] (id=${e.id}) ${e.name}\n${e.content}${meta}`;
      }).join('\n\n');
    },
  };
}

import { registerSchema } from '../catalog.js';
registerSchema({
  name: 'memory_save',
  toolset: 'memory',
  description: '存储、更新或删除长期记忆。',
  capability: 'text',
  visibility: 'tool',
});
registerSchema({
  name: 'memory_recall',
  toolset: 'memory',
  description: '搜索长期记忆中的相关信息。',
  capability: 'text',
  visibility: 'tool',
});
