import { stdout } from 'node:process';
import readline from 'node:readline';

// src/platform/ui/status.ts
var ANSI = {
  bold: "\x1B[1m",
  cyan: "\x1B[36m",
  dim: "\x1B[2m",
  red: "\x1B[31m",
  reset: "\x1B[0m"};
var ANSI_PATTERN = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
var COMBINING_MARK_PATTERN = /\p{Mark}/u;
var GRAPHEME_SEGMENTER = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter("ko", { granularity: "grapheme" }) : null;
function colorize(text, color) {
  return `${color}${text}${ANSI.reset}`;
}
function segmentGraphemes(value) {
  if (!GRAPHEME_SEGMENTER) {
    return [...value];
  }
  return [...GRAPHEME_SEGMENTER.segment(value)].map(({ segment }) => segment);
}
function getGraphemeWidth(grapheme) {
  let width = 0;
  for (const character of grapheme) {
    const codePoint = character.codePointAt(0);
    if (!codePoint || COMBINING_MARK_PATTERN.test(character) || codePoint === 8205) {
      continue;
    }
    if (codePoint >= 65024 && codePoint <= 65039 || codePoint >= 917760 && codePoint <= 917999) {
      continue;
    }
    if (isWideCodePoint(codePoint) || isEmojiCodePoint(codePoint)) {
      width = Math.max(width, 2);
      continue;
    }
    width = Math.max(width, 1);
  }
  return width;
}
function tokenizePlainText(value) {
  return segmentGraphemes(value).map((segment) => ({
    value: segment,
    visibleWidth: getGraphemeWidth(segment)
  }));
}
function tokenizeVisibleText(value) {
  const tokens = [];
  let lastIndex = 0;
  for (const match of value.matchAll(ANSI_PATTERN)) {
    const index = match.index ?? 0;
    if (index > lastIndex) {
      tokens.push(...tokenizePlainText(value.slice(lastIndex, index)));
    }
    tokens.push({
      value: match[0],
      visibleWidth: 0
    });
    lastIndex = index + match[0].length;
  }
  if (lastIndex < value.length) {
    tokens.push(...tokenizePlainText(value.slice(lastIndex)));
  }
  return tokens;
}
function isWideCodePoint(codePoint) {
  return codePoint >= 4352 && (codePoint <= 4447 || codePoint === 9001 || codePoint === 9002 || codePoint >= 11904 && codePoint <= 12871 && codePoint !== 12351 || codePoint >= 12880 && codePoint <= 19903 || codePoint >= 19968 && codePoint <= 42182 || codePoint >= 43360 && codePoint <= 43388 || codePoint >= 44032 && codePoint <= 55203 || codePoint >= 63744 && codePoint <= 64255 || codePoint >= 65040 && codePoint <= 65049 || codePoint >= 65072 && codePoint <= 65131 || codePoint >= 65281 && codePoint <= 65376 || codePoint >= 65504 && codePoint <= 65510 || codePoint >= 127488 && codePoint <= 127569 || codePoint >= 131072 && codePoint <= 262141);
}
function isEmojiCodePoint(codePoint) {
  return codePoint >= 127462 && codePoint <= 127487 || codePoint >= 127744 && codePoint <= 129791 || codePoint >= 9728 && codePoint <= 10175;
}
function visibleLength(value) {
  return tokenizeVisibleText(value).reduce((total, token) => total + token.visibleWidth, 0);
}
function getTerminalColumns() {
  return Math.max(stdout.columns || 100, 4);
}
function wrapPlainText(value, firstLineWidth, continuationLineWidth) {
  const renderedLines = [];
  const safeFirstLineWidth = Math.max(firstLineWidth, 1);
  const safeContinuationLineWidth = Math.max(continuationLineWidth, 1);
  const normalizedValue = value.replace(/\r\n?/g, "\n");
  const pushWrappedLine = (line) => {
    if (line.length === 0) {
      renderedLines.push("");
      return;
    }
    let currentLine = "";
    let currentWidth = 0;
    let currentLineWidth = renderedLines.length === 0 ? safeFirstLineWidth : safeContinuationLineWidth;
    for (const segment of segmentGraphemes(line)) {
      const segmentWidth = Math.max(getGraphemeWidth(segment), 1);
      if (currentLine && currentWidth + segmentWidth > currentLineWidth) {
        renderedLines.push(currentLine);
        currentLine = "";
        currentWidth = 0;
        currentLineWidth = safeContinuationLineWidth;
      }
      currentLine += segment;
      currentWidth += segmentWidth;
    }
    renderedLines.push(currentLine);
  };
  normalizedValue.split("\n").forEach(pushWrappedLine);
  return renderedLines.length > 0 ? renderedLines : [""];
}
function buildPromptRenderLayout(promptLabel, buffer, placeholder) {
  const columns = getTerminalColumns();
  const promptLabelWidth = visibleLength(promptLabel);
  const continuationIndentWidth = Math.min(promptLabelWidth, Math.max(columns - 1, 0));
  const continuationIndent = " ".repeat(continuationIndentWidth);
  const firstLineWidth = Math.max(columns - promptLabelWidth, 1);
  const continuationLineWidth = Math.max(columns - continuationIndentWidth, 1);
  const hasBuffer = buffer.length > 0;
  const contentLines = hasBuffer ? wrapPlainText(buffer, firstLineWidth, continuationLineWidth) : wrapPlainText("", firstLineWidth, continuationLineWidth);
  const cursorLines = hasBuffer ? contentLines : [""];
  const renderedPromptLines = contentLines.map((line, index) => {
    const linePrefix = index === 0 ? promptLabel : continuationIndent;
    return `${linePrefix}${hasBuffer ? line : colorize(line, ANSI.dim)}`;
  });
  const activeCursorLine = cursorLines.at(-1) || "";
  const activeCursorLinePrefixWidth = cursorLines.length <= 1 ? promptLabelWidth : continuationIndentWidth;
  return {
    cursorColumn: activeCursorLinePrefixWidth + visibleLength(activeCursorLine),
    cursorRowOffset: Math.max(cursorLines.length - 1, 0),
    lines: renderedPromptLines,
    totalLines: renderedPromptLines.length
  };
}

