import { describe, it, expect } from 'vitest';
import {
  buildWakeUpLayers,
  truncateToTokenBudget,
  estimateTokens,
  WAKEUP_PRESETS,
} from '../wakeup.js';

describe('estimateTokens', () => {
  it('estimates ~4 chars per token', () => {
    expect(estimateTokens('abcd')).toBe(1);
    expect(estimateTokens('abcdefgh')).toBe(2);
  });

  it('returns 0 for empty string', () => {
    expect(estimateTokens('')).toBe(0);
  });
});

describe('truncateToTokenBudget', () => {
  it('returns unchanged text if within budget', () => {
    expect(truncateToTokenBudget('short', 100)).toBe('short');
  });

  it('truncates long text with ellipsis', () => {
    const longText = 'a'.repeat(1000);
    const result = truncateToTokenBudget(longText, 10); // 40 chars max
    expect(result.length).toBeLessThanOrEqual(43); // 40 + '...'
    expect(result.endsWith('...')).toBe(true);
  });

  it('returns empty string for empty input', () => {
    expect(truncateToTokenBudget('', 100)).toBe('');
  });
});

describe('buildWakeUpLayers', () => {
  const config = WAKEUP_PRESETS.notelett; // 600 total, 50/150/400

  it('assembles all three layers', () => {
    const result = buildWakeUpLayers(
      'Project: NoteLett',
      'Key fact: Uses Cosmos DB',
      'Related: User asked about search',
      config
    );
    expect(result.text).toContain('[Identity]');
    expect(result.text).toContain('[Critical Facts]');
    expect(result.text).toContain('[Relevant Memories]');
    expect(result.layers).toHaveLength(3);
  });

  it('handles empty L0', () => {
    const result = buildWakeUpLayers('', 'facts', 'memories', config);
    expect(result.layers.find(l => l.label === 'L0:identity')).toBeUndefined();
    expect(result.layers).toHaveLength(2);
  });

  it('handles all empty layers gracefully', () => {
    const result = buildWakeUpLayers('', '', '', config);
    expect(result.text).toBe('');
    expect(result.layers).toHaveLength(0);
    expect(result.truncated).toBe(false);
  });

  it('marks truncated when content exceeds budget', () => {
    const longL2 = 'x '.repeat(5000);
    const result = buildWakeUpLayers('id', 'fact', longL2, config);
    expect(result.truncated).toBe(true);
  });

  it('respects total budget', () => {
    const result = buildWakeUpLayers(
      'identity context here',
      'critical facts here',
      'semantic memories here',
      config
    );
    const tokens = estimateTokens(result.text);
    expect(tokens).toBeLessThanOrEqual(config.totalBudget + 10); // small margin for headers
  });
});

describe('WAKEUP_PRESETS', () => {
  it('has notelett preset with 600 budget', () => {
    expect(WAKEUP_PRESETS.notelett.totalBudget).toBe(600);
  });

  it('has mindlyst preset with 800 budget', () => {
    expect(WAKEUP_PRESETS.mindlyst.totalBudget).toBe(800);
  });

  it('has coding preset with 800 budget', () => {
    expect(WAKEUP_PRESETS.coding.totalBudget).toBe(800);
  });
});
