<template>
  <div class="input-area compact-input-area">
    <div class="stadium-input-wrapper" ref="stadiumShellOuter">
      <div
        class="stadium-shell"
        ref="compactInputShell"
        :class="{
          'is-multiline': inputIsMultiline,
          'is-focused': inputIsFocused,
          'has-text': (inputMessage || '').trim().length > 0
        }"
      >
        <input type="file" ref="fileUploadInput" class="file-input-hidden" @change="onFileChange" />
        <button
          type="button"
          class="stadium-btn add-btn"
          @click.stop="$emit('toggle-quick-menu')"
          :disabled="!isConnected || streamingMessage || inputLocked"
        >
          +
        </button>
        <textarea
          ref="stadiumInput"
          class="stadium-input"
          rows="1"
          :value="inputMessage"
          :disabled="!isConnected || streamingMessage || inputLocked"
          placeholder="输入消息... (Ctrl+Enter 发送)"
          @input="onInput"
          @focus="$emit('input-focus')"
          @blur="$emit('input-blur')"
          @keydown.enter.ctrl.prevent="$emit('send-message')"
        ></textarea>
        <button
          type="button"
          class="stadium-btn send-btn"
          @click="$emit('send-or-stop')"
          :disabled="
            !isConnected ||
            (inputLocked && !streamingMessage) ||
            (!(inputMessage || '').trim() && !streamingMessage)
          "
        >
          <span v-if="streamingMessage" class="stop-icon"></span>
          <span v-else class="send-icon"></span>
        </button>
      </div>
      <QuickMenu
        :open="quickMenuOpen"
        :is-connected="isConnected"
        :uploading="uploading"
        :streaming-message="streamingMessage"
        :thinking-mode="thinkingMode"
        :run-mode="runMode"
        :tool-menu-open="toolMenuOpen"
        :tool-settings="toolSettings"
        :tool-settings-loading="toolSettingsLoading"
        :settings-open="settingsOpen"
        :mode-menu-open="modeMenuOpen"
        :compressing="compressing"
        :current-conversation-id="currentConversationId"
        :icon-style="iconStyle"
        :tool-category-icon="toolCategoryIcon"
        @quick-upload="triggerQuickUpload"
        @toggle-tool-menu="$emit('toggle-tool-menu')"
        @toggle-settings="$emit('toggle-settings')"
        @toggle-mode-menu="$emit('toggle-mode-menu')"
        @select-run-mode="(mode) => $emit('select-run-mode', mode)"
        @update-tool-category="(id, enabled) => $emit('update-tool-category', id, enabled)"
        @realtime-terminal="$emit('realtime-terminal')"
        @toggle-focus-panel="$emit('toggle-focus-panel')"
        @toggle-token-panel="$emit('toggle-token-panel')"
        @compress-conversation="$emit('compress-conversation')"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref, watch, nextTick } from 'vue';
import QuickMenu from '@/components/input/QuickMenu.vue';
import { useInputStore } from '@/stores/input';

defineOptions({ name: 'InputComposer' });

const emit = defineEmits([
  'update:input-message',
  'input-change',
  'input-focus',
  'input-blur',
  'toggle-quick-menu',
  'send-message',
  'send-or-stop',
  'quick-upload',
  'toggle-tool-menu',
  'toggle-mode-menu',
  'select-run-mode',
  'toggle-settings',
  'update-tool-category',
  'realtime-terminal',
  'toggle-focus-panel',
  'toggle-token-panel',
  'compress-conversation',
  'file-selected'
]);

const props = defineProps<{
  inputMessage: string;
  inputIsMultiline: boolean;
  inputIsFocused: boolean;
  isConnected: boolean;
  streamingMessage: boolean;
  inputLocked: boolean;
  uploading: boolean;
  thinkingMode: boolean;
  runMode: 'fast' | 'thinking' | 'deep';
  quickMenuOpen: boolean;
  toolMenuOpen: boolean;
  modeMenuOpen: boolean;
  toolSettings: Array<{ id: string; label: string; enabled: boolean }>;
  toolSettingsLoading: boolean;
  settingsOpen: boolean;
  compressing: boolean;
  currentConversationId: string | null;
  iconStyle: (key: string) => Record<string, string>;
  toolCategoryIcon: (categoryId: string) => string;
}>();

const inputStore = useInputStore();
const stadiumShellOuter = ref<HTMLElement | null>(null);
const compactInputShell = ref<HTMLElement | null>(null);
const stadiumInput = ref<HTMLTextAreaElement | null>(null);
const fileUploadInput = ref<HTMLInputElement | null>(null);

const applyLineMetrics = (lines: number, multiline: boolean) => {
  inputStore.setInputLineCount(lines);
  inputStore.setInputMultiline(multiline);
};

const adjustTextareaSize = () => {
  const textarea = stadiumInput.value;
  if (!textarea) {
    return;
  }
  const previousHeight = textarea.offsetHeight;
  textarea.style.height = 'auto';
  const computedStyle = window.getComputedStyle(textarea);
  const lineHeight = parseFloat(computedStyle.lineHeight || '20') || 20;
  const maxHeight = lineHeight * 6;
  const targetHeight = Math.min(textarea.scrollHeight, maxHeight);
  const lines = Math.max(1, Math.round(targetHeight / lineHeight));
  const multiline = targetHeight > lineHeight * 1.4;
  applyLineMetrics(lines, multiline);

  if (Math.abs(targetHeight - previousHeight) <= 0.5) {
    textarea.style.height = `${targetHeight}px`;
    return;
  }
  textarea.style.height = `${previousHeight}px`;
  void textarea.offsetHeight;
  requestAnimationFrame(() => {
    textarea.style.height = `${targetHeight}px`;
  });
};

const onInput = (event: Event) => {
  const target = event.target as HTMLTextAreaElement;
  emit('update:input-message', target.value);
  emit('input-change');
  adjustTextareaSize();
};

const onFileChange = (event: Event) => {
  const target = event.target as HTMLInputElement;
  emit('file-selected', target?.files || null);
  if (target) {
    target.value = '';
  }
};

const triggerQuickUpload = () => {
  if (!props.isConnected || props.uploading) {
    return;
  }
  emit('quick-upload');
};

defineExpose({
  stadiumShellOuter,
  compactInputShell,
  stadiumInput,
  fileUploadInput
});

watch(
  () => props.inputMessage,
  async () => {
    await nextTick();
    adjustTextareaSize();
  }
);

onMounted(() => {
  adjustTextareaSize();
});
</script>
