/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import { StreamingState } from '../ui/types.js';

export interface TerminalTitleOptions {
  streamingState: StreamingState;
  thoughtSubject?: string;
  isConfirming: boolean;
  isSilentWorking: boolean;
  folderName: string;
  showThoughts: boolean;
  useDynamicTitle: boolean;
}

function truncate(text: string, maxLen: number): string {
  if (text.length <= maxLen) {
    return text;
  }
  return text.substring(0, maxLen - 1) + '…';
}

/**
 * Computes the dynamic terminal window title based on the current CLI state.
 *
 * @param options - The current state of the CLI and environment context
 * @returns A formatted string padded to 80 characters for the terminal title
 */
export function computeTerminalTitle({
  streamingState,
  thoughtSubject,
  isConfirming,
  isSilentWorking,
  folderName,
  showThoughts,
  useDynamicTitle,
}: TerminalTitleOptions): string {
  const MAX_LEN = 80;

  // Use CLI_TITLE env var if available, otherwise use the provided folder name
  let displayContext = process.env['CLI_TITLE'] || folderName;

  if (!useDynamicTitle) {
    const base = 'Gemini CLI ';
    // Max context length is 80 - base.length - 2 (for brackets)
    const maxContextLen = MAX_LEN - base.length - 2;
    displayContext = truncate(displayContext, maxContextLen);
    return `${base}(${displayContext})`.padEnd(MAX_LEN, ' ');
  }

  // Pre-calculate suffix but keep it flexible
  const getSuffix = (context: string) => ` (${context})`;

  let title;
  if (
    isConfirming ||
    streamingState === StreamingState.WaitingForConfirmation
  ) {
    const base = '✋  Action Required';
    // Max context length is 80 - base.length - 3 (for ' (' and ')')
    const maxContextLen = MAX_LEN - base.length - 3;
    const context = truncate(displayContext, maxContextLen);
    title = `${base}${getSuffix(context)}`;
  } else if (isSilentWorking) {
    const base = '⏲  Working…';
    // Max context length is 80 - base.length - 3 (for ' (' and ')')
    const maxContextLen = MAX_LEN - base.length - 3;
    const context = truncate(displayContext, maxContextLen);
    title = `${base}${getSuffix(context)}`;
  } else if (streamingState === StreamingState.Idle) {
    const base = '◇  Ready';
    // Max context length is 80 - base.length - 3 (for ' (' and ')')
    const maxContextLen = MAX_LEN - base.length - 3;
    const context = truncate(displayContext, maxContextLen);
    title = `${base}${getSuffix(context)}`;
  } else {
    // Active/Working state
    const cleanSubject =
      showThoughts && thoughtSubject?.replace(/[\r\n]+/g, ' ').trim();

    // If we have a thought subject and it's too long to fit with the suffix,
    // we drop the suffix to maximize space for the thought.
    // Otherwise, we keep the suffix.
    const suffix = getSuffix(displayContext);
    const suffixLen = suffix.length;
    const canFitThoughtWithSuffix = cleanSubject
      ? cleanSubject.length + suffixLen + 3 <= MAX_LEN
      : true;

    let activeSuffix = '';
    let maxStatusLen = MAX_LEN - 3; // Subtract icon prefix "✦  " (3 chars)

    if (!cleanSubject || canFitThoughtWithSuffix) {
      activeSuffix = suffix;
      maxStatusLen -= activeSuffix.length;
    }

    const displayStatus = cleanSubject
      ? truncate(cleanSubject, maxStatusLen)
      : 'Working…';

    title = `✦  ${displayStatus}${activeSuffix}`;
  }

  // Remove control characters that could cause issues in terminal titles
  // eslint-disable-next-line no-control-regex
  const safeTitle = title.replace(/[\x00-\x1F\x7F]/g, '');

  // Pad the title to a fixed width to prevent taskbar icon resizing/jitter.
  // We also slice it to ensure it NEVER exceeds MAX_LEN.
  return safeTitle.padEnd(MAX_LEN, ' ').substring(0, MAX_LEN);
}
