<template>
  <aside class="conversation-sidebar" :class="{ collapsed, 'monitor-mode': monitorModeActive }">
    <div class="conversation-sidebar-inner">
      <div class="conversation-primary-actions">
        <button
          type="button"
          class="sidebar-nav-row conversation-menu-btn"
          :title="collapsed ? '展开对话记录' : '收起对话记录'"
          @click="$emit('toggle')"
        >
          <span
            class="sidebar-nav-icon chat-icon"
            data-tutorial="conversation-menu"
            aria-hidden="true"
          >
            <svg viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path
                d="M5 6.5c0-1.38 1.12-2.5 2.5-2.5h13c1.38 0 2.5 1.12 2.5 2.5v8.5c0 1.38-1.12 2.5-2.5 2.5h-5.6l-3.4 3.2.6-3.2H7.5c-1.38 0-2.5-1.12-2.5-2.5V6.5z"
                stroke="currentColor"
                stroke-width="1.45"
                stroke-linejoin="round"
              />
              <path
                d="M9 9.5h10"
                stroke="currentColor"
                stroke-width="1.45"
                stroke-linecap="round"
              />
              <path d="M9 13h6" stroke="currentColor" stroke-width="1.45" stroke-linecap="round" />
            </svg>
          </span>
          <span class="sidebar-nav-label">对话记录</span>
        </button>

        <button type="button" class="sidebar-nav-row" title="新建对话" @click="$emit('create')">
          <span
            class="sidebar-nav-icon pencil-icon"
            data-tutorial="quick-new-conversation"
            aria-hidden="true"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="24"
              height="24"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="1.6"
              stroke-linecap="round"
              stroke-linejoin="round"
            >
              <path
                d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
              />
              <path d="m15 5 4 4" />
            </svg>
          </span>
          <span class="sidebar-nav-label">新建对话</span>
        </button>

        <button
          type="button"
          class="sidebar-nav-row workspace-control-btn"
          :class="{ active: workspaceCollapsed }"
          :title="workspaceCollapsed ? '显示工作区' : '隐藏工作区'"
          @click="$emit('toggle-workspace')"
        >
          <span class="sidebar-nav-icon" data-tutorial="workspace-toggle" aria-hidden="true">
            <span class="icon icon-md" :style="iconStyle('layers')"></span>
          </span>
          <span class="sidebar-nav-label">工作区</span>
        </button>

        <button
          type="button"
          class="sidebar-nav-row monitor-mode-btn"
          :class="{ active: displayMode === 'monitor', blocked: displayModeDisabled }"
          :aria-disabled="displayModeDisabled"
          :title="displayMode === 'monitor' ? '退出显示器' : '虚拟显示器'"
          @click="$emit('toggle-display-mode')"
        >
          <span class="sidebar-nav-icon" data-tutorial="monitor-toggle" aria-hidden="true">
            <span class="icon icon-md" :style="iconStyle('monitor')"></span>
          </span>
          <span class="sidebar-nav-label">虚拟显示器</span>
        </button>
      </div>

      <div class="conversation-search">
        <label class="search-input-wrap">
          <span class="sidebar-nav-icon search-inline-icon" aria-hidden="true">
            <span class="icon icon-sm" :style="iconStyle('search')"></span>
          </span>
          <input
            class="search-input"
            :value="searchQuery"
            placeholder="搜索对话"
            @input="$emit('search', ($event.target as HTMLInputElement).value)"
            @keydown.enter.prevent="
              $emit('search-submit', ($event.target as HTMLInputElement).value)
            "
          />
        </label>
      </div>

      <div class="conversation-list">
        <div
          v-if="loading && !displayConversations.length && !searchActive"
          class="loading-conversations"
        >
          正在加载...
        </div>
        <div v-else-if="!displayConversations.length && !loading" class="no-conversations">
          {{ searchActive ? '未找到匹配对话' : '暂无对话记录' }}
        </div>
        <transition-group
          v-else
          name="conversation-delete"
          tag="div"
          class="conversation-list-items"
          :class="`animation-mode-${conversationListAnimationMode}`"
        >
          <div
            v-for="conv in displayConversations"
            :key="conv.id"
            class="conversation-item"
            :class="{
              active: conv.id === currentConversationId,
              'insert-from-left': conversationInsertAnimations[conv.id] === 'create',
              'insert-from-under': conversationInsertAnimations[conv.id] === 'duplicate',
              'duplicate-source-mask': conversationInsertAnimations[conv.id] === 'duplicateSource'
            }"
            @click="
              openActionMenuId = null;
              $emit('select', conv.id);
            "
          >
            <div class="conversation-title">{{ conv.title }}</div>
            <div
              class="conversation-action-wrap"
              :class="{ 'menu-open': openActionMenuId === conv.id }"
              @click.stop
            >
              <button
                type="button"
                class="conversation-more-btn"
                title="更多操作"
                aria-label="更多操作"
                :aria-expanded="openActionMenuId === conv.id"
                @click="toggleActionMenu(conv.id)"
              >
                <span aria-hidden="true"></span>
              </button>
              <div
                class="conversation-actions-menu"
                :class="{ open: openActionMenuId === conv.id }"
              >
                <button
                  type="button"
                  @click="
                    openActionMenuId = null;
                    $emit('duplicate', conv.id);
                  "
                >
                  <span class="icon icon-sm" :style="iconStyle('copy')" aria-hidden="true"></span>
                  <span>复制</span>
                </button>
                <button
                  type="button"
                  class="danger"
                  @click="
                    openActionMenuId = null;
                    $emit('delete', conv.id);
                  "
                >
                  <span class="icon icon-sm" :style="iconStyle('trash')" aria-hidden="true"></span>
                  <span>删除</span>
                </button>
              </div>
            </div>
          </div>
        </transition-group>
        <div v-if="!searchActive && hasMore" class="load-more">
          <button
            class="load-more-btn"
            type="button"
            :disabled="loadingMore"
            @click="$emit('load-more')"
          >
            {{ loadingMore ? '载入中...' : '加载更多' }}
          </button>
        </div>
        <div v-else-if="searchActive" class="load-more search-more">
          <div v-if="searchInProgress" class="search-progress">
            <span class="search-spinner" aria-hidden="true">
              <span class="search-spinner-orbit">
                <span class="icon icon-sm search-spinner-icon" :style="iconStyle('search')"></span>
              </span>
            </span>
            <span class="search-progress-text">搜索中...</span>
          </div>
          <button
            v-else-if="searchMoreAvailable"
            class="load-more-btn"
            type="button"
            @click="$emit('search-more')"
          >
            搜索更多
          </button>
          <div v-else-if="displayConversations.length" class="search-done">已全部搜索</div>
        </div>
      </div>

      <div class="conversation-personal-entry" :class="{ active: personalPageVisible }">
        <button
          type="button"
          class="sidebar-nav-row personal-page-btn"
          data-tutorial="open-personal-space"
          title="个人空间"
          @click="$emit('personal')"
        >
          <span class="sidebar-nav-icon" aria-hidden="true">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
              <path
                fill-rule="evenodd"
                clip-rule="evenodd"
                d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
              ></path>
            </svg>
          </span>
          <span class="sidebar-nav-label personal-label">个人空间</span>
        </button>
      </div>
    </div>
  </aside>