// src/platform/ui/status.ts
var STATUS_FRAMES = ["-", "\\", "|", "/"];
function formatStatusPrefix(title) {
  return `${colorize(`[${title}]`, `${ANSI.bold}${ANSI.cyan}`)}`;
}
function formatElapsed(startedAt) {
  return `${Math.max(0, Math.floor((Date.now() - startedAt) / 1e3))}s`;
}
function buildStatusRenderLayout(prefix, body) {
  return buildPromptRenderLayout(`${prefix} `, body);
}
function clearRenderedStatus(previousState) {
  if (previousState?.totalLines && previousState.totalLines > 1) {
    readline.moveCursor(stdout, 0, -(previousState.totalLines - 1));
  }
  readline.cursorTo(stdout, 0);
  readline.clearScreenDown(stdout);
}
function renderStatusLayout(layout, previousState) {
  clearRenderedStatus(previousState);
  stdout.write(layout.lines.join("\n"));
  return {
    totalLines: layout.totalLines
  };
}
function createSessionActionStatus(title) {
  const prefix = formatStatusPrefix(title);
  const print = (message) => {
    console.log(`${prefix} ${message}`);
  };
  return {
    fail(message) {
      print(colorize(message, ANSI.red));
    },
    step(message) {
      print(message);
    },
    async track(message, task) {
      if (!stdout.isTTY) {
        print(`${message}...`);
        return task();
      }
      const startedAt = Date.now();
      let frameIndex = 0;
      let renderState;
      const render = () => {
        const frame = STATUS_FRAMES[frameIndex % STATUS_FRAMES.length];
        frameIndex += 1;
        renderState = renderStatusLayout(buildStatusRenderLayout(`${prefix} ${frame}`, `${message} (${formatElapsed(startedAt)})`), renderState);
      };
      render();
      const timer = setInterval(render, 120);
      try {
        const result = await task();
        clearInterval(timer);
        renderState = renderStatusLayout(
          buildStatusRenderLayout(`${prefix} done`, `${message} (${formatElapsed(startedAt)})`),
          renderState
        );
        stdout.write("\n");
        return result;
      } catch (error) {
        clearInterval(timer);
        renderState = renderStatusLayout(
          buildStatusRenderLayout(`${prefix} fail`, `${message} (${formatElapsed(startedAt)})`),
          renderState
        );
        stdout.write("\n");
        throw error;
      }
    }
  };
}

export { createSessionActionStatus };
