import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, rmSync } from 'fs';
import { join } from 'path';
import { tmpdir } from 'os';
import { MemoryStore } from './store.js';
import { buildAdaptiveMemoryContext, buildRecentMemoryContext } from './adaptive.js';
import type { Message } from '../models/types.js';

describe('adaptive memory context', () => {
  let dir: string;
  let store: MemoryStore;

  beforeEach(() => {
    dir = mkdtempSync(join(tmpdir(), 'flynn-adaptive-memory-test-'));
    store = new MemoryStore({ dir, maxContextTokens: 4000 });

    store.write('user', 'Preferred language: TypeScript', 'replace');
    store.writeCategory('user', 'preferences', [
      'Prefers concise responses and direct code snippets.',
      'Use markdown tables for summaries.',
      'Avoid unnecessary setup details.',
    ].join('\n\n'), 'replace');
    store.writeCategory('global', 'facts', [
      'Project uses pnpm and Vitest.',
      'Release workflow runs lint, test, and build.',
      'Kubernetes cluster is k0s on arm64.',
    ].join('\n\n'), 'replace');
  });

  afterEach(() => {
    rmSync(dir, { recursive: true, force: true });
  });

  it('selects memory snippets relevant to the current message', () => {
    const recentMessages: Message[] = [
      { role: 'user', content: 'Please keep answers concise' },
      { role: 'assistant', content: 'Understood' },
    ];

    const context = buildAdaptiveMemoryContext({
      store,
      userMessage: 'Can you provide a concise summary in markdown table format?',
      recentMessages,
      config: { maxTokens: 200 },
    });

    expect(context).toContain('User Preferences');
    expect(context).toContain('markdown tables');
    expect(context).not.toContain('Kubernetes cluster is k0s on arm64');
  });

  it('respects token budget clipping', () => {
    const context = buildAdaptiveMemoryContext({
      store,
      userMessage: 'Tell me something about this project',
      recentMessages: [],
      config: { maxTokens: 20 },
    });

    expect(context.length).toBeLessThanOrEqual(80);
  });

  it('recent strategy keeps the tail of memory context', () => {
    const recentContext = buildRecentMemoryContext(store, 25);
    const fullContext = store.getContextForPrompt();

    expect(recentContext.length).toBeLessThanOrEqual(100);
    expect(fullContext.endsWith(recentContext)).toBe(true);
  });
});