</template>

<script setup lang="ts">
defineOptions({ name: 'ConversationSidebar' });

import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useUiStore } from '@/stores/ui';
import { useConversationStore } from '@/stores/conversation';
import { usePersonalizationStore } from '@/stores/personalization';

const props = withDefaults(
  defineProps<{
    formatTime?: (input: unknown) => string;
    iconStyle?: (key: string) => Record<string, string>;
    showCollapseButton?: boolean;
    collapseButtonVariant?: 'toggle' | 'close';
    displayMode?: 'chat' | 'monitor';
    displayModeDisabled?: boolean;
  }>(),
  {
    showCollapseButton: true,
    collapseButtonVariant: 'toggle',
    displayMode: 'chat',
    displayModeDisabled: false
  }
);

defineEmits<{
  (event: 'toggle'): void;
  (event: 'create'): void;
  (event: 'search', value: string): void;
  (event: 'search-submit', value: string): void;
  (event: 'select', id: string): void;
  (event: 'load-more'): void;
  (event: 'search-more'): void;
  (event: 'personal'): void;
  (event: 'delete', id: string): void;
  (event: 'duplicate', id: string): void;
  (event: 'toggle-workspace'): void;
  (event: 'toggle-display-mode'): void;
}>();

const uiStore = useUiStore();
const conversationStore = useConversationStore();
const personalizationStore = usePersonalizationStore();

const {
  sidebarCollapsed: collapsed,
  workspaceCollapsed,
  chatDisplayMode: uiChatDisplayMode
} = storeToRefs(uiStore);
const {
  searchQuery,
  searchResults,
  searchActive,
  searchInProgress,
  searchMoreAvailable,
  conversations,
  conversationInsertAnimations,
  conversationListAnimationMode,
  conversationsLoading,
  hasMoreConversations: hasMore,
  loadingMoreConversations: loadingMore,
  currentConversationId
} = storeToRefs(conversationStore);
const { visible: personalPageVisible } = storeToRefs(personalizationStore);

const iconStyle = (key: string) => (props.iconStyle ? props.iconStyle(key) : {});
const displayMode = computed(() => props.displayMode);
const monitorModeActive = computed(
  () => displayMode.value === 'monitor' || uiChatDisplayMode.value === 'monitor'
);
const displayModeDisabled = computed(() => props.displayModeDisabled);
const openActionMenuId = ref<string | null>(null);

const toggleActionMenu = (conversationId: string) => {
  openActionMenuId.value = openActionMenuId.value === conversationId ? null : conversationId;
};

const closeActionMenu = () => {
  openActionMenuId.value = null;
};

onMounted(() => {
  document.addEventListener('click', closeActionMenu);
});

onBeforeUnmount(() => {
  document.removeEventListener('click', closeActionMenu);
});

const displayConversations = computed(() =>
  searchActive.value ? searchResults.value : conversations.value
);
const loading = computed(() =>
  searchActive.value ? searchInProgress.value : conversationsLoading.value
);
</script>
