<script lang="ts" module>
  // One tool call rendered as a compact, progressive line — the Claude-Code
  // signature for the inline trace. Collapsed: state icon + humanized label +
  // a one-line RESULT summary on completion (or a "live" tag while a `run`
  // streams). Expanded (click): raw args/result/error in opaque <pre> blocks.
  // Border-driven, square, no rounded/shadow (cyberspace system).
</script>

<script lang="ts">
  import { Check, ChevronRight, Loader2, X } from '@lucide/svelte'
  import type { ToolCallResult } from '$lib/types'
  import { toolActivityLabel, toolResultSummary } from '$lib/stores/activity'
  let { tool }: { tool: ToolCallResult } = $props()
  let expanded = $state(false)
  let liveEl = $state<HTMLPreElement | null>(null)

  const status = $derived(tool.type === 'tool_use' ? 'running' : tool.error ? 'error' : 'done')
  const label = $derived(toolActivityLabel(tool))
  const summary = $derived(toolResultSummary(tool))
  // Tool calls start COLLAPSED — the operator expands them on demand. The
  // live `run` output is shown in a separate pinned-tail mini pane below the
  // collapsed row (not by auto-opening the whole detail), so the line stays
  // compact while the command streams. Previously `open` auto-expanded on
  // liveOutput and then collapsed when it cleared — the "start open, then
  // collapse" behavior the operator found confusing.
  const open = $derived(expanded)
  $effect(() => {
    if (tool.liveOutput && liveEl) liveEl.scrollTop = liveEl.scrollHeight
  })

  const hasDetail = $derived(
    !!tool.args || (tool.result !== undefined && tool.result !== null) || !!tool.error
  )
  function pretty(v: unknown): string {
    if (typeof v === 'string') {
      try {
        return JSON.stringify(JSON.parse(v), null, 2)
      } catch {
        return v
      }
    }
    try {
      return JSON.stringify(v, null, 2)
    } catch {
      return String(v)
    }
  }
</script>

<div class="tool-line">
  <button
    class="row"
    onclick={() => (expanded = !expanded)}
    aria-expanded={open}
    disabled={!hasDetail && !tool.liveOutput}
  >
    <span class="icon {status}" aria-hidden="true">
      {#if status === 'running'}
        <Loader2 class="size-3 animate-spin" />
      {:else if status === 'error'}
        <X class="size-3" />
      {:else}
        <Check class="size-3" />
      {/if}
    </span>
    <span class="text min-w-0 flex-1">
      <span class="label {status === 'done' ? 'done-text' : ''}">{label}</span>
    </span>
    {#if status === 'running' && tool.liveOutput}
      <span class="live-tag"><Loader2 class="size-2.5 animate-spin" /> live</span>
    {:else if status === 'done' && summary}
      <span class="summary">{summary}</span>
    {:else if status === 'error'}
      <span class="summary err">error</span>
    {/if}
    {#if hasDetail || tool.liveOutput}
      <ChevronRight class="chev size-3 {open ? 'open' : ''}" />
    {/if}
  </button>

  {#if tool.liveOutput}
    <!-- Live `run` output — pinned-tail mini pane, always visible while the
         command streams. Separate from the expand/collapse state so the tool
         line itself stays collapsed. -->
    <div class="live-output">
      <pre bind:this={liveEl} class="live">{tool.liveOutput}</pre>
    </div>
  {/if}

  {#if open}
    <div class="detail">
      {#if tool.args}
        <div class="khead">Args</div>
        <pre>{pretty(tool.args)}</pre>
      {/if}
      {#if tool.result !== undefined && tool.result !== null}
        <div class="khead">Result</div>
        <pre class={status === 'error' ? 'err' : ''}>{pretty(tool.result)}</pre>
      {/if}
      {#if tool.error}
        <div class="khead err">Error</div>
        <pre class="err">{tool.error}</pre>
      {/if}
    </div>
  {/if}
</div>

<style>
  .tool-line {
    border-left: 1px solid var(--border);
    padding-left: 0.5rem;
    animation: tool-line-in 0.15s ease-out;
  }
  @keyframes tool-line-in {
    from {
      opacity: 0;
      transform: translateY(-2px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .tool-line {
      animation: none;
    }
  }
  .row {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    width: 100%;
    padding: 0.2rem 0;
    text-align: left;
    background: transparent;
    border: none;
    cursor: pointer;
  }
  .row:disabled {
    cursor: default;
  }
  .row:not(:disabled):hover .label {
    color: var(--foreground);
  }
  .icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 0.75rem;
    flex-shrink: 0;
  }
  .icon.running {
    color: var(--primary);
  }
  .icon.error {
    color: var(--destructive);
  }
  .icon.done {
    color: var(--muted-foreground);
  }
  .label {
    font-size: 12px;
    color: var(--foreground);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .label.done-text {
    color: var(--muted-foreground);
  }
  .text {
    display: flex;
    align-items: baseline;
    gap: 0.25rem;
  }
  .summary {
    flex-shrink: 0;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--muted-foreground);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 45%;
  }
  .summary.err {
    color: var(--destructive);
  }
  .live-tag {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--primary);
  }
  .chev {
    flex-shrink: 0;
    color: var(--muted-foreground);
    opacity: 0.6;
    transition: transform 0.12s;
  }
  .chev.open {
    transform: rotate(90deg);
  }
  .detail {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.25rem 0 0.4rem 1.25rem;
  }
  .live-output {
    padding: 0.1rem 0 0.3rem 1.25rem;
  }
  .live-output :global(pre.live) {
    max-height: 8rem;
  }
  .khead {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 9px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted-foreground);
  }
  .khead.err {
    color: var(--destructive);
  }
  .tool-line :global(pre) {
    margin: 0;
    max-height: 12rem;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-word;
    background: var(--muted);
    border: 1px solid var(--border);
    padding: 0.4rem 0.5rem;
    font-family: var(--font-mono);
    font-size: 11px;
    line-height: 1.4;
    color: var(--foreground);
  }
  .tool-line :global(pre.err) {
    color: var(--destructive);
    border-color: color-mix(in oklab, var(--destructive) 40%, var(--border));
    background: color-mix(in oklab, var(--destructive) 6%, var(--muted));
  }
  @media (prefers-reduced-motion: reduce) {
    .chev {
      transition: none;
    }
  }
</style>
