import type { ReactElement } from 'react';
import { CommandsPanel } from '@/spa/chat/commands-panel';
import { Composer } from '@/spa/chat/composer';
import { MessageTranscript } from '@/spa/chat/message-transcript';
import { asFiniteNumberOrNull, asString } from '@/spa/chat/runtime-guards';
import { SessionPanel } from '@/spa/chat/session-panel';
import { ToolCallList } from '@/spa/chat/tool-call-list';
import { useChatConnection } from '@/spa/chat/use-chat-connection';
import { useHarnessSelection } from '@/spa/chat/use-harness-selection';

/** Renders a real value normally, but an honest "unavailable" label instead
 * of a fabricated `0` for a missing/malformed count — a real `0 tokens` and
 * an unknown token count must never look the same. */
function formatTokens(value: unknown): string {
  const tokens = asFiniteNumberOrNull(value);
  return tokens === null ? 'tokens unavailable' : `${tokens} tokens`;
}

/** Same honesty guarantee as `formatTokens`, for cost. */
function formatCost(value: unknown): string {
  const cost = asFiniteNumberOrNull(value);
  return cost === null ? 'cost unavailable' : `$${cost.toFixed(4)}`;
}

export function ChatPage(): ReactElement {
  const { state, actions } = useChatConnection();
  const harness = useHarnessSelection();
  const hasConversation = state.conversationId !== null;

  return (
    <div className="flex h-[calc(100vh-3.5rem)] min-h-0 flex-col overflow-hidden md:h-screen">
      <header className="border-b px-4 py-3">
        <h1 className="text-lg font-semibold">Chat</h1>
      </header>

      {state.systemReload ? (
        <div role="status" className="border-b px-4 py-2 text-sm">
          {asString(state.systemReload.message)}
        </div>
      ) : null}

      {state.error ? (
        <div role="alert" className="border-b px-4 py-2 text-sm">
          {asString(state.error)}
        </div>
      ) : null}

      {state.ack ? (
        <div role="status" className="border-b px-4 py-1 text-xs opacity-70">
          Message accepted · conversation {asString(state.ack.conversationId, 'unknown')} · id{' '}
          {asString(state.ack.messageId, 'unknown')}
        </div>
      ) : null}

      <SessionPanel sessionInfo={state.sessionInfo} onSetThinking={actions.setThinking} />

      <MessageTranscript messages={state.messages} streaming={state.streaming} text={state.text} />

      {state.thinking ? (
        <section aria-label="Thinking" className="px-4 pb-2 text-xs italic opacity-80">
          {state.thinking}
        </section>
      ) : null}

      <ToolCallList tools={state.tools} />

      {state.usage ? (
        <div aria-label="Usage" className="px-4 pb-2 text-xs opacity-80">
          {formatTokens(state.usage.tokens?.total)} · {formatCost(state.usage.cost)} ·{' '}
          {asString(state.usage.provider, 'unknown')}/{asString(state.usage.modelId, 'unknown')}
        </div>
      ) : null}

      <CommandsPanel
        manifest={state.manifest}
        results={state.commandResults}
        approval={state.approval}
        pendingApproval={state.pendingApproval}
        hasConversation={hasConversation}
        onExecute={actions.executeCommand}
        onApprove={actions.approveCommand}
        onRunApproved={actions.runApprovedCommand}
      />

      <Composer
        onSend={actions.sendMessage}
        onStop={actions.abort}
        streaming={state.streaming}
        sending={state.sending}
        hasConversation={hasConversation}
        harness={harness}
      />
    </div>
  );
}
