/**
 * Tool-result cache keys.
 *
 * Each formula is prefixed with a version tag (`v1`) so a future schema
 * change can invalidate existing entries by bumping the prefix instead of
 * trying to translate them.
 *
 * `workspacePath` is included in workspace-bound formulas so two pieces
 * running on the same orchestrator but different workspaces never share
 * entries — even if their path arguments collide.
 */

const CACHE_KEY_VERSION = 'v1';

function normalizeRange(value: number | undefined): string {
  return value === undefined ? 'all' : String(value);
}

// --- Read ---

export interface ReadCacheKeyArgs {
  workspacePath: string;
  filePath: string;
  offset?: number;
  limit?: number;
  byteOffset?: number;
  byteLength?: number;
}

export function buildReadCacheKey(args: ReadCacheKeyArgs): string {
  return [
    'read',
    CACHE_KEY_VERSION,
    args.workspacePath,
    args.filePath,
    normalizeRange(args.offset),
    normalizeRange(args.limit),
    normalizeRange(args.byteOffset),
    normalizeRange(args.byteLength),
  ].join(':');
}

// --- Grep ---

export interface GrepCacheKeyArgs {
  workspacePath: string;
  pattern: string;
  path?: string;
  glob?: string;
}

export function buildGrepCacheKey(args: GrepCacheKeyArgs): string {
  return [
    'grep',
    CACHE_KEY_VERSION,
    args.workspacePath,
    args.path ?? '.',
    args.glob ?? '*',
    args.pattern,
  ].join(':');
}

// --- Glob ---

export interface GlobCacheKeyArgs {
  workspacePath: string;
  pattern: string;
  path?: string;
}

export function buildGlobCacheKey(args: GlobCacheKeyArgs): string {
  return [
    'glob',
    CACHE_KEY_VERSION,
    args.workspacePath,
    args.path ?? '.',
    args.pattern,
  ].join(':');
}

// --- WebFetch ---

export interface WebFetchCacheKeyArgs {
  url: string;
}

/** Lower-case scheme/host, drop fragments. Bad URLs key on themselves. */
function normalizeUrl(url: string): string {
  try {
    const parsed = new URL(url);
    parsed.hash = '';
    parsed.protocol = parsed.protocol.toLowerCase();
    parsed.hostname = parsed.hostname.toLowerCase();
    return parsed.toString();
  } catch {
    return url;
  }
}

export function buildWebFetchCacheKey(args: WebFetchCacheKeyArgs): string {
  return ['webfetch', CACHE_KEY_VERSION, normalizeUrl(args.url)].join(':');
}

// --- Office (ReadPdf / ReadExcel / ReadDocx / ReadPPTX) ---

export interface OfficeCacheKeyArgs {
  workspacePath: string;
  toolName: string;
  filePath: string;
  /** Optional sheet/page slice descriptor — caller stringifies all params. */
  range?: string;
}

export function buildOfficeCacheKey(args: OfficeCacheKeyArgs): string {
  return [
    'office',
    CACHE_KEY_VERSION,
    args.toolName,
    args.workspacePath,
    args.filePath,
    args.range ?? 'all',
  ].join(':');
}
