import { jsx } from "react/jsx-runtime";
import { useCallback, useState } from "react";
import { render } from "ink";
import { registerGracefulShutdown } from "./host/index.js";
import { enableBracketedPaste, disableBracketedPaste } from "./utils/bracketedPaste.js";
import {
  KeypressProvider,
  MouseProvider,
  ScrollProvider,
  SoundProvider
} from "./contexts/index.js";
import { ErrorBoundary } from "./components/ErrorBoundary.js";
import { AlternateBufferCLI, StaticCLI } from "./components/modes/index.js";
import { useStreaming } from "./hooks/useStreaming.js";
import { getStartupInfo } from "./utils/messageFormatting.js";
const USE_ALTERNATE_BUFFER = false;
function formatCost(c) {
  if (c < 0.01) return `$${c.toFixed(4)}`;
  if (c < 1) return `$${c.toFixed(3)}`;
  return `$${c.toFixed(2)}`;
}
function InkCLIInner({
  agent,
  initialSessionId,
  initialPrompt,
  startupInfo,
  soundService,
  configFilePath,
  initialBypassPermissions = false
}) {
  const [, setSelectionHintShown] = useState(false);
  const { streaming } = useStreaming();
  const handleSelectionAttempt = useCallback(() => {
    setSelectionHintShown(true);
  }, []);
  if (USE_ALTERNATE_BUFFER) {
    return /* @__PURE__ */ jsx(SoundProvider, { soundService, children: /* @__PURE__ */ jsx(ScrollProvider, { onSelectionAttempt: handleSelectionAttempt, children: /* @__PURE__ */ jsx(
      AlternateBufferCLI,
      {
        agent,
        initialSessionId,
        initialPrompt,
        startupInfo,
        onSelectionAttempt: handleSelectionAttempt,
        useStreaming: streaming,
        configFilePath,
        initialBypassPermissions
      }
    ) }) });
  }
  return /* @__PURE__ */ jsx(SoundProvider, { soundService, children: /* @__PURE__ */ jsx(
    StaticCLI,
    {
      agent,
      initialSessionId,
      initialPrompt,
      startupInfo,
      useStreaming: streaming,
      configFilePath,
      initialBypassPermissions
    }
  ) });
}
function InkCLIRefactored({
  agent,
  initialSessionId,
  initialPrompt,
  startupInfo,
  soundService,
  configFilePath,
  initialBypassPermissions = false
}) {
  return /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(KeypressProvider, { children: /* @__PURE__ */ jsx(MouseProvider, { mouseEventsEnabled: USE_ALTERNATE_BUFFER, children: /* @__PURE__ */ jsx(
    InkCLIInner,
    {
      agent,
      initialSessionId,
      initialPrompt,
      startupInfo,
      soundService,
      configFilePath,
      initialBypassPermissions
    }
  ) }) }) });
}
async function startInkCliRefactored(agent, initialSessionId, options = {}) {
  registerGracefulShutdown(() => agent, { inkMode: true });
  enableBracketedPaste();
  const baseStartupInfo = await getStartupInfo(agent, initialSessionId);
  const startupInfo = {
    ...baseStartupInfo,
    updateInfo: options.updateInfo,
    needsAgentSync: options.needsAgentSync
  };
  let globalPreferencesExistFn = () => false;
  let loadGlobalPreferencesFn = null;
  let agentPreferencesExistFn = () => false;
  let loadAgentPreferencesFn = null;
  try {
    const agentManagement = await import("@dexto/agent-management");
    globalPreferencesExistFn = agentManagement.globalPreferencesExist;
    loadGlobalPreferencesFn = agentManagement.loadGlobalPreferences;
    agentPreferencesExistFn = agentManagement.agentPreferencesExist;
    loadAgentPreferencesFn = agentManagement.loadAgentPreferences;
  } catch (error) {
    agent.logger.debug(
      `Preferences module could not be loaded: ${error instanceof Error ? error.message : String(error)}`
    );
  }
  let soundService = null;
  let soundConfig = {
    enabled: true,
    onStartup: false,
    startupSoundFile: void 0,
    onApprovalRequired: true,
    approvalSoundFile: void 0,
    onTaskComplete: true,
    completeSoundFile: void 0
  };
  try {
    const { SoundNotificationService: SoundNotificationServiceImpl } = await import("./utils/soundNotification.js");
    if (globalPreferencesExistFn() && loadGlobalPreferencesFn) {
      try {
        const preferences = await loadGlobalPreferencesFn();
        soundConfig = {
          enabled: preferences.sounds?.enabled ?? soundConfig.enabled,
          onStartup: preferences.sounds?.onStartup ?? soundConfig.onStartup,
          startupSoundFile: preferences.sounds?.startupSoundFile ?? soundConfig.startupSoundFile,
          onApprovalRequired: preferences.sounds?.onApprovalRequired ?? soundConfig.onApprovalRequired,
          approvalSoundFile: preferences.sounds?.approvalSoundFile ?? soundConfig.approvalSoundFile,
          onTaskComplete: preferences.sounds?.onTaskComplete ?? soundConfig.onTaskComplete,
          completeSoundFile: preferences.sounds?.completeSoundFile ?? soundConfig.completeSoundFile
        };
      } catch (error) {
        agent.logger.debug(
          `Sound preferences could not be loaded: ${error instanceof Error ? error.message : String(error)}`
        );
      }
    }
    soundService = new SoundNotificationServiceImpl(soundConfig);
    soundService.playStartupSound();
  } catch (error) {
    agent.logger.debug(
      `Sound initialization failed: ${error instanceof Error ? error.message : String(error)}`
    );
    soundService = null;
  }
  if (agentPreferencesExistFn(agent.config.agentId) && loadAgentPreferencesFn) {
    try {
      const preferences = await loadAgentPreferencesFn(agent.config.agentId);
      agent.setGlobalDisabledTools(preferences.tools?.disabled ?? []);
    } catch (error) {
      agent.logger.debug(
        `Agent tool preferences could not be loaded: ${error instanceof Error ? error.message : String(error)}`
      );
    }
  }
  const { registerExitHandler } = await import("./interactive-commands/exit-handler.js");
  const inkApp = render(
    /* @__PURE__ */ jsx(
      InkCLIRefactored,
      {
        agent,
        initialSessionId,
        initialPrompt: options.initialPrompt,
        startupInfo,
        soundService,
        configFilePath: options.configFilePath ?? null,
        initialBypassPermissions: options.bypassPermissions ?? false
      }
    ),
    {
      exitOnCtrlC: false,
      alternateBuffer: USE_ALTERNATE_BUFFER,
      // Incremental rendering works better with VirtualizedList
      // Static pattern doesn't need it (and may work better without)
      incrementalRendering: USE_ALTERNATE_BUFFER
    }
  );
  registerExitHandler(() => inkApp.unmount());
  await inkApp.waitUntilExit();
  disableBracketedPaste();
  const chalk = (await import("chalk")).default;
  const { getExitStats, clearExitStats } = await import("./interactive-commands/exit-stats.js");
  const exitStats = getExitStats();
  if (exitStats) {
    process.stdout.write("\n".repeat(1));
    process.stdout.write(chalk.bold.cyan("\u{1F4CA} Session Summary") + "\n");
    process.stdout.write(chalk.dim("\u2500".repeat(50)) + "\n");
    if (exitStats.sessionId) {
      process.stdout.write(chalk.gray(`  Session ID:  ${exitStats.sessionId}`) + "\n");
    }
    if (exitStats.duration) {
      process.stdout.write(chalk.gray(`  Duration:    ${exitStats.duration}`) + "\n");
    }
    if (exitStats.messageCount.total > 0) {
      process.stdout.write(
        chalk.gray(
          `  Messages:    ${exitStats.messageCount.total} total (${exitStats.messageCount.user} user, ${exitStats.messageCount.assistant} assistant)`
        ) + "\n"
      );
    }
    if (exitStats.modelStats && exitStats.modelStats.length > 1) {
      process.stdout.write(chalk.gray("\n  Models Used:") + "\n");
      for (const modelStat of exitStats.modelStats) {
        const modelLabel = `${modelStat.model} (${modelStat.messageCount} msgs)`;
        process.stdout.write(chalk.gray(`    \u2022 ${modelLabel}`) + "\n");
        if (exitStats.tokenUsage) {
          const tokens = modelStat.tokenUsage;
          process.stdout.write(
            chalk.gray(
              `      Input tokens:       ${tokens.inputTokens.toLocaleString()}`
            ) + "\n"
          );
          process.stdout.write(
            chalk.gray(
              `      Output tokens:      ${tokens.outputTokens.toLocaleString()}`
            ) + "\n"
          );
          process.stdout.write(
            chalk.gray(
              `      Reasoning tokens:   ${tokens.reasoningTokens.toLocaleString()}`
            ) + "\n"
          );
          process.stdout.write(
            chalk.gray(
              `      Cache read tokens:  ${tokens.cacheReadTokens.toLocaleString()}`
            ) + "\n"
          );
          process.stdout.write(
            chalk.gray(
              `      Cache write tokens: ${tokens.cacheWriteTokens.toLocaleString()}`
            ) + "\n"
          );
          process.stdout.write(
            chalk.gray(
              `      Total tokens:       ${tokens.totalTokens.toLocaleString()}`
            ) + "\n"
          );
          if (modelStat.estimatedCost !== void 0) {
            process.stdout.write(
              chalk.gray(
                `      Cost:               ${formatCost(modelStat.estimatedCost)}`
              ) + "\n"
            );
          }
        }
      }
    }
    if (exitStats.usageNote) {
      process.stdout.write(chalk.gray("\n  Usage:") + "\n");
      process.stdout.write(chalk.gray(`    ${exitStats.usageNote}`) + "\n");
    }
    if (exitStats.tokenUsage) {
      const {
        inputTokens,
        outputTokens,
        reasoningTokens,
        cacheReadTokens,
        cacheWriteTokens,
        totalTokens
      } = exitStats.tokenUsage;
      const totalInputWithCache = inputTokens + cacheReadTokens;
      const cacheSavingsPercent = totalInputWithCache > 0 ? (cacheReadTokens / totalInputWithCache * 100).toFixed(1) : "0.0";
      const tokenSectionLabel = exitStats.modelStats && exitStats.modelStats.length > 1 ? "\n  Total Token Usage:" : "\n  Token Usage:";
      process.stdout.write(chalk.gray(tokenSectionLabel) + "\n");
      process.stdout.write(
        chalk.gray(`    Input tokens:       ${inputTokens.toLocaleString()}`) + "\n"
      );
      process.stdout.write(
        chalk.gray(`    Output tokens:      ${outputTokens.toLocaleString()}`) + "\n"
      );
      process.stdout.write(
        chalk.gray(`    Reasoning tokens:   ${reasoningTokens.toLocaleString()}`) + "\n"
      );
      const cacheReadLabel = cacheReadTokens > 0 ? `${cacheReadTokens.toLocaleString()} (\u{1F4B0} ${cacheSavingsPercent}% savings)` : cacheReadTokens.toLocaleString();
      process.stdout.write(chalk.gray(`    Cache read tokens:  ${cacheReadLabel}`) + "\n");
      process.stdout.write(
        chalk.gray(`    Cache write tokens: ${cacheWriteTokens.toLocaleString()}`) + "\n"
      );
      process.stdout.write(
        chalk.gray(`    Total tokens:       ${totalTokens.toLocaleString()}`) + "\n"
      );
    }
    if (exitStats.estimatedCost !== void 0) {
      process.stdout.write(
        chalk.green(`
  Estimated Cost: ${formatCost(exitStats.estimatedCost)}`) + "\n"
      );
    }
    clearExitStats();
  }
  process.stdout.write(chalk.dim("\u2500".repeat(50)) + "\n");
  process.stdout.write("\n" + chalk.rgb(255, 165, 0)("Exiting Dexto CLI. Goodbye!") + "\n");
}
export {
  InkCLIRefactored,
  startInkCliRefactored
};
