<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" />
        <div class="input-stack">
          <div v-if="selectedImages && selectedImages.length" class="image-inline-row">
            <span class="image-name" v-for="img in selectedImages" :key="img">
              {{ formatImageName(img) }}
              <button type="button" class="image-remove-btn" @click.stop="$emit('remove-image', img)">×</button>
            </span>
          </div>
          <div v-if="selectedVideos && selectedVideos.length" class="image-inline-row video-inline-row">
            <span class="image-name" v-for="video in selectedVideos" :key="video">
              {{ formatImageName(video) }}
              <button type="button" class="image-remove-btn" @click.stop="$emit('remove-video', video)">×</button>
            </span>
          </div>
          <div class="input-row">
            <button
              type="button"
              class="stadium-btn add-btn"
              @click.stop="$emit('toggle-quick-menu')"
              :disabled="!isConnected"
            >
              +
            </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() && (!selectedImages?.length && !selectedVideos?.length)) && !streamingMessage)
              "
            >
              <span v-if="streamingMessage" class="stop-icon"></span>
              <span v-else class="send-icon"></span>
            </button>
          </div>
        </div>
      </div>
      <QuickMenu
        :open="quickMenuOpen"
        :is-connected="isConnected"
        :uploading="uploading"
        :streaming-message="streamingMessage"
        :thinking-mode="thinkingMode"
        :run-mode="runMode"
        :model-menu-open="modelMenuOpen"
        :model-options="modelOptions"
        :current-model-key="currentModelKey"
        :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"
        :block-upload="blockUpload"
        :block-tool-toggle="blockToolToggle"
        :block-realtime-terminal="blockRealtimeTerminal"
        :block-focus-panel="blockFocusPanel"
        :block-token-panel="blockTokenPanel"
        :block-compress-conversation="blockCompressConversation"
        :block-conversation-review="blockConversationReview"
        @quick-upload="triggerQuickUpload"
        @pick-images="$emit('pick-images')"
        @pick-video="$emit('pick-video')"
        @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)"
        @toggle-model-menu="$emit('toggle-model-menu')"
        @select-model="(key) => $emit('select-model', key)"
        @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')"
        @open-review="$emit('open-review')"
      />
    </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',
  'pick-images',
  'pick-video',
  'toggle-tool-menu',
  'toggle-mode-menu',
  'toggle-model-menu',
  'select-run-mode',
  'select-model',
  'toggle-settings',
  'update-tool-category',
  'realtime-terminal',
  'toggle-focus-panel',
  'toggle-token-panel',
  'compress-conversation',
  'file-selected',
  'remove-image',
  'remove-video',
  'open-review'
]);

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;
  modelMenuOpen: 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;
  modelOptions: Array<{ key: string; label: string; description: string; disabled?: boolean }>;
  currentModelKey: string;
  selectedImages?: string[];
  selectedVideos?: string[];
  blockUpload?: boolean;
  blockToolToggle?: boolean;
  blockRealtimeTerminal?: boolean;
  blockFocusPanel?: boolean;
  blockTokenPanel?: boolean;
  blockCompressConversation?: boolean;
  blockConversationReview?: boolean;
}>();

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 formatImageName = (path: string): string => {
  if (!path) return '';
  const parts = path.split(/[/\\]/);
  return parts[parts.length - 1] || path;
};

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>

<style scoped>
.image-inline-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 4px 10px 2px;
  font-size: 12px;
  color: var(--text-secondary, #7f8792);
  line-height: 1.4;
}
.image-name {
  white-space: nowrap;
}
</style>
