const originalEnv = {
  CREDS_KEY: process.env.CREDS_KEY,
  CREDS_IV: process.env.CREDS_IV,
};

process.env.CREDS_KEY = '0123456789abcdef0123456789abcdef';
process.env.CREDS_IV = '0123456789abcdef';

jest.mock('~/server/services/Config', () => ({
  getCachedTools: jest.fn(),
  getMCPServerTools: jest.fn(),
}));

const mongoose = require('mongoose');
const { v4: uuidv4 } = require('uuid');
const { agentSchema } = require('@librechat/data-schemas');
const { MongoMemoryServer } = require('mongodb-memory-server');
const { AccessRoleIds, ResourceType, PrincipalType } = require('librechat-data-provider');
const {
  getAgent,
  loadAgent,
  createAgent,
  updateAgent,
  deleteAgent,
  deleteUserAgents,
  revertAgentVersion,
  updateAgentProjects,
  addAgentResourceFile,
  getListAgentsByAccess,
  removeAgentResourceFiles,
  generateActionMetadataHash,
} = require('./Agent');
const permissionService = require('~/server/services/PermissionService');
const { getCachedTools, getMCPServerTools } = require('~/server/services/Config');
const { AclEntry, User } = require('~/db/models');

/**
 * @type {import('mongoose').Model<import('@librechat/data-schemas').IAgent>}
 */
let Agent;

