'use strict';

/**
 * Fast token estimation utilities for context compaction.
 * Uses chars/4 with a 1.2x safety margin (overestimates slightly — safer than underestimating).
 */

const CHARS_PER_TOKEN = 4;
const SAFETY_MARGIN = 1.2;

/**
 * Estimate token count for a string.
 * @param {string} text
 * @returns {number}
 */
function estimateTokens(text) {
  if (!text) return 0;
  return Math.ceil((text.length / CHARS_PER_TOKEN) * SAFETY_MARGIN);
}

/**
 * Estimate total tokens across an array of messages.
 * Handles both string content and structured content blocks (tool_use, tool_result, etc.).
 * @param {Array} messages - Array of { role, content } objects
 * @returns {number}
 */
function estimateMessagesTokens(messages) {
  if (!messages || !Array.isArray(messages)) return 0;
  let total = 0;
  for (const msg of messages) {
    if (!msg) continue;
    if (typeof msg.content === 'string') {
      total += estimateTokens(msg.content);
    } else if (Array.isArray(msg.content)) {
      // Structured content: tool_use blocks, tool_result blocks, text blocks, etc.
      for (const block of msg.content) {
        if (block.type === 'text') {
          total += estimateTokens(block.text || '');
        } else if (block.type === 'tool_use') {
          total += estimateTokens(JSON.stringify(block.input || {}));
          total += estimateTokens(block.name || '');
        } else if (block.type === 'tool_result') {
          total += estimateTokens(typeof block.content === 'string' ? block.content : JSON.stringify(block.content || ''));
        } else {
          total += estimateTokens(JSON.stringify(block));
        }
      }
    }
    // Add small overhead per message for role, etc.
    total += 4;
  }
  return total;
}

module.exports = { estimateTokens, estimateMessagesTokens };