describe('models/Agent', () => {
  describe('Agent Resource File Operations', () => {
    let mongoServer;

    beforeAll(async () => {
      mongoServer = await MongoMemoryServer.create();
      const mongoUri = mongoServer.getUri();
      Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
      await mongoose.connect(mongoUri);
    }, 20000);

    afterAll(async () => {
      await mongoose.disconnect();
      await mongoServer.stop();
      process.env.CREDS_KEY = originalEnv.CREDS_KEY;
      process.env.CREDS_IV = originalEnv.CREDS_IV;
    });

    beforeEach(async () => {
      await Agent.deleteMany({});
      await User.deleteMany({});
    });

    test('should add tool_resource to tools if missing', async () => {
      const agent = await createBasicAgent();
      const fileId = uuidv4();
      const toolResource = 'file_search';

      const updatedAgent = await addAgentResourceFile({
        agent_id: agent.id,
        tool_resource: toolResource,
        file_id: fileId,
      });

      expect(updatedAgent.tools).toContain(toolResource);
      expect(Array.isArray(updatedAgent.tools)).toBe(true);
      // Should not duplicate
      const count = updatedAgent.tools.filter((t) => t === toolResource).length;
      expect(count).toBe(1);
    });

    test('should not duplicate tool_resource in tools if already present', async () => {
      const agent = await createBasicAgent();
      const fileId1 = uuidv4();
      const fileId2 = uuidv4();
      const toolResource = 'file_search';

      // First add
      await addAgentResourceFile({
        agent_id: agent.id,
        tool_resource: toolResource,
        file_id: fileId1,
      });

      // Second add (should not duplicate)
      const updatedAgent = await addAgentResourceFile({
        agent_id: agent.id,
        tool_resource: toolResource,
        file_id: fileId2,
      });

      expect(updatedAgent.tools).toContain(toolResource);
      expect(Array.isArray(updatedAgent.tools)).toBe(true);
      const count = updatedAgent.tools.filter((t) => t === toolResource).length;
      expect(count).toBe(1);
    });

    test('should handle concurrent file additions', async () => {
      const agent = await createBasicAgent();
      const fileIds = Array.from({ length: 10 }, () => uuidv4());

      // Concurrent additions
      const additionPromises = createFileOperations(agent.id, fileIds, 'add');

      await Promise.all(additionPromises);

      const updatedAgent = await Agent.findOne({ id: agent.id });
      expect(updatedAgent.tool_resources.test_tool.file_ids).toBeDefined();
      expect(updatedAgent.tool_resources.test_tool.file_ids).toHaveLength(10);
      expect(new Set(updatedAgent.tool_resources.test_tool.file_ids).size).toBe(10);
    });

    test('should handle concurrent additions and removals', async () => {
      const agent = await createBasicAgent();
      const initialFileIds = Array.from({ length: 5 }, () => uuidv4());

      await Promise.all(createFileOperations(agent.id, initialFileIds, 'add'));

      const newFileIds = Array.from({ length: 5 }, () => uuidv4());
      const operations = [
        ...newFileIds.map((fileId) =>
          addAgentResourceFile({
            agent_id: agent.id,
            tool_resource: 'test_tool',
            file_id: fileId,
          }),
        ),
        ...initialFileIds.map((fileId) =>
          removeAgentResourceFiles({
            agent_id: agent.id,
            files: [{ tool_resource: 'test_tool', file_id: fileId }],
          }),
        ),
      ];

      await Promise.all(operations);

      const updatedAgent = await Agent.findOne({ id: agent.id });
      expect(updatedAgent.tool_resources.test_tool.file_ids).toBeDefined();
      expect(updatedAgent.tool_resources.test_tool.file_ids).toHaveLength(5);
    });

    test('should initialize array when adding to non-existent tool resource', async () => {
      const agent = await createBasicAgent();
      const fileId = uuidv4();

      const updatedAgent = await addAgentResourceFile({
        agent_id: agent.id,
        tool_resource: 'new_tool',
        file_id: fileId,
      });

      expect(updatedAgent.tool_resources.new_tool.file_ids).toBeDefined();
      expect(updatedAgent.tool_resources.new_tool.file_ids).toHaveLength(1);
      expect(updatedAgent.tool_resources.new_tool.file_ids[0]).toBe(fileId);
    });

    test('should handle rapid sequential modifications to same tool resource', async () => {
      const agent = await createBasicAgent();
      const fileId = uuidv4();

      for (let i = 0; i < 10; i++) {
        await addAgentResourceFile({
          agent_id: agent.id,
          tool_resource: 'test_tool',
          file_id: `${fileId}_${i}`,
        });

        if (i % 2 === 0) {
          await removeAgentResourceFiles({
            agent_id: agent.id,
            files: [{ tool_resource: 'test_tool', file_id: `${fileId}_${i}` }],
          });
        }
      }

      const updatedAgent = await Agent.findOne({ id: agent.id });
      expect(updatedAgent.tool_resources.test_tool.file_ids).toBeDefined();
      expect(Array.isArray(updatedAgent.tool_resources.test_tool.file_ids)).toBe(true);
    });

    test('should handle multiple tool resources concurrently', async () => {
      const agent = await createBasicAgent();
      const toolResources = ['tool1', 'tool2', 'tool3'];
      const operations = [];

      toolResources.forEach((tool) => {
        const fileIds = Array.from({ length: 5 }, () => uuidv4());
        fileIds.forEach((fileId) => {
          operations.push(
            addAgentResourceFile({
              agent_id: agent.id,
              tool_resource: tool,
              file_id: fileId,
            }),
          );
        });
      });

      await Promise.all(operations);

      const updatedAgent = await Agent.findOne({ id: agent.id });
      toolResources.forEach((tool) => {
        expect(updatedAgent.tool_resources[tool].file_ids).toBeDefined();
        expect(updatedAgent.tool_resources[tool].file_ids).toHaveLength(5);
      });
    });

    test.each([
      {
        name: 'duplicate additions',
        operation: 'add',
        duplicateCount: 5,
        expectedLength: 1,
        expectedContains: true,
      },
      {
        name: 'duplicate removals',
        operation: 'remove',
        duplicateCount: 5,
        expectedLength: 0,
        expectedContains: false,
        setupFile: true,
      },
    ])(
      'should handle concurrent $name',
      async ({ operation, duplicateCount, expectedLength, expectedContains, setupFile }) => {
        const agent = await createBasicAgent();
        const fileId = uuidv4();

        if (setupFile) {
          await addAgentResourceFile({
            agent_id: agent.id,
            tool_resource: 'test_tool',
            file_id: fileId,
          });
        }

        const promises = Array.from({ length: duplicateCount }).map(() =>
          operation === 'add'
            ? addAgentResourceFile({
                agent_id: agent.id,
                tool_resource: 'test_tool',
                file_id: fileId,
              })
            : removeAgentResourceFiles({
                agent_id: agent.id,
                files: [{ tool_resource: 'test_tool', file_id: fileId }],
              }),
        );

        await Promise.all(promises);

        const updatedAgent = await Agent.findOne({ id: agent.id });
        const fileIds = updatedAgent.tool_resources?.test_tool?.file_ids ?? [];

        expect(fileIds).toHaveLength(expectedLength);
        if (expectedContains) {
          expect(fileIds[0]).toBe(fileId);
        } else {
          expect(fileIds).not.toContain(fileId);
        }
      },
    );

    test('should handle concurrent add and remove of the same file', async () => {
      const agent = await createBasicAgent();
      const fileId = uuidv4();

      await addAgentResourceFile({
        agent_id: agent.id,
        tool_resource: 'test_tool',
        file_id: fileId,
      });

      const operations = [
        addAgentResourceFile({
          agent_id: agent.id,
          tool_resource: 'test_tool',
          file_id: fileId,
        }),
        removeAgentResourceFiles({
          agent_id: agent.id,
          files: [{ tool_resource: 'test_tool', file_id: fileId }],
        }),
      ];

      await Promise.all(operations);

      const updatedAgent = await Agent.findOne({ id: agent.id });
      const finalFileIds = updatedAgent.tool_resources.test_tool.file_ids;
      const count = finalFileIds.filter((id) => id === fileId).length;

      expect(count).toBeLessThanOrEqual(1);
      if (count === 0) {
        expect(finalFileIds).toHaveLength(0);
      } else {
        expect(finalFileIds).toHaveLength(1);
        expect(finalFileIds[0]).toBe(fileId);
      }
    });

    test('should handle concurrent removals of different files', async () => {
      const agent = await createBasicAgent();
      const fileIds = Array.from({ length: 10 }, () => uuidv4());

      // Add all files first
      await Promise.all(
        fileIds.map((fileId) =>
          addAgentResourceFile({
            agent_id: agent.id,
            tool_resource: 'test_tool',
            file_id: fileId,
          }),
        ),
      );

      // Concurrently remove all files
      const removalPromises = fileIds.map((fileId) =>
        removeAgentResourceFiles({
          agent_id: agent.id,
          files: [{ tool_resource: 'test_tool', file_id: fileId }],
        }),
      );

      await Promise.all(removalPromises);

      const updatedAgent = await Agent.findOne({ id: agent.id });
      // Check if the array is empty or the tool resource itself is removed
      const finalFileIds = updatedAgent.tool_resources?.test_tool?.file_ids ?? [];
      expect(finalFileIds).toHaveLength(0);
    });

    describe('Edge Cases', () => {
      describe.each([
        {
          operation: 'add',
          name: 'empty file_id',
          needsAgent: true,
          params: { tool_resource: 'file_search', file_id: '' },
          shouldResolve: true,
        },
        {
          operation: 'add',
          name: 'non-existent agent',
          needsAgent: false,
          params: { tool_resource: 'file_search', file_id: 'file123' },
          shouldResolve: false,
          error: 'Agent not found for adding resource file',
        },
      ])('addAgentResourceFile with $name', ({ needsAgent, params, shouldResolve, error }) => {
        test(`should ${shouldResolve ? 'resolve' : 'reject'}`, async () => {
          const agent = needsAgent ? await createBasicAgent() : null;
          const agent_id = needsAgent ? agent.id : `agent_${uuidv4()}`;

          if (shouldResolve) {
            await expect(addAgentResourceFile({ agent_id, ...params })).resolves.toBeDefined();
          } else {
            await expect(addAgentResourceFile({ agent_id, ...params })).rejects.toThrow(error);
          }
        });
      });

      describe.each([
        {
          name: 'empty files array',
          files: [],
          needsAgent: true,
          shouldResolve: true,
        },
        {
          name: 'non-existent tool_resource',
          files: [{ tool_resource: 'non_existent_tool', file_id: 'file123' }],
          needsAgent: true,
          shouldResolve: true,
        },
        {
          name: 'non-existent agent',
          files: [{ tool_resource: 'file_search', file_id: 'file123' }],
          needsAgent: false,
          shouldResolve: false,
          error: 'Agent not found for removing resource files',
        },
      ])('removeAgentResourceFiles with $name', ({ files, needsAgent, shouldResolve, error }) => {
        test(`should ${shouldResolve ? 'resolve' : 'reject'}`, async () => {
          const agent = needsAgent ? await createBasicAgent() : null;
          const agent_id = needsAgent ? agent.id : `agent_${uuidv4()}`;

          if (shouldResolve) {
            const result = await removeAgentResourceFiles({ agent_id, files });
            expect(result).toBeDefined();
            if (agent) {
              expect(result.id).toBe(agent.id);
            }
          } else {
            await expect(removeAgentResourceFiles({ agent_id, files })).rejects.toThrow(error);
          }
        });
      });
    });
  });

  describe('Agent CRUD Operations', () => {
    let mongoServer;
    let AccessRole;

    beforeAll(async () => {
      mongoServer = await MongoMemoryServer.create();
      const mongoUri = mongoServer.getUri();
      Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
      await mongoose.connect(mongoUri);

      // Initialize models
      const dbModels = require('~/db/models');
      AccessRole = dbModels.AccessRole;

      // Create necessary access roles for agents
      await AccessRole.create({
        accessRoleId: AccessRoleIds.AGENT_OWNER,
        name: 'Owner',
        description: 'Full control over agents',
        resourceType: ResourceType.AGENT,
        permBits: 15, // VIEW | EDIT | DELETE | SHARE
      });
    }, 20000);

    afterAll(async () => {
      await mongoose.disconnect();
      await mongoServer.stop();
    });

    beforeEach(async () => {
      await Agent.deleteMany({});
    });

    test('should create and get an agent', async () => {
      const { agentId, authorId } = createTestIds();

      const newAgent = await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        description: 'Test description',
      });

      expect(newAgent).toBeDefined();
      expect(newAgent.id).toBe(agentId);
      expect(newAgent.name).toBe('Test Agent');

      const retrievedAgent = await getAgent({ id: agentId });
      expect(retrievedAgent).toBeDefined();
      expect(retrievedAgent.id).toBe(agentId);
      expect(retrievedAgent.name).toBe('Test Agent');
      expect(retrievedAgent.description).toBe('Test description');
    });

    test('should delete an agent', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Agent To Delete',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      const agentBeforeDelete = await getAgent({ id: agentId });
      expect(agentBeforeDelete).toBeDefined();

      await deleteAgent({ id: agentId });

      const agentAfterDelete = await getAgent({ id: agentId });
      expect(agentAfterDelete).toBeNull();
    });

    test('should remove ACL entries when deleting an agent', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      // Create agent
      const agent = await createAgent({
        id: agentId,
        name: 'Agent With Permissions',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Grant permissions (simulating sharing)
      await permissionService.grantPermission({
        principalType: PrincipalType.USER,
        principalId: authorId,
        resourceType: ResourceType.AGENT,
        resourceId: agent._id,
        accessRoleId: AccessRoleIds.AGENT_OWNER,
        grantedBy: authorId,
      });

      // Verify ACL entry exists
      const aclEntriesBefore = await AclEntry.find({
        resourceType: ResourceType.AGENT,
        resourceId: agent._id,
      });
      expect(aclEntriesBefore).toHaveLength(1);

      // Delete the agent
      await deleteAgent({ id: agentId });

      // Verify agent is deleted
      const agentAfterDelete = await getAgent({ id: agentId });
      expect(agentAfterDelete).toBeNull();

      // Verify ACL entries are removed
      const aclEntriesAfter = await AclEntry.find({
        resourceType: ResourceType.AGENT,
        resourceId: agent._id,
      });
      expect(aclEntriesAfter).toHaveLength(0);
    });

    test('should remove handoff edges referencing deleted agent from other agents', async () => {
      const authorId = new mongoose.Types.ObjectId();
      const targetAgentId = `agent_${uuidv4()}`;
      const sourceAgentId = `agent_${uuidv4()}`;

      // Create target agent (handoff destination)
      await createAgent({
        id: targetAgentId,
        name: 'Target Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Create source agent with handoff edge to target
      await createAgent({
        id: sourceAgentId,
        name: 'Source Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        edges: [
          {
            from: sourceAgentId,
            to: targetAgentId,
            edgeType: 'handoff',
          },
        ],
      });

      // Verify edge exists before deletion
      const sourceAgentBefore = await getAgent({ id: sourceAgentId });
      expect(sourceAgentBefore.edges).toHaveLength(1);
      expect(sourceAgentBefore.edges[0].to).toBe(targetAgentId);

      // Delete the target agent
      await deleteAgent({ id: targetAgentId });

      // Verify the edge is removed from source agent
      const sourceAgentAfter = await getAgent({ id: sourceAgentId });
      expect(sourceAgentAfter.edges).toHaveLength(0);
    });

    test('should remove agent from user favorites when agent is deleted', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const userId = new mongoose.Types.ObjectId();

      // Create agent
      await createAgent({
        id: agentId,
        name: 'Agent To Delete',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Create user with the agent in favorites
      await User.create({
        _id: userId,
        name: 'Test User',
        email: `test-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ agentId: agentId }, { model: 'gpt-4', endpoint: 'openAI' }],
      });

      // Verify user has agent in favorites
      const userBefore = await User.findById(userId);
      expect(userBefore.favorites).toHaveLength(2);
      expect(userBefore.favorites.some((f) => f.agentId === agentId)).toBe(true);

      // Delete the agent
      await deleteAgent({ id: agentId });

      // Verify agent is deleted
      const agentAfterDelete = await getAgent({ id: agentId });
      expect(agentAfterDelete).toBeNull();

      // Verify agent is removed from user favorites
      const userAfter = await User.findById(userId);
      expect(userAfter.favorites).toHaveLength(1);
      expect(userAfter.favorites.some((f) => f.agentId === agentId)).toBe(false);
      expect(userAfter.favorites.some((f) => f.model === 'gpt-4')).toBe(true);
    });

    test('should remove agent from multiple users favorites when agent is deleted', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const user1Id = new mongoose.Types.ObjectId();
      const user2Id = new mongoose.Types.ObjectId();

      // Create agent
      await createAgent({
        id: agentId,
        name: 'Agent To Delete',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Create two users with the agent in favorites
      await User.create({
        _id: user1Id,
        name: 'Test User 1',
        email: `test1-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ agentId: agentId }],
      });

      await User.create({
        _id: user2Id,
        name: 'Test User 2',
        email: `test2-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ agentId: agentId }, { agentId: `agent_${uuidv4()}` }],
      });

      // Delete the agent
      await deleteAgent({ id: agentId });

      // Verify agent is removed from both users' favorites
      const user1After = await User.findById(user1Id);
      const user2After = await User.findById(user2Id);

      expect(user1After.favorites).toHaveLength(0);
      expect(user2After.favorites).toHaveLength(1);
      expect(user2After.favorites.some((f) => f.agentId === agentId)).toBe(false);
    });

    test('should preserve other agents in database when one agent is deleted', async () => {
      const agentToDeleteId = `agent_${uuidv4()}`;
      const agentToKeep1Id = `agent_${uuidv4()}`;
      const agentToKeep2Id = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      // Create multiple agents
      await createAgent({
        id: agentToDeleteId,
        name: 'Agent To Delete',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await createAgent({
        id: agentToKeep1Id,
        name: 'Agent To Keep 1',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await createAgent({
        id: agentToKeep2Id,
        name: 'Agent To Keep 2',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Verify all agents exist
      expect(await getAgent({ id: agentToDeleteId })).not.toBeNull();
      expect(await getAgent({ id: agentToKeep1Id })).not.toBeNull();
      expect(await getAgent({ id: agentToKeep2Id })).not.toBeNull();

      // Delete one agent
      await deleteAgent({ id: agentToDeleteId });

      // Verify only the deleted agent is removed, others remain intact
      expect(await getAgent({ id: agentToDeleteId })).toBeNull();
      const keptAgent1 = await getAgent({ id: agentToKeep1Id });
      const keptAgent2 = await getAgent({ id: agentToKeep2Id });
      expect(keptAgent1).not.toBeNull();
      expect(keptAgent1.name).toBe('Agent To Keep 1');
      expect(keptAgent2).not.toBeNull();
      expect(keptAgent2.name).toBe('Agent To Keep 2');
    });

    test('should preserve other agents in user favorites when one agent is deleted', async () => {
      const agentToDeleteId = `agent_${uuidv4()}`;
      const agentToKeep1Id = `agent_${uuidv4()}`;
      const agentToKeep2Id = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const userId = new mongoose.Types.ObjectId();

      // Create multiple agents
      await createAgent({
        id: agentToDeleteId,
        name: 'Agent To Delete',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await createAgent({
        id: agentToKeep1Id,
        name: 'Agent To Keep 1',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await createAgent({
        id: agentToKeep2Id,
        name: 'Agent To Keep 2',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Create user with all three agents in favorites
      await User.create({
        _id: userId,
        name: 'Test User',
        email: `test-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [
          { agentId: agentToDeleteId },
          { agentId: agentToKeep1Id },
          { agentId: agentToKeep2Id },
        ],
      });

      // Verify user has all three agents in favorites
      const userBefore = await User.findById(userId);
      expect(userBefore.favorites).toHaveLength(3);

      // Delete one agent
      await deleteAgent({ id: agentToDeleteId });

      // Verify only the deleted agent is removed from favorites
      const userAfter = await User.findById(userId);
      expect(userAfter.favorites).toHaveLength(2);
      expect(userAfter.favorites.some((f) => f.agentId === agentToDeleteId)).toBe(false);
      expect(userAfter.favorites.some((f) => f.agentId === agentToKeep1Id)).toBe(true);
      expect(userAfter.favorites.some((f) => f.agentId === agentToKeep2Id)).toBe(true);
    });

    test('should not affect users who do not have deleted agent in favorites', async () => {
      const agentToDeleteId = `agent_${uuidv4()}`;
      const otherAgentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const userWithDeletedAgentId = new mongoose.Types.ObjectId();
      const userWithoutDeletedAgentId = new mongoose.Types.ObjectId();

      // Create agents
      await createAgent({
        id: agentToDeleteId,
        name: 'Agent To Delete',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await createAgent({
        id: otherAgentId,
        name: 'Other Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Create user with the agent to be deleted
      await User.create({
        _id: userWithDeletedAgentId,
        name: 'User With Deleted Agent',
        email: `user1-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ agentId: agentToDeleteId }, { model: 'gpt-4', endpoint: 'openAI' }],
      });

      // Create user without the agent to be deleted
      await User.create({
        _id: userWithoutDeletedAgentId,
        name: 'User Without Deleted Agent',
        email: `user2-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ agentId: otherAgentId }, { model: 'claude-3', endpoint: 'anthropic' }],
      });

      // Delete the agent
      await deleteAgent({ id: agentToDeleteId });

      // Verify user with deleted agent has it removed
      const userWithDeleted = await User.findById(userWithDeletedAgentId);
      expect(userWithDeleted.favorites).toHaveLength(1);
      expect(userWithDeleted.favorites.some((f) => f.agentId === agentToDeleteId)).toBe(false);
      expect(userWithDeleted.favorites.some((f) => f.model === 'gpt-4')).toBe(true);

      // Verify user without deleted agent is completely unaffected
      const userWithoutDeleted = await User.findById(userWithoutDeletedAgentId);
      expect(userWithoutDeleted.favorites).toHaveLength(2);
      expect(userWithoutDeleted.favorites.some((f) => f.agentId === otherAgentId)).toBe(true);
      expect(userWithoutDeleted.favorites.some((f) => f.model === 'claude-3')).toBe(true);
    });

    test('should remove all user agents from favorites when deleteUserAgents is called', async () => {
      const authorId = new mongoose.Types.ObjectId();
      const otherAuthorId = new mongoose.Types.ObjectId();
      const userId = new mongoose.Types.ObjectId();

      const agent1Id = `agent_${uuidv4()}`;
      const agent2Id = `agent_${uuidv4()}`;
      const otherAuthorAgentId = `agent_${uuidv4()}`;

      // Create agents by the author to be deleted
      await createAgent({
        id: agent1Id,
        name: 'Author Agent 1',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await createAgent({
        id: agent2Id,
        name: 'Author Agent 2',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Create agent by different author (should not be deleted)
      await createAgent({
        id: otherAuthorAgentId,
        name: 'Other Author Agent',
        provider: 'test',
        model: 'test-model',
        author: otherAuthorId,
      });

      // Create user with all agents in favorites
      await User.create({
        _id: userId,
        name: 'Test User',
        email: `test-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [
          { agentId: agent1Id },
          { agentId: agent2Id },
          { agentId: otherAuthorAgentId },
          { model: 'gpt-4', endpoint: 'openAI' },
        ],
      });

      // Verify user has all favorites
      const userBefore = await User.findById(userId);
      expect(userBefore.favorites).toHaveLength(4);

      // Delete all agents by the author
      await deleteUserAgents(authorId.toString());

      // Verify author's agents are deleted from database
      expect(await getAgent({ id: agent1Id })).toBeNull();
      expect(await getAgent({ id: agent2Id })).toBeNull();

      // Verify other author's agent still exists
      expect(await getAgent({ id: otherAuthorAgentId })).not.toBeNull();

      // Verify user favorites: author's agents removed, others remain
      const userAfter = await User.findById(userId);
      expect(userAfter.favorites).toHaveLength(2);
      expect(userAfter.favorites.some((f) => f.agentId === agent1Id)).toBe(false);
      expect(userAfter.favorites.some((f) => f.agentId === agent2Id)).toBe(false);
      expect(userAfter.favorites.some((f) => f.agentId === otherAuthorAgentId)).toBe(true);
      expect(userAfter.favorites.some((f) => f.model === 'gpt-4')).toBe(true);
    });

    test('should handle deleteUserAgents when agents are in multiple users favorites', async () => {
      const authorId = new mongoose.Types.ObjectId();
      const user1Id = new mongoose.Types.ObjectId();
      const user2Id = new mongoose.Types.ObjectId();
      const user3Id = new mongoose.Types.ObjectId();

      const agent1Id = `agent_${uuidv4()}`;
      const agent2Id = `agent_${uuidv4()}`;
      const unrelatedAgentId = `agent_${uuidv4()}`;

      // Create agents by the author
      await createAgent({
        id: agent1Id,
        name: 'Author Agent 1',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await createAgent({
        id: agent2Id,
        name: 'Author Agent 2',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Create users with various favorites configurations
      await User.create({
        _id: user1Id,
        name: 'User 1',
        email: `user1-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ agentId: agent1Id }, { agentId: agent2Id }],
      });

      await User.create({
        _id: user2Id,
        name: 'User 2',
        email: `user2-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ agentId: agent1Id }, { model: 'claude-3', endpoint: 'anthropic' }],
      });

      await User.create({
        _id: user3Id,
        name: 'User 3',
        email: `user3-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ agentId: unrelatedAgentId }, { model: 'gpt-4', endpoint: 'openAI' }],
      });

      // Delete all agents by the author
      await deleteUserAgents(authorId.toString());

      // Verify all users' favorites are correctly updated
      const user1After = await User.findById(user1Id);
      expect(user1After.favorites).toHaveLength(0);

      const user2After = await User.findById(user2Id);
      expect(user2After.favorites).toHaveLength(1);
      expect(user2After.favorites.some((f) => f.agentId === agent1Id)).toBe(false);
      expect(user2After.favorites.some((f) => f.model === 'claude-3')).toBe(true);

      // User 3 should be completely unaffected
      const user3After = await User.findById(user3Id);
      expect(user3After.favorites).toHaveLength(2);
      expect(user3After.favorites.some((f) => f.agentId === unrelatedAgentId)).toBe(true);
      expect(user3After.favorites.some((f) => f.model === 'gpt-4')).toBe(true);
    });

    test('should handle deleteUserAgents when user has no agents', async () => {
      const authorWithNoAgentsId = new mongoose.Types.ObjectId();
      const otherAuthorId = new mongoose.Types.ObjectId();
      const userId = new mongoose.Types.ObjectId();

      const existingAgentId = `agent_${uuidv4()}`;

      // Create agent by different author
      await createAgent({
        id: existingAgentId,
        name: 'Existing Agent',
        provider: 'test',
        model: 'test-model',
        author: otherAuthorId,
      });

      // Create user with favorites
      await User.create({
        _id: userId,
        name: 'Test User',
        email: `test-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ agentId: existingAgentId }, { model: 'gpt-4', endpoint: 'openAI' }],
      });

      // Delete agents for user with no agents (should be a no-op)
      await deleteUserAgents(authorWithNoAgentsId.toString());

      // Verify existing agent still exists
      expect(await getAgent({ id: existingAgentId })).not.toBeNull();

      // Verify user favorites are unchanged
      const userAfter = await User.findById(userId);
      expect(userAfter.favorites).toHaveLength(2);
      expect(userAfter.favorites.some((f) => f.agentId === existingAgentId)).toBe(true);
      expect(userAfter.favorites.some((f) => f.model === 'gpt-4')).toBe(true);
    });

    test('should handle deleteUserAgents when agents are not in any favorites', async () => {
      const authorId = new mongoose.Types.ObjectId();
      const userId = new mongoose.Types.ObjectId();

      const agent1Id = `agent_${uuidv4()}`;
      const agent2Id = `agent_${uuidv4()}`;

      // Create agents by the author
      await createAgent({
        id: agent1Id,
        name: 'Agent 1',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await createAgent({
        id: agent2Id,
        name: 'Agent 2',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Create user with favorites that don't include these agents
      await User.create({
        _id: userId,
        name: 'Test User',
        email: `test-${uuidv4()}@example.com`,
        provider: 'local',
        favorites: [{ model: 'gpt-4', endpoint: 'openAI' }],
      });

      // Verify agents exist
      expect(await getAgent({ id: agent1Id })).not.toBeNull();
      expect(await getAgent({ id: agent2Id })).not.toBeNull();

      // Delete all agents by the author
      await deleteUserAgents(authorId.toString());

      // Verify agents are deleted
      expect(await getAgent({ id: agent1Id })).toBeNull();
      expect(await getAgent({ id: agent2Id })).toBeNull();

      // Verify user favorites are unchanged
      const userAfter = await User.findById(userId);
      expect(userAfter.favorites).toHaveLength(1);
      expect(userAfter.favorites.some((f) => f.model === 'gpt-4')).toBe(true);
    });

    test('should update agent projects', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const projectId1 = new mongoose.Types.ObjectId();
      const projectId2 = new mongoose.Types.ObjectId();
      const projectId3 = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Project Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        projectIds: [projectId1],
      });

      await updateAgent(
        { id: agentId },
        { $addToSet: { projectIds: { $each: [projectId2, projectId3] } } },
      );

      await updateAgent({ id: agentId }, { $pull: { projectIds: projectId1 } });

      await updateAgent({ id: agentId }, { projectIds: [projectId2, projectId3] });

      const updatedAgent = await getAgent({ id: agentId });
      expect(updatedAgent.projectIds).toHaveLength(2);
      expect(updatedAgent.projectIds.map((id) => id.toString())).toContain(projectId2.toString());
      expect(updatedAgent.projectIds.map((id) => id.toString())).toContain(projectId3.toString());
      expect(updatedAgent.projectIds.map((id) => id.toString())).not.toContain(
        projectId1.toString(),
      );

      await updateAgent({ id: agentId }, { projectIds: [] });

      const emptyProjectsAgent = await getAgent({ id: agentId });
      expect(emptyProjectsAgent.projectIds).toHaveLength(0);

      const nonExistentId = `agent_${uuidv4()}`;
      await expect(
        updateAgentProjects({
          id: nonExistentId,
          projectIds: [projectId1],
        }),
      ).rejects.toThrow();
    });

    test('should handle ephemeral agent loading', async () => {
      const agentId = 'ephemeral_test';
      const endpoint = 'openai';

      const originalModule = jest.requireActual('librechat-data-provider');

      const mockDataProvider = {
        ...originalModule,
        Constants: {
          ...originalModule.Constants,
          EPHEMERAL_AGENT_ID: 'ephemeral_test',
        },
      };

      jest.doMock('librechat-data-provider', () => mockDataProvider);

      expect(agentId).toBeDefined();
      expect(endpoint).toBeDefined();

      jest.dontMock('librechat-data-provider');
    });

    test('should handle loadAgent functionality and errors', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Load Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        tools: ['tool1', 'tool2'],
      });

      const agent = await getAgent({ id: agentId });

      expect(agent).toBeDefined();
      expect(agent.id).toBe(agentId);
      expect(agent.name).toBe('Test Load Agent');
      expect(agent.tools).toEqual(expect.arrayContaining(['tool1', 'tool2']));

      const mockLoadAgent = jest.fn().mockResolvedValue(agent);
      const loadedAgent = await mockLoadAgent();
      expect(loadedAgent).toBeDefined();
      expect(loadedAgent.id).toBe(agentId);

      const nonExistentId = `agent_${uuidv4()}`;
      const nonExistentAgent = await getAgent({ id: nonExistentId });
      expect(nonExistentAgent).toBeNull();

      const mockLoadAgentError = jest.fn().mockRejectedValue(new Error('No agent found with ID'));
      await expect(mockLoadAgentError()).rejects.toThrow('No agent found with ID');
    });

    describe('Edge Cases', () => {
      test.each([
        {
          name: 'getAgent with undefined search parameters',
          fn: () => getAgent(undefined),
          expected: null,
        },
        {
          name: 'deleteAgent with non-existent agent',
          fn: () => deleteAgent({ id: 'non-existent' }),
          expected: null,
        },
      ])('$name should return null', async ({ fn, expected }) => {
        const result = await fn();
        expect(result).toBe(expected);
      });

      test('should handle updateAgentProjects with non-existent agent', async () => {
        const nonExistentId = `agent_${uuidv4()}`;
        const userId = new mongoose.Types.ObjectId();
        const projectId = new mongoose.Types.ObjectId();

        const result = await updateAgentProjects({
          user: { id: userId.toString() },
          agentId: nonExistentId,
          projectIds: [projectId.toString()],
        });

        expect(result).toBeNull();
      });
    });
  });

  describe('Agent Version History', () => {
    let mongoServer;

    beforeAll(async () => {
      mongoServer = await MongoMemoryServer.create();
      const mongoUri = mongoServer.getUri();
      Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
      await mongoose.connect(mongoUri);
    }, 20000);

    afterAll(async () => {
      await mongoose.disconnect();
      await mongoServer.stop();
    });

    beforeEach(async () => {
      await Agent.deleteMany({});
    });

    test('should create an agent with a single entry in versions array', async () => {
      const agent = await createBasicAgent();

      expect(agent.versions).toBeDefined();
      expect(Array.isArray(agent.versions)).toBe(true);
      expect(agent.versions).toHaveLength(1);
      expect(agent.versions[0].name).toBe('Test Agent');
      expect(agent.versions[0].provider).toBe('test');
      expect(agent.versions[0].model).toBe('test-model');
    });

    test('should accumulate version history across multiple updates', async () => {
      const agentId = `agent_${uuidv4()}`;
      const author = new mongoose.Types.ObjectId();
      await createAgent({
        id: agentId,
        name: 'First Name',
        provider: 'test',
        model: 'test-model',
        author,
        description: 'First description',
      });

      await updateAgent(
        { id: agentId },
        { name: 'Second Name', description: 'Second description' },
      );
      await updateAgent({ id: agentId }, { name: 'Third Name', model: 'new-model' });
      const finalAgent = await updateAgent({ id: agentId }, { description: 'Final description' });

      expect(finalAgent.versions).toBeDefined();
      expect(Array.isArray(finalAgent.versions)).toBe(true);
      expect(finalAgent.versions).toHaveLength(4);

      expect(finalAgent.versions[0].name).toBe('First Name');
      expect(finalAgent.versions[0].description).toBe('First description');
      expect(finalAgent.versions[0].model).toBe('test-model');

      expect(finalAgent.versions[1].name).toBe('Second Name');
      expect(finalAgent.versions[1].description).toBe('Second description');
      expect(finalAgent.versions[1].model).toBe('test-model');

      expect(finalAgent.versions[2].name).toBe('Third Name');
      expect(finalAgent.versions[2].description).toBe('Second description');
      expect(finalAgent.versions[2].model).toBe('new-model');

      expect(finalAgent.versions[3].name).toBe('Third Name');
      expect(finalAgent.versions[3].description).toBe('Final description');
      expect(finalAgent.versions[3].model).toBe('new-model');

      expect(finalAgent.name).toBe('Third Name');
      expect(finalAgent.description).toBe('Final description');
      expect(finalAgent.model).toBe('new-model');
    });

    test('should not include metadata fields in version history', async () => {
      const agentId = `agent_${uuidv4()}`;
      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: new mongoose.Types.ObjectId(),
      });

      const updatedAgent = await updateAgent({ id: agentId }, { description: 'New description' });

      expect(updatedAgent.versions).toHaveLength(2);
      expect(updatedAgent.versions[0]._id).toBeUndefined();
      expect(updatedAgent.versions[0].__v).toBeUndefined();
      expect(updatedAgent.versions[0].name).toBe('Test Agent');
      expect(updatedAgent.versions[0].author).toBeUndefined();

      expect(updatedAgent.versions[1]._id).toBeUndefined();
      expect(updatedAgent.versions[1].__v).toBeUndefined();
    });

    test('should not recursively include previous versions', async () => {
      const agentId = `agent_${uuidv4()}`;
      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: new mongoose.Types.ObjectId(),
      });

      await updateAgent({ id: agentId }, { name: 'Updated Name 1' });
      await updateAgent({ id: agentId }, { name: 'Updated Name 2' });
      const finalAgent = await updateAgent({ id: agentId }, { name: 'Updated Name 3' });

      expect(finalAgent.versions).toHaveLength(4);

      finalAgent.versions.forEach((version) => {
        expect(version.versions).toBeUndefined();
      });
    });

    test('should handle MongoDB operators and field updates correctly', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const projectId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'MongoDB Operator Test',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        tools: ['tool1'],
      });

      await updateAgent(
        { id: agentId },
        {
          description: 'Updated description',
          $push: { tools: 'tool2' },
          $addToSet: { projectIds: projectId },
        },
      );

      const firstUpdate = await getAgent({ id: agentId });
      expect(firstUpdate.description).toBe('Updated description');
      expect(firstUpdate.tools).toContain('tool1');
      expect(firstUpdate.tools).toContain('tool2');
      expect(firstUpdate.projectIds.map((id) => id.toString())).toContain(projectId.toString());
      expect(firstUpdate.versions).toHaveLength(2);

      await updateAgent(
        { id: agentId },
        {
          tools: ['tool2', 'tool3'],
        },
      );

      const secondUpdate = await getAgent({ id: agentId });
      expect(secondUpdate.tools).toHaveLength(2);
      expect(secondUpdate.tools).toContain('tool2');
      expect(secondUpdate.tools).toContain('tool3');
      expect(secondUpdate.tools).not.toContain('tool1');
      expect(secondUpdate.versions).toHaveLength(3);

      await updateAgent(
        { id: agentId },
        {
          $push: { tools: 'tool3' },
        },
      );

      const thirdUpdate = await getAgent({ id: agentId });
      const toolCount = thirdUpdate.tools.filter((t) => t === 'tool3').length;
      expect(toolCount).toBe(2);
      expect(thirdUpdate.versions).toHaveLength(4);
    });

    test('should handle parameter objects correctly', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Parameters Test',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        model_parameters: { temperature: 0.7 },
      });

      const updatedAgent = await updateAgent(
        { id: agentId },
        { model_parameters: { temperature: 0.8 } },
      );

      expect(updatedAgent.versions).toHaveLength(2);
      expect(updatedAgent.model_parameters.temperature).toBe(0.8);

      await updateAgent(
        { id: agentId },
        {
          model_parameters: {
            temperature: 0.8,
            max_tokens: 1000,
          },
        },
      );

      const complexAgent = await getAgent({ id: agentId });
      expect(complexAgent.versions).toHaveLength(3);
      expect(complexAgent.model_parameters.temperature).toBe(0.8);
      expect(complexAgent.model_parameters.max_tokens).toBe(1000);

      await updateAgent({ id: agentId }, { model_parameters: {} });

      const emptyParamsAgent = await getAgent({ id: agentId });
      expect(emptyParamsAgent.versions).toHaveLength(4);
      expect(emptyParamsAgent.model_parameters).toEqual({});
    });

    test('should not create new version for duplicate updates', async () => {
      const authorId = new mongoose.Types.ObjectId();
      const testCases = generateVersionTestCases();

      for (const testCase of testCases) {
        const testAgentId = `agent_${uuidv4()}`;

        await createAgent({
          id: testAgentId,
          provider: 'test',
          model: 'test-model',
          author: authorId,
          ...testCase.initial,
        });

        const updatedAgent = await updateAgent({ id: testAgentId }, testCase.update);
        expect(updatedAgent.versions).toHaveLength(2); // No new version created

        // Update with duplicate data should succeed but not create a new version
        const duplicateUpdate = await updateAgent({ id: testAgentId }, testCase.duplicate);

        expect(duplicateUpdate.versions).toHaveLength(2); // No new version created

        const agent = await getAgent({ id: testAgentId });
        expect(agent.versions).toHaveLength(2);
      }
    });

    test('should track updatedBy when a different user updates an agent', async () => {
      const agentId = `agent_${uuidv4()}`;
      const originalAuthor = new mongoose.Types.ObjectId();
      const updatingUser = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Original Agent',
        provider: 'test',
        model: 'test-model',
        author: originalAuthor,
        description: 'Original description',
      });

      const updatedAgent = await updateAgent(
        { id: agentId },
        { name: 'Updated Agent', description: 'Updated description' },
        { updatingUserId: updatingUser.toString() },
      );

      expect(updatedAgent.versions).toHaveLength(2);
      expect(updatedAgent.versions[1].updatedBy.toString()).toBe(updatingUser.toString());
      expect(updatedAgent.author.toString()).toBe(originalAuthor.toString());
    });

    test('should include updatedBy even when the original author updates the agent', async () => {
      const agentId = `agent_${uuidv4()}`;
      const originalAuthor = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Original Agent',
        provider: 'test',
        model: 'test-model',
        author: originalAuthor,
        description: 'Original description',
      });

      const updatedAgent = await updateAgent(
        { id: agentId },
        { name: 'Updated Agent', description: 'Updated description' },
        { updatingUserId: originalAuthor.toString() },
      );

      expect(updatedAgent.versions).toHaveLength(2);
      expect(updatedAgent.versions[1].updatedBy.toString()).toBe(originalAuthor.toString());
      expect(updatedAgent.author.toString()).toBe(originalAuthor.toString());
    });

    test('should track multiple different users updating the same agent', async () => {
      const agentId = `agent_${uuidv4()}`;
      const originalAuthor = new mongoose.Types.ObjectId();
      const user1 = new mongoose.Types.ObjectId();
      const user2 = new mongoose.Types.ObjectId();
      const user3 = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Original Agent',
        provider: 'test',
        model: 'test-model',
        author: originalAuthor,
        description: 'Original description',
      });

      // User 1 makes an update
      await updateAgent(
        { id: agentId },
        { name: 'Updated by User 1', description: 'First update' },
        { updatingUserId: user1.toString() },
      );

      // Original author makes an update
      await updateAgent(
        { id: agentId },
        { description: 'Updated by original author' },
        { updatingUserId: originalAuthor.toString() },
      );

      // User 2 makes an update
      await updateAgent(
        { id: agentId },
        { name: 'Updated by User 2', model: 'new-model' },
        { updatingUserId: user2.toString() },
      );

      // User 3 makes an update
      const finalAgent = await updateAgent(
        { id: agentId },
        { description: 'Final update by User 3' },
        { updatingUserId: user3.toString() },
      );

      expect(finalAgent.versions).toHaveLength(5);
      expect(finalAgent.author.toString()).toBe(originalAuthor.toString());

      // Check that each version has the correct updatedBy
      expect(finalAgent.versions[0].updatedBy).toBeUndefined(); // Initial creation has no updatedBy
      expect(finalAgent.versions[1].updatedBy.toString()).toBe(user1.toString());
      expect(finalAgent.versions[2].updatedBy.toString()).toBe(originalAuthor.toString());
      expect(finalAgent.versions[3].updatedBy.toString()).toBe(user2.toString());
      expect(finalAgent.versions[4].updatedBy.toString()).toBe(user3.toString());

      // Verify the final state
      expect(finalAgent.name).toBe('Updated by User 2');
      expect(finalAgent.description).toBe('Final update by User 3');
      expect(finalAgent.model).toBe('new-model');
    });

    test('should preserve original author during agent restoration', async () => {
      const agentId = `agent_${uuidv4()}`;
      const originalAuthor = new mongoose.Types.ObjectId();
      const updatingUser = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Original Agent',
        provider: 'test',
        model: 'test-model',
        author: originalAuthor,
        description: 'Original description',
      });

      await updateAgent(
        { id: agentId },
        { name: 'Updated Agent', description: 'Updated description' },
        { updatingUserId: updatingUser.toString() },
      );

      const { revertAgentVersion } = require('./Agent');
      const revertedAgent = await revertAgentVersion({ id: agentId }, 0);

      expect(revertedAgent.author.toString()).toBe(originalAuthor.toString());
      expect(revertedAgent.name).toBe('Original Agent');
      expect(revertedAgent.description).toBe('Original description');
    });

    test('should detect action metadata changes and force version update', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const actionId = 'testActionId123';

      // Create agent with actions
      await createAgent({
        id: agentId,
        name: 'Agent with Actions',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        actions: [`test.com_action_${actionId}`],
        tools: ['listEvents_action_test.com', 'createEvent_action_test.com'],
      });

      // First update with forceVersion should create a version
      const firstUpdate = await updateAgent(
        { id: agentId },
        { tools: ['listEvents_action_test.com', 'createEvent_action_test.com'] },
        { updatingUserId: authorId.toString(), forceVersion: true },
      );

      expect(firstUpdate.versions).toHaveLength(2);

      // Second update with same data but forceVersion should still create a version
      const secondUpdate = await updateAgent(
        { id: agentId },
        { tools: ['listEvents_action_test.com', 'createEvent_action_test.com'] },
        { updatingUserId: authorId.toString(), forceVersion: true },
      );

      expect(secondUpdate.versions).toHaveLength(3);

      // Update without forceVersion and no changes should not create a version
      const duplicateUpdate = await updateAgent(
        { id: agentId },
        { tools: ['listEvents_action_test.com', 'createEvent_action_test.com'] },
        { updatingUserId: authorId.toString(), forceVersion: false },
      );

      expect(duplicateUpdate.versions).toHaveLength(3); // No new version created
    });

    test('should handle isDuplicateVersion with arrays containing null/undefined values', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        tools: ['tool1', null, 'tool2', undefined],
      });

      // Update with same array but different null/undefined arrangement
      const updatedAgent = await updateAgent({ id: agentId }, { tools: ['tool1', 'tool2'] });

      expect(updatedAgent.versions).toHaveLength(2);
      expect(updatedAgent.tools).toEqual(['tool1', 'tool2']);
    });

    test('should handle isDuplicateVersion with empty objects in tool_kwargs', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        tool_kwargs: [
          { tool: 'tool1', config: { setting: 'value' } },
          {},
          { tool: 'tool2', config: {} },
        ],
      });

      // Try to update with reordered but equivalent tool_kwargs
      const updatedAgent = await updateAgent(
        { id: agentId },
        {
          tool_kwargs: [
            { tool: 'tool2', config: {} },
            { tool: 'tool1', config: { setting: 'value' } },
            {},
          ],
        },
      );

      // Should create new version as order matters for arrays
      expect(updatedAgent.versions).toHaveLength(2);
    });

    test('should handle isDuplicateVersion with mixed primitive and object arrays', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        mixed_array: [1, 'string', { key: 'value' }, true, null],
      });

      // Update with same values but different types
      const updatedAgent = await updateAgent(
        { id: agentId },
        { mixed_array: ['1', 'string', { key: 'value' }, 'true', null] },
      );

      // Should create new version as types differ
      expect(updatedAgent.versions).toHaveLength(2);
    });

    test('should handle isDuplicateVersion with deeply nested objects', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      const deepObject = {
        level1: {
          level2: {
            level3: {
              level4: {
                value: 'deep',
                array: [1, 2, { nested: true }],
              },
            },
          },
        },
      };

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        model_parameters: deepObject,
      });

      // First create a version with changes
      await updateAgent({ id: agentId }, { description: 'Updated' });

      // Then try to create duplicate of the original version
      await updateAgent(
        { id: agentId },
        {
          model_parameters: deepObject,
          description: undefined,
        },
      );

      // Since we're updating back to the same model_parameters but with a different description,
      // it should create a new version
      const agent = await getAgent({ id: agentId });
      expect(agent.versions).toHaveLength(3);
    });

    test('should handle version comparison with special field types', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const projectId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        projectIds: [projectId],
        model_parameters: { temperature: 0.7 },
      });

      // Update with a real field change first
      const firstUpdate = await updateAgent({ id: agentId }, { description: 'New description' });

      expect(firstUpdate.versions).toHaveLength(2);

      // Update with model parameters change
      const secondUpdate = await updateAgent(
        { id: agentId },
        { model_parameters: { temperature: 0.8 } },
      );

      expect(secondUpdate.versions).toHaveLength(3);
    });

    test('should detect changes in support_contact fields', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      // Create agent with initial support_contact
      await createAgent({
        id: agentId,
        name: 'Agent with Support Contact',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        support_contact: {
          name: 'Initial Support',
          email: 'initial@support.com',
        },
      });

      // Update support_contact name only
      const firstUpdate = await updateAgent(
        { id: agentId },
        {
          support_contact: {
            name: 'Updated Support',
            email: 'initial@support.com',
          },
        },
      );

      expect(firstUpdate.versions).toHaveLength(2);
      expect(firstUpdate.support_contact.name).toBe('Updated Support');
      expect(firstUpdate.support_contact.email).toBe('initial@support.com');

      // Update support_contact email only
      const secondUpdate = await updateAgent(
        { id: agentId },
        {
          support_contact: {
            name: 'Updated Support',
            email: 'updated@support.com',
          },
        },
      );

      expect(secondUpdate.versions).toHaveLength(3);
      expect(secondUpdate.support_contact.email).toBe('updated@support.com');

      // Try to update with same support_contact - should be detected as duplicate but return successfully
      const duplicateUpdate = await updateAgent(
        { id: agentId },
        {
          support_contact: {
            name: 'Updated Support',
            email: 'updated@support.com',
          },
        },
      );

      // Should not create a new version
      expect(duplicateUpdate.versions).toHaveLength(3);
      expect(duplicateUpdate.version).toBe(3);
      expect(duplicateUpdate.support_contact.email).toBe('updated@support.com');
    });

    test('should handle support_contact from empty to populated', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      // Create agent without support_contact
      const agent = await createAgent({
        id: agentId,
        name: 'Agent without Support',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Verify support_contact is undefined since it wasn't provided
      expect(agent.support_contact).toBeUndefined();

      // Update to add support_contact
      const updated = await updateAgent(
        { id: agentId },
        {
          support_contact: {
            name: 'New Support Team',
            email: 'support@example.com',
          },
        },
      );

      expect(updated.versions).toHaveLength(2);
      expect(updated.support_contact.name).toBe('New Support Team');
      expect(updated.support_contact.email).toBe('support@example.com');
    });

    test('should handle support_contact edge cases in isDuplicateVersion', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      // Create agent with support_contact
      await createAgent({
        id: agentId,
        name: 'Edge Case Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        support_contact: {
          name: 'Support',
          email: 'support@test.com',
        },
      });

      // Update to empty support_contact
      const emptyUpdate = await updateAgent(
        { id: agentId },
        {
          support_contact: {},
        },
      );

      expect(emptyUpdate.versions).toHaveLength(2);
      expect(emptyUpdate.support_contact).toEqual({});

      // Update back to populated support_contact
      const repopulated = await updateAgent(
        { id: agentId },
        {
          support_contact: {
            name: 'Support',
            email: 'support@test.com',
          },
        },
      );

      expect(repopulated.versions).toHaveLength(3);

      // Verify all versions have correct support_contact
      const finalAgent = await getAgent({ id: agentId });
      expect(finalAgent.versions[0].support_contact).toEqual({
        name: 'Support',
        email: 'support@test.com',
      });
      expect(finalAgent.versions[1].support_contact).toEqual({});
      expect(finalAgent.versions[2].support_contact).toEqual({
        name: 'Support',
        email: 'support@test.com',
      });
    });

    test('should preserve support_contact in version history', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      // Create agent
      await createAgent({
        id: agentId,
        name: 'Version History Test',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        support_contact: {
          name: 'Initial Contact',
          email: 'initial@test.com',
        },
      });

      // Multiple updates with different support_contact values
      await updateAgent(
        { id: agentId },
        {
          support_contact: {
            name: 'Second Contact',
            email: 'second@test.com',
          },
        },
      );

      await updateAgent(
        { id: agentId },
        {
          support_contact: {
            name: 'Third Contact',
            email: 'third@test.com',
          },
        },
      );

      const finalAgent = await getAgent({ id: agentId });

      // Verify version history
      expect(finalAgent.versions).toHaveLength(3);
      expect(finalAgent.versions[0].support_contact).toEqual({
        name: 'Initial Contact',
        email: 'initial@test.com',
      });
      expect(finalAgent.versions[1].support_contact).toEqual({
        name: 'Second Contact',
        email: 'second@test.com',
      });
      expect(finalAgent.versions[2].support_contact).toEqual({
        name: 'Third Contact',
        email: 'third@test.com',
      });

      // Current state should match last version
      expect(finalAgent.support_contact).toEqual({
        name: 'Third Contact',
        email: 'third@test.com',
      });
    });

    test('should handle partial support_contact updates', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      // Create agent with full support_contact
      await createAgent({
        id: agentId,
        name: 'Partial Update Test',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        support_contact: {
          name: 'Original Name',
          email: 'original@email.com',
        },
      });

      // MongoDB's findOneAndUpdate will replace the entire support_contact object
      // So we need to verify that partial updates still work correctly
      const updated = await updateAgent(
        { id: agentId },
        {
          support_contact: {
            name: 'New Name',
            email: '', // Empty email
          },
        },
      );

      expect(updated.versions).toHaveLength(2);
      expect(updated.support_contact.name).toBe('New Name');
      expect(updated.support_contact.email).toBe('');

      // Verify isDuplicateVersion works with partial changes - should return successfully without creating new version
      const duplicateUpdate = await updateAgent(
        { id: agentId },
        {
          support_contact: {
            name: 'New Name',
            email: '',
          },
        },
      );

      // Should not create a new version since content is the same
      expect(duplicateUpdate.versions).toHaveLength(2);
      expect(duplicateUpdate.version).toBe(2);
      expect(duplicateUpdate.support_contact.name).toBe('New Name');
      expect(duplicateUpdate.support_contact.email).toBe('');
    });

    // Edge Cases
    describe.each([
      {
        operation: 'add',
        name: 'empty file_id',
        needsAgent: true,
        params: { tool_resource: 'file_search', file_id: '' },
        shouldResolve: true,
      },
      {
        operation: 'add',
        name: 'non-existent agent',
        needsAgent: false,
        params: { tool_resource: 'file_search', file_id: 'file123' },
        shouldResolve: false,
        error: 'Agent not found for adding resource file',
      },
    ])('addAgentResourceFile with $name', ({ needsAgent, params, shouldResolve, error }) => {
      test(`should ${shouldResolve ? 'resolve' : 'reject'}`, async () => {
        const agent = needsAgent ? await createBasicAgent() : null;
        const agent_id = needsAgent ? agent.id : `agent_${uuidv4()}`;

        if (shouldResolve) {
          await expect(addAgentResourceFile({ agent_id, ...params })).resolves.toBeDefined();
        } else {
          await expect(addAgentResourceFile({ agent_id, ...params })).rejects.toThrow(error);
        }
      });
    });

    describe.each([
      {
        name: 'empty files array',
        files: [],
        needsAgent: true,
        shouldResolve: true,
      },
      {
        name: 'non-existent tool_resource',
        files: [{ tool_resource: 'non_existent_tool', file_id: 'file123' }],
        needsAgent: true,
        shouldResolve: true,
      },
      {
        name: 'non-existent agent',
        files: [{ tool_resource: 'file_search', file_id: 'file123' }],
        needsAgent: false,
        shouldResolve: false,
        error: 'Agent not found for removing resource files',
      },
    ])('removeAgentResourceFiles with $name', ({ files, needsAgent, shouldResolve, error }) => {
      test(`should ${shouldResolve ? 'resolve' : 'reject'}`, async () => {
        const agent = needsAgent ? await createBasicAgent() : null;
        const agent_id = needsAgent ? agent.id : `agent_${uuidv4()}`;

        if (shouldResolve) {
          const result = await removeAgentResourceFiles({ agent_id, files });
          expect(result).toBeDefined();
          if (agent) {
            expect(result.id).toBe(agent.id);
          }
        } else {
          await expect(removeAgentResourceFiles({ agent_id, files })).rejects.toThrow(error);
        }
      });
    });

    describe('Edge Cases', () => {
      test('should handle extremely large version history', async () => {
        const agentId = `agent_${uuidv4()}`;
        const authorId = new mongoose.Types.ObjectId();

        await createAgent({
          id: agentId,
          name: 'Version Test',
          provider: 'test',
          model: 'test-model',
          author: authorId,
        });

        for (let i = 0; i < 20; i++) {
          await updateAgent({ id: agentId }, { description: `Version ${i}` });
        }

        const agent = await getAgent({ id: agentId });
        expect(agent.versions).toHaveLength(21);
        expect(agent.description).toBe('Version 19');
      });

      test('should handle revertAgentVersion with invalid version index', async () => {
        const agentId = `agent_${uuidv4()}`;
        const authorId = new mongoose.Types.ObjectId();

        await createAgent({
          id: agentId,
          name: 'Test Agent',
          provider: 'test',
          model: 'test-model',
          author: authorId,
        });

        await expect(revertAgentVersion({ id: agentId }, 5)).rejects.toThrow('Version 5 not found');
      });

      test('should handle revertAgentVersion with non-existent agent', async () => {
        const nonExistentId = `agent_${uuidv4()}`;

        await expect(revertAgentVersion({ id: nonExistentId }, 0)).rejects.toThrow(
          'Agent not found',
        );
      });

      test('should handle updateAgent with empty update object', async () => {
        const agentId = `agent_${uuidv4()}`;
        const authorId = new mongoose.Types.ObjectId();

        await createAgent({
          id: agentId,
          name: 'Test Agent',
          provider: 'test',
          model: 'test-model',
          author: authorId,
        });

        const updatedAgent = await updateAgent({ id: agentId }, {});

        expect(updatedAgent).toBeDefined();
        expect(updatedAgent.name).toBe('Test Agent');
        expect(updatedAgent.versions).toHaveLength(1);
      });
    });
  });

  describe('Action Metadata and Hash Generation', () => {
    let mongoServer;

    beforeAll(async () => {
      mongoServer = await MongoMemoryServer.create();
      const mongoUri = mongoServer.getUri();
      Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
      await mongoose.connect(mongoUri);
    }, 20000);

    afterAll(async () => {
      await mongoose.disconnect();
      await mongoServer.stop();
    });

    beforeEach(async () => {
      await Agent.deleteMany({});
    });

    test('should generate consistent hash for same action metadata', async () => {
      const actionIds = ['test.com_action_123', 'example.com_action_456'];
      const actions = [
        {
          action_id: '123',
          metadata: { version: '1.0', endpoints: ['GET /api/test'], schema: { type: 'object' } },
        },
        {
          action_id: '456',
          metadata: {
            version: '2.0',
            endpoints: ['POST /api/example'],
            schema: { type: 'string' },
          },
        },
      ];

      const hash1 = await generateActionMetadataHash(actionIds, actions);
      const hash2 = await generateActionMetadataHash(actionIds, actions);

      expect(hash1).toBe(hash2);
      expect(typeof hash1).toBe('string');
      expect(hash1.length).toBe(64); // SHA-256 produces 64 character hex string
    });

    test('should generate different hashes for different action metadata', async () => {
      const actionIds = ['test.com_action_123'];
      const actions1 = [
        { action_id: '123', metadata: { version: '1.0', endpoints: ['GET /api/test'] } },
      ];
      const actions2 = [
        { action_id: '123', metadata: { version: '2.0', endpoints: ['GET /api/test'] } },
      ];

      const hash1 = await generateActionMetadataHash(actionIds, actions1);
      const hash2 = await generateActionMetadataHash(actionIds, actions2);

      expect(hash1).not.toBe(hash2);
    });

    test('should handle empty action arrays', async () => {
      const hash = await generateActionMetadataHash([], []);
      expect(hash).toBe('');
    });

    test('should handle null or undefined action arrays', async () => {
      const hash1 = await generateActionMetadataHash(null, []);
      const hash2 = await generateActionMetadataHash(undefined, []);

      expect(hash1).toBe('');
      expect(hash2).toBe('');
    });

    test('should handle missing action metadata gracefully', async () => {
      const actionIds = ['test.com_action_123', 'missing.com_action_999'];
      const actions = [
        { action_id: '123', metadata: { version: '1.0' } },
        // missing action with id '999'
      ];

      const hash = await generateActionMetadataHash(actionIds, actions);
      expect(typeof hash).toBe('string');
      expect(hash.length).toBe(64);
    });

    test('should sort action IDs for consistent hashing', async () => {
      const actionIds1 = ['b.com_action_2', 'a.com_action_1'];
      const actionIds2 = ['a.com_action_1', 'b.com_action_2'];
      const actions = [
        { action_id: '1', metadata: { version: '1.0' } },
        { action_id: '2', metadata: { version: '2.0' } },
      ];

      const hash1 = await generateActionMetadataHash(actionIds1, actions);
      const hash2 = await generateActionMetadataHash(actionIds2, actions);

      expect(hash1).toBe(hash2);
    });

    test('should handle complex nested metadata objects', async () => {
      const actionIds = ['complex.com_action_1'];
      const actions = [
        {
          action_id: '1',
          metadata: {
            version: '1.0',
            schema: {
              type: 'object',
              properties: {
                name: { type: 'string' },
                nested: {
                  type: 'object',
                  properties: {
                    id: { type: 'number' },
                    tags: { type: 'array', items: { type: 'string' } },
                  },
                },
              },
            },
            endpoints: [
              { path: '/api/test', method: 'GET', params: ['id'] },
              { path: '/api/create', method: 'POST', body: true },
            ],
          },
        },
      ];

      const hash = await generateActionMetadataHash(actionIds, actions);
      expect(typeof hash).toBe('string');
      expect(hash.length).toBe(64);
    });

    describe('Edge Cases', () => {
      test('should handle generateActionMetadataHash with null metadata', async () => {
        const hash = await generateActionMetadataHash(
          ['test.com_action_1'],
          [{ action_id: '1', metadata: null }],
        );
        expect(typeof hash).toBe('string');
      });

      test('should handle generateActionMetadataHash with deeply nested metadata', async () => {
        const deepMetadata = {
          level1: {
            level2: {
              level3: {
                level4: {
                  level5: 'deep value',
                  array: [1, 2, { nested: true }],
                },
              },
            },
          },
        };

        const hash = await generateActionMetadataHash(
          ['test.com_action_1'],
          [{ action_id: '1', metadata: deepMetadata }],
        );

        expect(typeof hash).toBe('string');
        expect(hash.length).toBe(64);
      });

      test('should handle generateActionMetadataHash with special characters', async () => {
        const specialMetadata = {
          unicode: '🚀🎉👍',
          symbols: '!@#$%^&*()_+-=[]{}|;:,.<>?',
          quotes: 'single\'s and "doubles"',
          newlines: 'line1\nline2\r\nline3',
        };

        const hash = await generateActionMetadataHash(
          ['test.com_action_1'],
          [{ action_id: '1', metadata: specialMetadata }],
        );

        expect(typeof hash).toBe('string');
        expect(hash.length).toBe(64);
      });
    });
  });

  describe('Load Agent Functionality', () => {
    let mongoServer;

    beforeAll(async () => {
      mongoServer = await MongoMemoryServer.create();
      const mongoUri = mongoServer.getUri();
      Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
      await mongoose.connect(mongoUri);
    }, 20000);

    afterAll(async () => {
      await mongoose.disconnect();
      await mongoServer.stop();
    });

    beforeEach(async () => {
      await Agent.deleteMany({});
    });

    test('should return null when agent_id is not provided', async () => {
      const mockReq = { user: { id: 'user123' } };
      const result = await loadAgent({
        req: mockReq,
        agent_id: null,
        endpoint: 'openai',
        model_parameters: { model: 'gpt-4' },
      });

      expect(result).toBeNull();
    });

    test('should return null when agent_id is empty string', async () => {
      const mockReq = { user: { id: 'user123' } };
      const result = await loadAgent({
        req: mockReq,
        agent_id: '',
        endpoint: 'openai',
        model_parameters: { model: 'gpt-4' },
      });

      expect(result).toBeNull();
    });

    test('should test ephemeral agent loading logic', async () => {
      const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;

      getCachedTools.mockResolvedValue({
        tool1_mcp_server1: {},
        tool2_mcp_server2: {},
        another_tool: {},
      });

      // Mock getMCPServerTools to return tools for each server
      getMCPServerTools.mockImplementation(async (_userId, server) => {
        if (server === 'server1') {
          return { tool1_mcp_server1: {} };
        } else if (server === 'server2') {
          return { tool2_mcp_server2: {} };
        }
        return null;
      });

      const mockReq = {
        user: { id: 'user123' },
        body: {
          promptPrefix: 'Test instructions',
          ephemeralAgent: {
            execute_code: true,
            web_search: true,
            mcp: ['server1', 'server2'],
          },
        },
      };

      const result = await loadAgent({
        req: mockReq,
        agent_id: EPHEMERAL_AGENT_ID,
        endpoint: 'openai',
        model_parameters: { model: 'gpt-4', temperature: 0.7 },
      });

      if (result) {
        // Ephemeral agent ID is encoded with endpoint and model
        expect(result.id).toBe('openai__gpt-4');
        expect(result.instructions).toBe('Test instructions');
        expect(result.provider).toBe('openai');
        expect(result.model).toBe('gpt-4');
        expect(result.model_parameters.temperature).toBe(0.7);
        expect(result.tools).toContain('execute_code');
        expect(result.tools).toContain('web_search');
        expect(result.tools).toContain('tool1_mcp_server1');
        expect(result.tools).toContain('tool2_mcp_server2');
      } else {
        expect(result).toBeNull();
      }
    });

    test('should return null for non-existent agent', async () => {
      const mockReq = { user: { id: 'user123' } };
      const result = await loadAgent({
        req: mockReq,
        agent_id: 'agent_non_existent',
        endpoint: 'openai',
        model_parameters: { model: 'gpt-4' },
      });

      expect(result).toBeNull();
    });

    test('should load agent when user is the author', async () => {
      const userId = new mongoose.Types.ObjectId();
      const agentId = `agent_${uuidv4()}`;

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'openai',
        model: 'gpt-4',
        author: userId,
        description: 'Test description',
        tools: ['web_search'],
      });

      const mockReq = { user: { id: userId.toString() } };
      const result = await loadAgent({
        req: mockReq,
        agent_id: agentId,
        endpoint: 'openai',
        model_parameters: { model: 'gpt-4' },
      });

      expect(result).toBeDefined();
      expect(result.id).toBe(agentId);
      expect(result.name).toBe('Test Agent');
      expect(result.author.toString()).toBe(userId.toString());
      expect(result.version).toBe(1);
    });

    test('should return agent even when user is not author (permissions checked at route level)', async () => {
      const authorId = new mongoose.Types.ObjectId();
      const userId = new mongoose.Types.ObjectId();
      const agentId = `agent_${uuidv4()}`;

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'openai',
        model: 'gpt-4',
        author: authorId,
      });

      const mockReq = { user: { id: userId.toString() } };
      const result = await loadAgent({
        req: mockReq,
        agent_id: agentId,
        endpoint: 'openai',
        model_parameters: { model: 'gpt-4' },
      });

      // With the new permission system, loadAgent returns the agent regardless of permissions
      // Permission checks are handled at the route level via middleware
      expect(result).toBeTruthy();
      expect(result.id).toBe(agentId);
      expect(result.name).toBe('Test Agent');
    });

    test('should handle ephemeral agent with no MCP servers', async () => {
      const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;

      getCachedTools.mockResolvedValue({});

      const mockReq = {
        user: { id: 'user123' },
        body: {
          promptPrefix: 'Simple instructions',
          ephemeralAgent: {
            execute_code: false,
            web_search: false,
            mcp: [],
          },
        },
      };

      const result = await loadAgent({
        req: mockReq,
        agent_id: EPHEMERAL_AGENT_ID,
        endpoint: 'openai',
        model_parameters: { model: 'gpt-3.5-turbo' },
      });

      if (result) {
        expect(result.tools).toEqual([]);
        expect(result.instructions).toBe('Simple instructions');
      } else {
        expect(result).toBeFalsy();
      }
    });

    test('should handle ephemeral agent with undefined ephemeralAgent in body', async () => {
      const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;

      getCachedTools.mockResolvedValue({});

      const mockReq = {
        user: { id: 'user123' },
        body: {
          promptPrefix: 'Basic instructions',
        },
      };

      const result = await loadAgent({
        req: mockReq,
        agent_id: EPHEMERAL_AGENT_ID,
        endpoint: 'openai',
        model_parameters: { model: 'gpt-4' },
      });

      if (result) {
        expect(result.tools).toEqual([]);
      } else {
        expect(result).toBeFalsy();
      }
    });

    describe('Edge Cases', () => {
      test('should handle loadAgent with malformed req object', async () => {
        const result = await loadAgent({
          req: null,
          agent_id: 'agent_test',
          endpoint: 'openai',
          model_parameters: { model: 'gpt-4' },
        });

        expect(result).toBeNull();
      });

      test('should handle ephemeral agent with extremely large tool list', async () => {
        const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;

        const largeToolList = Array.from({ length: 100 }, (_, i) => `tool_${i}_mcp_server1`);
        const availableTools = largeToolList.reduce((acc, tool) => {
          acc[tool] = {};
          return acc;
        }, {});

        getCachedTools.mockResolvedValue(availableTools);

        // Mock getMCPServerTools to return all tools for server1
        getMCPServerTools.mockImplementation(async (_userId, server) => {
          if (server === 'server1') {
            return availableTools; // All 100 tools belong to server1
          }
          return null;
        });

        const mockReq = {
          user: { id: 'user123' },
          body: {
            promptPrefix: 'Test',
            ephemeralAgent: {
              execute_code: true,
              web_search: true,
              mcp: ['server1'],
            },
          },
        };

        const result = await loadAgent({
          req: mockReq,
          agent_id: EPHEMERAL_AGENT_ID,
          endpoint: 'openai',
          model_parameters: { model: 'gpt-4' },
        });

        if (result) {
          expect(result.tools.length).toBeGreaterThan(100);
        }
      });

      test('should return agent from different project (permissions checked at route level)', async () => {
        const authorId = new mongoose.Types.ObjectId();
        const userId = new mongoose.Types.ObjectId();
        const agentId = `agent_${uuidv4()}`;
        const projectId = new mongoose.Types.ObjectId();

        await createAgent({
          id: agentId,
          name: 'Project Agent',
          provider: 'openai',
          model: 'gpt-4',
          author: authorId,
          projectIds: [projectId],
        });

        const mockReq = { user: { id: userId.toString() } };
        const result = await loadAgent({
          req: mockReq,
          agent_id: agentId,
          endpoint: 'openai',
          model_parameters: { model: 'gpt-4' },
        });

        // With the new permission system, loadAgent returns the agent regardless of permissions
        // Permission checks are handled at the route level via middleware
        expect(result).toBeTruthy();
        expect(result.id).toBe(agentId);
        expect(result.name).toBe('Project Agent');
      });
    });
  });

  describe('Agent Edge Cases and Error Handling', () => {
    let mongoServer;

    beforeAll(async () => {
      mongoServer = await MongoMemoryServer.create();
      const mongoUri = mongoServer.getUri();
      Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
      await mongoose.connect(mongoUri);
    }, 20000);

    afterAll(async () => {
      await mongoose.disconnect();
      await mongoServer.stop();
    });

    beforeEach(async () => {
      await Agent.deleteMany({});
    });

    test('should handle agent creation with minimal required fields', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      const agent = await createAgent({
        id: agentId,
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      expect(agent).toBeDefined();
      expect(agent.id).toBe(agentId);
      expect(agent.versions).toHaveLength(1);
      expect(agent.versions[0].provider).toBe('test');
      expect(agent.versions[0].model).toBe('test-model');
    });

    test('should handle agent creation with all optional fields', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const projectId = new mongoose.Types.ObjectId();

      const agent = await createAgent({
        id: agentId,
        name: 'Complex Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        description: 'Complex description',
        instructions: 'Complex instructions',
        tools: ['tool1', 'tool2'],
        actions: ['action1', 'action2'],
        model_parameters: { temperature: 0.8, max_tokens: 1000 },
        projectIds: [projectId],
        avatar: 'https://example.com/avatar.png',
        isCollaborative: true,
        tool_resources: {
          file_search: { file_ids: ['file1', 'file2'] },
        },
      });

      expect(agent).toBeDefined();
      expect(agent.name).toBe('Complex Agent');
      expect(agent.description).toBe('Complex description');
      expect(agent.instructions).toBe('Complex instructions');
      expect(agent.tools).toEqual(['tool1', 'tool2']);
      expect(agent.actions).toEqual(['action1', 'action2']);
      expect(agent.model_parameters.temperature).toBe(0.8);
      expect(agent.model_parameters.max_tokens).toBe(1000);
      expect(agent.projectIds.map((id) => id.toString())).toContain(projectId.toString());
      expect(agent.avatar).toBe('https://example.com/avatar.png');
      expect(agent.isCollaborative).toBe(true);
      expect(agent.tool_resources.file_search.file_ids).toEqual(['file1', 'file2']);
    });

    test('should handle updateAgent with empty update object', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      const updatedAgent = await updateAgent({ id: agentId }, {});

      expect(updatedAgent).toBeDefined();
      expect(updatedAgent.name).toBe('Test Agent');
      expect(updatedAgent.versions).toHaveLength(1); // No new version should be created
    });

    test('should handle concurrent updates to different agents', async () => {
      const agent1Id = `agent_${uuidv4()}`;
      const agent2Id = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agent1Id,
        name: 'Agent 1',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await createAgent({
        id: agent2Id,
        name: 'Agent 2',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Concurrent updates to different agents
      const [updated1, updated2] = await Promise.all([
        updateAgent({ id: agent1Id }, { description: 'Updated Agent 1' }),
        updateAgent({ id: agent2Id }, { description: 'Updated Agent 2' }),
      ]);

      expect(updated1.description).toBe('Updated Agent 1');
      expect(updated2.description).toBe('Updated Agent 2');
      expect(updated1.versions).toHaveLength(2);
      expect(updated2.versions).toHaveLength(2);
    });

    test('should handle agent deletion with non-existent ID', async () => {
      const nonExistentId = `agent_${uuidv4()}`;
      const result = await deleteAgent({ id: nonExistentId });

      expect(result).toBeNull();
    });

    test('should handle updateAgent with MongoDB operators mixed with direct updates', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        tools: ['tool1'],
      });

      // Test with $push and direct field update
      const updatedAgent = await updateAgent(
        { id: agentId },
        {
          name: 'Updated Name',
          $push: { tools: 'tool2' },
        },
      );

      expect(updatedAgent.name).toBe('Updated Name');
      expect(updatedAgent.tools).toContain('tool1');
      expect(updatedAgent.tools).toContain('tool2');
      expect(updatedAgent.versions).toHaveLength(2);
    });

    test('should handle revertAgentVersion with invalid version index', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Try to revert to non-existent version
      await expect(revertAgentVersion({ id: agentId }, 5)).rejects.toThrow('Version 5 not found');
    });

    test('should handle revertAgentVersion with non-existent agent', async () => {
      const nonExistentId = `agent_${uuidv4()}`;

      await expect(revertAgentVersion({ id: nonExistentId }, 0)).rejects.toThrow('Agent not found');
    });

    test('should handle addAgentResourceFile with non-existent agent', async () => {
      const nonExistentId = `agent_${uuidv4()}`;
      const mockReq = { user: { id: 'user123' } };

      await expect(
        addAgentResourceFile({
          req: mockReq,
          agent_id: nonExistentId,
          tool_resource: 'file_search',
          file_id: 'file123',
        }),
      ).rejects.toThrow('Agent not found for adding resource file');
    });

    test('should handle removeAgentResourceFiles with non-existent agent', async () => {
      const nonExistentId = `agent_${uuidv4()}`;

      await expect(
        removeAgentResourceFiles({
          agent_id: nonExistentId,
          files: [{ tool_resource: 'file_search', file_id: 'file123' }],
        }),
      ).rejects.toThrow('Agent not found for removing resource files');
    });

    test('should handle updateAgent with complex nested updates', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        model_parameters: { temperature: 0.5 },
        tools: ['tool1'],
      });

      // First update with $push operation
      const firstUpdate = await updateAgent(
        { id: agentId },
        {
          $push: { tools: 'tool2' },
        },
      );

      expect(firstUpdate.tools).toContain('tool1');
      expect(firstUpdate.tools).toContain('tool2');

      // Second update with direct field update and $addToSet
      const secondUpdate = await updateAgent(
        { id: agentId },
        {
          name: 'Updated Agent',
          model_parameters: { temperature: 0.8, max_tokens: 500 },
          $addToSet: { tools: 'tool3' },
        },
      );

      expect(secondUpdate.name).toBe('Updated Agent');
      expect(secondUpdate.model_parameters.temperature).toBe(0.8);
      expect(secondUpdate.model_parameters.max_tokens).toBe(500);
      expect(secondUpdate.tools).toContain('tool1');
      expect(secondUpdate.tools).toContain('tool2');
      expect(secondUpdate.tools).toContain('tool3');
      expect(secondUpdate.versions).toHaveLength(3);
    });

    test('should preserve version order in versions array', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Version 1',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      await updateAgent({ id: agentId }, { name: 'Version 2' });
      await updateAgent({ id: agentId }, { name: 'Version 3' });
      const finalAgent = await updateAgent({ id: agentId }, { name: 'Version 4' });

      expect(finalAgent.versions).toHaveLength(4);
      expect(finalAgent.versions[0].name).toBe('Version 1');
      expect(finalAgent.versions[1].name).toBe('Version 2');
      expect(finalAgent.versions[2].name).toBe('Version 3');
      expect(finalAgent.versions[3].name).toBe('Version 4');
      expect(finalAgent.name).toBe('Version 4');
    });

    test('should handle updateAgentProjects error scenarios', async () => {
      const nonExistentId = `agent_${uuidv4()}`;
      const userId = new mongoose.Types.ObjectId();
      const projectId = new mongoose.Types.ObjectId();

      // Test with non-existent agent
      const result = await updateAgentProjects({
        user: { id: userId.toString() },
        agentId: nonExistentId,
        projectIds: [projectId.toString()],
      });

      expect(result).toBeNull();
    });

    test('should handle revertAgentVersion properly', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Original Name',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        description: 'Original description',
      });

      await updateAgent(
        { id: agentId },
        { name: 'Updated Name', description: 'Updated description' },
      );

      const revertedAgent = await revertAgentVersion({ id: agentId }, 0);

      expect(revertedAgent.name).toBe('Original Name');
      expect(revertedAgent.description).toBe('Original description');
      expect(revertedAgent.author.toString()).toBe(authorId.toString());
    });

    test('should handle action-related updates with getActions error', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      // Create agent with actions that might cause getActions to fail
      await createAgent({
        id: agentId,
        name: 'Agent with Actions',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        actions: ['test.com_action_invalid_id'],
      });

      // Update should still work even if getActions fails
      const updatedAgent = await updateAgent(
        { id: agentId },
        { description: 'Updated description' },
      );

      expect(updatedAgent).toBeDefined();
      expect(updatedAgent.description).toBe('Updated description');
      expect(updatedAgent.versions).toHaveLength(2);
    });

    test('should handle updateAgent with combined MongoDB operators', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const projectId1 = new mongoose.Types.ObjectId();
      const projectId2 = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        tools: ['tool1'],
        projectIds: [projectId1],
      });

      // Use multiple operators in single update - but avoid conflicting operations on same field
      const updatedAgent = await updateAgent(
        { id: agentId },
        {
          name: 'Updated Name',
          $push: { tools: 'tool2' },
          $addToSet: { projectIds: projectId2 },
        },
      );

      const finalAgent = await updateAgent(
        { id: agentId },
        {
          $pull: { projectIds: projectId1 },
        },
      );

      expect(updatedAgent).toBeDefined();
      expect(updatedAgent.name).toBe('Updated Name');
      expect(updatedAgent.tools).toContain('tool1');
      expect(updatedAgent.tools).toContain('tool2');
      expect(updatedAgent.projectIds.map((id) => id.toString())).toContain(projectId2.toString());

      expect(finalAgent).toBeDefined();
      expect(finalAgent.projectIds.map((id) => id.toString())).not.toContain(projectId1.toString());
      expect(finalAgent.versions).toHaveLength(3);
    });

    test('should handle updateAgent when agent does not exist', async () => {
      const nonExistentId = `agent_${uuidv4()}`;

      const result = await updateAgent({ id: nonExistentId }, { name: 'New Name' });

      expect(result).toBeNull();
    });

    test('should handle concurrent updates with database errors', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Mock findOneAndUpdate to simulate database error
      const cleanup = mockFindOneAndUpdateError(2);

      // Concurrent updates where one fails
      const promises = [
        updateAgent({ id: agentId }, { name: 'Update 1' }),
        updateAgent({ id: agentId }, { name: 'Update 2' }),
        updateAgent({ id: agentId }, { name: 'Update 3' }),
      ];

      const results = await Promise.allSettled(promises);

      cleanup();

      const succeeded = results.filter((r) => r.status === 'fulfilled').length;
      const failed = results.filter((r) => r.status === 'rejected').length;

      expect(succeeded).toBe(2);
      expect(failed).toBe(1);
    });

    test('should handle removeAgentResourceFiles when agent is deleted during operation', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        tool_resources: {
          file_search: {
            file_ids: ['file1', 'file2', 'file3'],
          },
        },
      });

      // Mock findOneAndUpdate to return null (simulating deletion)
      const originalFindOneAndUpdate = Agent.findOneAndUpdate;
      Agent.findOneAndUpdate = jest.fn().mockImplementation(() => ({
        lean: jest.fn().mockResolvedValue(null),
      }));

      // Try to remove files from deleted agent
      await expect(
        removeAgentResourceFiles({
          agent_id: agentId,
          files: [
            { tool_resource: 'file_search', file_id: 'file1' },
            { tool_resource: 'file_search', file_id: 'file2' },
          ],
        }),
      ).rejects.toThrow('Failed to update agent during file removal (pull step)');

      Agent.findOneAndUpdate = originalFindOneAndUpdate;
    });

    test('should handle loadEphemeralAgent with malformed MCP tool names', async () => {
      const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;

      getCachedTools.mockResolvedValue({
        malformed_tool_name: {}, // No mcp delimiter
        tool__server1: {}, // Wrong delimiter
        tool_mcp_server1: {}, // Correct format
        tool_mcp_server2: {}, // Different server
      });

      // Mock getMCPServerTools to return only tools matching the server
      getMCPServerTools.mockImplementation(async (_userId, server) => {
        if (server === 'server1') {
          // Only return tool that correctly matches server1 format
          return { tool_mcp_server1: {} };
        } else if (server === 'server2') {
          return { tool_mcp_server2: {} };
        }
        return null;
      });

      const mockReq = {
        user: { id: 'user123' },
        body: {
          promptPrefix: 'Test instructions',
          ephemeralAgent: {
            execute_code: false,
            web_search: false,
            mcp: ['server1'],
          },
        },
      };

      const result = await loadAgent({
        req: mockReq,
        agent_id: EPHEMERAL_AGENT_ID,
        endpoint: 'openai',
        model_parameters: { model: 'gpt-4' },
      });

      if (result) {
        expect(result.tools).toEqual(['tool_mcp_server1']);
        expect(result.tools).not.toContain('malformed_tool_name');
        expect(result.tools).not.toContain('tool__server1');
        expect(result.tools).not.toContain('tool_mcp_server2');
      }
    });

    test('should handle addAgentResourceFile when array initialization fails', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      // Mock the updateOne operation to fail but let updateAgent succeed
      const originalUpdateOne = Agent.updateOne;
      let updateOneCalled = false;
      Agent.updateOne = jest.fn().mockImplementation((...args) => {
        if (!updateOneCalled) {
          updateOneCalled = true;
          return Promise.reject(new Error('Database error'));
        }
        return originalUpdateOne.apply(Agent, args);
      });

      try {
        const result = await addAgentResourceFile({
          agent_id: agentId,
          tool_resource: 'new_tool',
          file_id: 'file123',
        });

        expect(result).toBeDefined();
        expect(result.tools).toContain('new_tool');
      } catch (error) {
        expect(error.message).toBe('Database error');
      }

      Agent.updateOne = originalUpdateOne;
    });
  });

  describe('Agent IDs Field in Version Detection', () => {
    let mongoServer;

    beforeAll(async () => {
      mongoServer = await MongoMemoryServer.create();
      const mongoUri = mongoServer.getUri();
      Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
      await mongoose.connect(mongoUri);
    }, 20000);

    afterAll(async () => {
      await mongoose.disconnect();
      await mongoServer.stop();
    });

    beforeEach(async () => {
      await Agent.deleteMany({});
    });

    test('should now create new version when agent_ids field changes', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      const agent = await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        agent_ids: ['agent1', 'agent2'],
      });

      expect(agent).toBeDefined();
      expect(agent.versions).toHaveLength(1);

      const updated = await updateAgent(
        { id: agentId },
        { agent_ids: ['agent1', 'agent2', 'agent3'] },
      );

      // Since agent_ids is no longer excluded, this should create a new version
      expect(updated.versions).toHaveLength(2);
      expect(updated.agent_ids).toEqual(['agent1', 'agent2', 'agent3']);
    });

    test('should detect duplicate version if agent_ids is updated to same value', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        agent_ids: ['agent1', 'agent2'],
      });

      const updatedAgent = await updateAgent(
        { id: agentId },
        { agent_ids: ['agent1', 'agent2', 'agent3'] },
      );
      expect(updatedAgent.versions).toHaveLength(2);

      // Update with same agent_ids should succeed but not create a new version
      const duplicateUpdate = await updateAgent(
        { id: agentId },
        { agent_ids: ['agent1', 'agent2', 'agent3'] },
      );
      expect(duplicateUpdate.versions).toHaveLength(2); // No new version created
    });

    test('should handle agent_ids field alongside other fields', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        description: 'Initial description',
        agent_ids: ['agent1'],
      });

      const updated = await updateAgent(
        { id: agentId },
        {
          agent_ids: ['agent1', 'agent2'],
          description: 'Updated description',
        },
      );

      expect(updated.versions).toHaveLength(2);
      expect(updated.agent_ids).toEqual(['agent1', 'agent2']);
      expect(updated.description).toBe('Updated description');

      const updated2 = await updateAgent({ id: agentId }, { description: 'Another description' });

      expect(updated2.versions).toHaveLength(3);
      expect(updated2.agent_ids).toEqual(['agent1', 'agent2']);
      expect(updated2.description).toBe('Another description');
    });

    test('should skip version creation when skipVersioning option is used', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();
      const projectId1 = new mongoose.Types.ObjectId();
      const projectId2 = new mongoose.Types.ObjectId();

      // Create agent with initial projectIds
      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        projectIds: [projectId1],
      });

      // Share agent using updateAgentProjects (which uses skipVersioning)
      const shared = await updateAgentProjects({
        user: { id: authorId.toString() }, // Use the same author ID
        agentId: agentId,
        projectIds: [projectId2.toString()],
      });

      // Should NOT create a new version due to skipVersioning
      expect(shared.versions).toHaveLength(1);
      expect(shared.projectIds.map((id) => id.toString())).toContain(projectId1.toString());
      expect(shared.projectIds.map((id) => id.toString())).toContain(projectId2.toString());

      // Unshare agent using updateAgentProjects
      const unshared = await updateAgentProjects({
        user: { id: authorId.toString() },
        agentId: agentId,
        removeProjectIds: [projectId1.toString()],
      });

      // Still should NOT create a new version
      expect(unshared.versions).toHaveLength(1);
      expect(unshared.projectIds.map((id) => id.toString())).not.toContain(projectId1.toString());
      expect(unshared.projectIds.map((id) => id.toString())).toContain(projectId2.toString());

      // Regular update without skipVersioning should create a version
      const regularUpdate = await updateAgent(
        { id: agentId },
        { description: 'Updated description' },
      );

      expect(regularUpdate.versions).toHaveLength(2);
      expect(regularUpdate.description).toBe('Updated description');

      // Direct updateAgent with MongoDB operators should still create versions
      const directUpdate = await updateAgent(
        { id: agentId },
        { $addToSet: { projectIds: { $each: [projectId1] } } },
      );

      expect(directUpdate.versions).toHaveLength(3);
      expect(directUpdate.projectIds.length).toBe(2);
    });

    test('should preserve agent_ids in version history', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        agent_ids: ['agent1'],
      });

      await updateAgent({ id: agentId }, { agent_ids: ['agent1', 'agent2'] });

      await updateAgent({ id: agentId }, { agent_ids: ['agent3'] });

      const finalAgent = await getAgent({ id: agentId });

      expect(finalAgent.versions).toHaveLength(3);
      expect(finalAgent.versions[0].agent_ids).toEqual(['agent1']);
      expect(finalAgent.versions[1].agent_ids).toEqual(['agent1', 'agent2']);
      expect(finalAgent.versions[2].agent_ids).toEqual(['agent3']);
      expect(finalAgent.agent_ids).toEqual(['agent3']);
    });

    test('should handle empty agent_ids arrays', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
        agent_ids: ['agent1', 'agent2'],
      });

      const updated = await updateAgent({ id: agentId }, { agent_ids: [] });

      expect(updated.versions).toHaveLength(2);
      expect(updated.agent_ids).toEqual([]);

      // Update with same empty agent_ids should succeed but not create a new version
      const duplicateUpdate = await updateAgent({ id: agentId }, { agent_ids: [] });
      expect(duplicateUpdate.versions).toHaveLength(2); // No new version created
      expect(duplicateUpdate.agent_ids).toEqual([]);
    });

    test('should handle agent without agent_ids field', async () => {
      const agentId = `agent_${uuidv4()}`;
      const authorId = new mongoose.Types.ObjectId();

      const agent = await createAgent({
        id: agentId,
        name: 'Test Agent',
        provider: 'test',
        model: 'test-model',
        author: authorId,
      });

      expect(agent.agent_ids).toEqual([]);

      const updated = await updateAgent({ id: agentId }, { agent_ids: ['agent1'] });

      expect(updated.versions).toHaveLength(2);
      expect(updated.agent_ids).toEqual(['agent1']);
    });
  });
});

describe('Support Contact Field', () => {
  let mongoServer;

  beforeAll(async () => {
    mongoServer = await MongoMemoryServer.create();
    const mongoUri = mongoServer.getUri();
    Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
    await mongoose.connect(mongoUri);
  }, 20000);

  afterAll(async () => {
    await mongoose.disconnect();
    await mongoServer.stop();
  });

  beforeEach(async () => {
    await Agent.deleteMany({});
  });

  it('should not create subdocument with ObjectId for support_contact', async () => {
    const userId = new mongoose.Types.ObjectId();
    const agentData = {
      id: 'agent_test_support',
      name: 'Test Agent',
      provider: 'openai',
      model: 'gpt-4',
      author: userId,
      support_contact: {
        name: 'Support Team',
        email: 'support@example.com',
      },
    };

    // Create agent
    const agent = await createAgent(agentData);

    // Verify support_contact is stored correctly
    expect(agent.support_contact).toBeDefined();
    expect(agent.support_contact.name).toBe('Support Team');
    expect(agent.support_contact.email).toBe('support@example.com');

    // Verify no _id field is created in support_contact
    expect(agent.support_contact._id).toBeUndefined();

    // Fetch from database to double-check
    const dbAgent = await Agent.findOne({ id: agentData.id });
    expect(dbAgent.support_contact).toBeDefined();
    expect(dbAgent.support_contact.name).toBe('Support Team');
    expect(dbAgent.support_contact.email).toBe('support@example.com');
    expect(dbAgent.support_contact._id).toBeUndefined();
  });

  it('should handle empty support_contact correctly', async () => {
    const userId = new mongoose.Types.ObjectId();
    const agentData = {
      id: 'agent_test_empty_support',
      name: 'Test Agent',
      provider: 'openai',
      model: 'gpt-4',
      author: userId,
      support_contact: {},
    };

    const agent = await createAgent(agentData);

    // Verify empty support_contact is stored as empty object
    expect(agent.support_contact).toEqual({});
    expect(agent.support_contact._id).toBeUndefined();
  });

  it('should handle missing support_contact correctly', async () => {
    const userId = new mongoose.Types.ObjectId();
    const agentData = {
      id: 'agent_test_no_support',
      name: 'Test Agent',
      provider: 'openai',
      model: 'gpt-4',
      author: userId,
    };

    const agent = await createAgent(agentData);

    // Verify support_contact is undefined when not provided
    expect(agent.support_contact).toBeUndefined();
  });

  describe('getListAgentsByAccess - Security Tests', () => {
    let userA, userB;
    let agentA1, agentA2, agentA3;

    beforeEach(async () => {
      Agent = mongoose.models.Agent || mongoose.model('Agent', agentSchema);
      await Agent.deleteMany({});
      await AclEntry.deleteMany({});

      // Create two users
      userA = new mongoose.Types.ObjectId();
      userB = new mongoose.Types.ObjectId();

      // Create agents for user A
      agentA1 = await createAgent({
        id: `agent_${uuidv4().slice(0, 12)}`,
        name: 'Agent A1',
        description: 'User A agent 1',
        provider: 'openai',
        model: 'gpt-4',
        author: userA,
      });

      agentA2 = await createAgent({
        id: `agent_${uuidv4().slice(0, 12)}`,
        name: 'Agent A2',
        description: 'User A agent 2',
        provider: 'openai',
        model: 'gpt-4',
        author: userA,
      });

      agentA3 = await createAgent({
        id: `agent_${uuidv4().slice(0, 12)}`,
        name: 'Agent A3',
        description: 'User A agent 3',
        provider: 'openai',
        model: 'gpt-4',
        author: userA,
      });
    });

    test('should return empty list when user has no accessible agents (empty accessibleIds)', async () => {
      // User B has no agents and no shared agents
      const result = await getListAgentsByAccess({
        accessibleIds: [],
        otherParams: {},
      });

      expect(result.data).toHaveLength(0);
      expect(result.has_more).toBe(false);
      expect(result.first_id).toBeNull();
      expect(result.last_id).toBeNull();
    });

    test('should not return other users agents when accessibleIds is empty', async () => {
      // User B trying to list agents with empty accessibleIds should not see User A's agents
      const result = await getListAgentsByAccess({
        accessibleIds: [],
        otherParams: { author: userB },
      });

      expect(result.data).toHaveLength(0);
      expect(result.has_more).toBe(false);
    });

    test('should only return agents in accessibleIds list', async () => {
      // Give User B access to only one of User A's agents
      const accessibleIds = [agentA1._id];

      const result = await getListAgentsByAccess({
        accessibleIds,
        otherParams: {},
      });

      expect(result.data).toHaveLength(1);
      expect(result.data[0].id).toBe(agentA1.id);
      expect(result.data[0].name).toBe('Agent A1');
    });

    test('should return multiple accessible agents when provided', async () => {
      // Give User B access to two of User A's agents
      const accessibleIds = [agentA1._id, agentA3._id];

      const result = await getListAgentsByAccess({
        accessibleIds,
        otherParams: {},
      });

      expect(result.data).toHaveLength(2);
      const returnedIds = result.data.map((agent) => agent.id);
      expect(returnedIds).toContain(agentA1.id);
      expect(returnedIds).toContain(agentA3.id);
      expect(returnedIds).not.toContain(agentA2.id);
    });

    test('should respect other query parameters while enforcing accessibleIds', async () => {
      // Give access to all agents but filter by name
      const accessibleIds = [agentA1._id, agentA2._id, agentA3._id];

      const result = await getListAgentsByAccess({
        accessibleIds,
        otherParams: { name: 'Agent A2' },
      });

      expect(result.data).toHaveLength(1);
      expect(result.data[0].id).toBe(agentA2.id);
    });

    test('should handle pagination correctly with accessibleIds filter', async () => {
      // Create more agents
      const moreAgents = [];
      for (let i = 4; i <= 10; i++) {
        const agent = await createAgent({
          id: `agent_${uuidv4().slice(0, 12)}`,
          name: `Agent A${i}`,
          description: `User A agent ${i}`,
          provider: 'openai',
          model: 'gpt-4',
          author: userA,
        });
        moreAgents.push(agent);
      }

      // Give access to all agents
      const allAgentIds = [agentA1, agentA2, agentA3, ...moreAgents].map((a) => a._id);

      // First page
      const page1 = await getListAgentsByAccess({
        accessibleIds: allAgentIds,
        otherParams: {},
        limit: 5,
      });

      expect(page1.data).toHaveLength(5);
      expect(page1.has_more).toBe(true);
      expect(page1.after).toBeTruthy();

      // Second page
      const page2 = await getListAgentsByAccess({
        accessibleIds: allAgentIds,
        otherParams: {},
        limit: 5,
        after: page1.after,
      });

      expect(page2.data).toHaveLength(5);
      expect(page2.has_more).toBe(false);

      // Verify no overlap between pages
      const page1Ids = page1.data.map((a) => a.id);
      const page2Ids = page2.data.map((a) => a.id);
      const intersection = page1Ids.filter((id) => page2Ids.includes(id));
      expect(intersection).toHaveLength(0);
    });

    test('should return empty list when accessibleIds contains non-existent IDs', async () => {
      // Try with non-existent agent IDs
      const fakeIds = [new mongoose.Types.ObjectId(), new mongoose.Types.ObjectId()];

      const result = await getListAgentsByAccess({
        accessibleIds: fakeIds,
        otherParams: {},
      });

      expect(result.data).toHaveLength(0);
      expect(result.has_more).toBe(false);
    });

    test('should handle undefined accessibleIds as empty array', async () => {
      // When accessibleIds is undefined, it should be treated as empty array
      const result = await getListAgentsByAccess({
        accessibleIds: undefined,
        otherParams: {},
      });

      expect(result.data).toHaveLength(0);
      expect(result.has_more).toBe(false);
    });

    test('should combine accessibleIds with author filter correctly', async () => {
      // Create an agent for User B
      const agentB1 = await createAgent({
        id: `agent_${uuidv4().slice(0, 12)}`,
        name: 'Agent B1',
        description: 'User B agent 1',
        provider: 'openai',
        model: 'gpt-4',
        author: userB,
      });

      // Give User B access to one of User A's agents
      const accessibleIds = [agentA1._id, agentB1._id];

      // Filter by author should further restrict the results
      const result = await getListAgentsByAccess({
        accessibleIds,
        otherParams: { author: userB },
      });

      expect(result.data).toHaveLength(1);
      expect(result.data[0].id).toBe(agentB1.id);
      expect(result.data[0].author).toBe(userB.toString());
    });
  });
});

function createBasicAgent(overrides = {}) {
  const defaults = {
    id: `agent_${uuidv4()}`,
    name: 'Test Agent',
    provider: 'test',
    model: 'test-model',
    author: new mongoose.Types.ObjectId(),
  };
  return createAgent({ ...defaults, ...overrides });
}

function createTestIds() {
  return {
    agentId: `agent_${uuidv4()}`,
    authorId: new mongoose.Types.ObjectId(),
    projectId: new mongoose.Types.ObjectId(),
    fileId: uuidv4(),
  };
}

function createFileOperations(agentId, fileIds, operation = 'add') {
  return fileIds.map((fileId) =>
    operation === 'add'
      ? addAgentResourceFile({ agent_id: agentId, tool_resource: 'test_tool', file_id: fileId })
      : removeAgentResourceFiles({
          agent_id: agentId,
          files: [{ tool_resource: 'test_tool', file_id: fileId }],
        }),
  );
}

function mockFindOneAndUpdateError(errorOnCall = 1) {
  const original = Agent.findOneAndUpdate;
  let callCount = 0;

  Agent.findOneAndUpdate = jest.fn().mockImplementation((...args) => {
    callCount++;
    if (callCount === errorOnCall) {
      throw new Error('Database connection lost');
    }
    return original.apply(Agent, args);
  });

  return () => {
    Agent.findOneAndUpdate = original;
  };
}

function generateVersionTestCases() {
  const projectId1 = new mongoose.Types.ObjectId();
  const projectId2 = new mongoose.Types.ObjectId();

  return [
    {
      name: 'simple field update',
      initial: {
        name: 'Test Agent',
        description: 'Initial description',
      },
      update: { name: 'Updated Name' },
      duplicate: { name: 'Updated Name' },
    },
    {
      name: 'object field update',
      initial: {
        model_parameters: { temperature: 0.7 },
      },
      update: { model_parameters: { temperature: 0.8 } },
      duplicate: { model_parameters: { temperature: 0.8 } },
    },
    {
      name: 'array field update',
      initial: {
        tools: ['tool1', 'tool2'],
      },
      update: { tools: ['tool2', 'tool3'] },
      duplicate: { tools: ['tool2', 'tool3'] },
    },
    {
      name: 'projectIds update',
      initial: {
        projectIds: [projectId1],
      },
      update: { projectIds: [projectId1, projectId2] },
      duplicate: { projectIds: [projectId2, projectId1] },
    },
  ];
}
