<script setup lang="ts">
import {
  SidebarGroup,
  SidebarGroupLabel,
  SidebarGroupContent,
  SidebarMenu,
  SidebarMenuItem,
  SidebarMenuButton,
} from '@/components/ui/sidebar'
import { ref, onMounted, reactive, nextTick, computed, watch } from 'vue'
import { MoreVertical, Calendar, Clock, Bot, ChevronDown, ChevronRight } from 'lucide-vue-next'
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog'
import {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
} from '@/components/ui/dropdown-menu'
import loader from './loader.vue'
import TypewriterText from './TypewriterText.vue'
import TypingIndicator from './TypingIndicator.vue'
import { formatDate, formatTime } from '@/lib/dateUtils'
import { useConversationCatalogStore } from '@/store/conversationCatalogStore'
import { useStreamingStore } from '@/store/streamingStore'
import { API } from '@/Api'
import { toast } from 'vue-sonner'
import { WT1iser } from '@/lib/wt1'

interface Conversation {
  id: string
  title: string
  lastUpdated: string
  messages: any[]
  agentIds: string[]
  agentCount: number
  modeAgents: boolean
  selectedLlm: string | null
}

const props = defineProps<{
  selectedConversationId?: string | null
  expanded?: boolean
}>()
const emit = defineEmits<{
  (
    e: 'selectConversation',
    payload: {
      conversationId: string
      agentIds: string[]
      modeAgents: boolean
      selectedLlm: string | null
    }
  ): void
  (e: 'newConversationCreated', id: string): void
  (e: 'conversationDeleted', id?: string): void
  (e: 'toggleGroup'): void
}>()

/* ------------------------------------------------------------------ */
const store = useConversationCatalogStore()
const streamingStore = useStreamingStore()
onMounted(() => store.load())

const conversations = computed(() => store.conversations as Conversation[])
const loading = computed(() => store.loading)

/* streaming state */
function isConversationStreaming(conversationId: string): boolean {
  const buffer = streamingStore.getReplyBuffer(conversationId)
  return buffer !== undefined && !buffer.done
}

/* delete dialogs */
const deleteAllOpen = ref(false)
const deleteSingleOpen = ref(false)
const conversationToDelete = ref<string | null>(null)

/* dropdown state tracking */
const openDropdowns = ref<Record<string, boolean>>({})
const openGroupDropdown = ref(false)

/* inline editing */
const editingConversationId = ref<string | null>(null)
const newTitle = ref('')
const editingInputs = reactive<Record<string, HTMLInputElement | null>>({})
const pendingEditId = ref<string | null>(null)

const isCancellingEdit = ref(false)

function handleTitleInputBlur() {
  if (isCancellingEdit.value) return
  doEditTitleInline()
}

// Watch for when editing starts and handle focus
watch(editingConversationId, async (newId) => {
  if (newId) {
    // Wait for DOM update
    await nextTick()

    // Try to focus multiple times to ensure it works
    let attempts = 0
    const tryFocus = () => {
      const input = editingInputs[newId]
      if (input && attempts < 5) {
        attempts++
        input.focus()
        // Check if actually focused
        if (document.activeElement === input) {
          input.setSelectionRange(0, input.value.length)
        } else {
          // Try again
          setTimeout(tryFocus, 50)
        }
      }
    }

    // Start trying after a small delay
    setTimeout(tryFocus, 100)
  }
})

function startEditing(conv: Conversation) {
  // Set the new title
  newTitle.value = conv.title

  // Start editing (the watcher will handle focus)
  editingConversationId.value = conv.id
  pendingEditId.value = null
}

/* API helpers */
async function deleteBackend(id: string | null) {
  if (!id) return
  await API.deleteConversation(id)
  store.invalidate()
  await store.load(true)
}

/* delete handlers */
function requestDeleteAllConversations() {
  deleteAllOpen.value = true
}
async function doDeleteAllConversations() {
  WT1iser.deleteAllConversations()
  await API.deleteAllConversations()
  store.invalidate()
  await store.load(true)
  emit('conversationDeleted')
  deleteAllOpen.value = false
}
function requestDeleteSingleConversation(id: string) {
  conversationToDelete.value = id
  deleteSingleOpen.value = true
}
async function doDeleteSingleConversation() {
  WT1iser.deleteConversation()
  await deleteBackend(conversationToDelete.value)
  if (props.selectedConversationId === conversationToDelete.value)
    emit('conversationDeleted', conversationToDelete.value!)
  deleteSingleOpen.value = false
  conversationToDelete.value = null
}

/* title update */
async function doEditTitleInline() {
  if (!editingConversationId.value) return

  // Only save if title actually changed
  const conv = store.conversations.find((c: any) => c.id === editingConversationId.value)
  if (!conv || newTitle.value.trim() === conv.title) {
    editingConversationId.value = null
    pendingEditId.value = null
    return
  }

  try {
    const res = await API.updateConversationTitle(editingConversationId.value, {
      title: newTitle.value.trim() || 'Untitled',
    })
    updateConversationTitle(editingConversationId.value, res.data.title)
  } catch (err: any) {
    toast.error(err.response?.data?.error || 'Error updating title')
    // Reset the title on error
    newTitle.value = conv.title
  }
  editingConversationId.value = null
  pendingEditId.value = null
}
function updateConversationTitle(id: string, title: string) {
  const conv = store.conversations.find((c: any) => c.id === id)
  if (conv) conv.title = title
}

/* Cancel editing without saving */
function cancelEditing() {
  editingConversationId.value = null
  pendingEditId.value = null
  newTitle.value = ''
}

function handleConversationDblClick(conv: Conversation) {
  if (editingConversationId.value === conv.id) return
  pendingEditId.value = conv.id
  openDropdowns.value[conv.id] = false
  startEditing(conv)
}

/* expose refresh for sidebar */
defineExpose({
  fetchConversations: () => store.load(true),
  updateConversationTitle,
  selectDefaultConversation: () => store.load(true),
})
</script>

<template>
  <SidebarGroup>
    <SidebarGroupLabel
      class="sidebar-group-label sidebar-group-label-main cursor-pointer select-none font-semibold"
      @click="$emit('toggleGroup')"
    >
      <div class="flex items-center justify-between w-full transition-colors">
        <div class="flex items-center">
          <component
            :is="props.expanded ? ChevronDown : ChevronRight"
            class="w-3 h-3 mr-1 transition-transform duration-200"
          />
          <i class="dku-icon-comment-multiple-20 mr-1 font-semibold"></i>Conversations
        </div>
        <DropdownMenu @click.stop v-model:open="openGroupDropdown">
          <DropdownMenuTrigger asChild>
            <button
              @click.stop
              class="sidebar-dropdown-trigger"
              :class="{ 'force-visible': openGroupDropdown }"
            >
              <MoreVertical class="w-3.5 h-3.5" />
            </button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" class="bg-white shadow-lg border-gray-200">
            <DropdownMenuItem @click="requestDeleteAllConversations" class="text-sm text-red-600">
              <i class="dku-icon-trash-16"></i> Delete all conversations
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </div>
    </SidebarGroupLabel>

    <Transition name="accordion">
      <SidebarGroupContent v-show="props.expanded">
        <SidebarMenu>
          <template v-if="loading">
            <SidebarMenuItem>
              <SidebarMenuButton disabled class="sidebar-menu-button">
                <loader />
              </SidebarMenuButton>
            </SidebarMenuItem>
          </template>

          <!-- list conversations -->
          <template v-else>
            <SidebarMenuItem
              v-for="conv in conversations"
              :key="conv.id"
              class="sidebar-menu-item pl-1"
            >
              <SidebarMenuButton
                @click="
                  editingConversationId !== conv.id &&
                    $emit('selectConversation', {
                      conversationId: conv.id,
                      agentIds: conv.agentIds || [],
                      modeAgents: conv.modeAgents,
                      selectedLlm: conv.selectedLlm,
                    })
                "
                @dblclick="handleConversationDblClick(conv)"
                class="sidebar-menu-button conversation-item group"
                :class="{ active: conv.id === selectedConversationId }"
              >
                <div
                  class="flex items-center justify-between w-full"
                  :class="editingConversationId === conv.id ? 'px-[6px] py-1.5' : ''"
                >
                  <div
                    class="min-w-0 flex-1"
                    :class="
                      editingConversationId === conv.id
                        ? 'flex h-[24px] items-center gap-1.5 self-stretch rounded-xs px-[6px] py-1.5 border bg-white'
                        : ''
                    "
                  >
                    <template v-if="editingConversationId === conv.id">
                      <input
                        :ref="el => (editingInputs[conv.id] = el as HTMLInputElement | null)"
                        v-model="newTitle"
                        placeholder="New title"
                        @keydown.enter.prevent="doEditTitleInline"
                        @keydown.esc.prevent="cancelEditing"
                        @blur="handleTitleInputBlur"
                        @click.stop
                        @mousedown.stop
                        class="flex-1 bg-transparent text-sm text-gray-700 focus:outline-none focus:ring-0 focus:border-0"
                        autofocus
                      />
                    </template>

                    <template v-else>
                      <TypewriterText
                        :text="conv.title"
                        :speed="30"
                        :delay="100"
                        :hideEllipsis="isConversationStreaming(conv.id)"
                      />
                    </template>
                  </div>

                  <TypingIndicator v-if="isConversationStreaming(conv.id)" />

                  <!-- Dropdown menu - hidden during editing or pending edit -->
                  <DropdownMenu
                    v-if="
                      editingConversationId !== conv.id &&
                      (!pendingEditId || pendingEditId !== conv.id)
                    "
                    v-model:open="openDropdowns[conv.id]"
                  >
                    <DropdownMenuTrigger asChild>
                      <button
                        @click.stop
                        class="sidebar-dropdown-trigger"
                        :class="{ 'force-visible': openDropdowns[conv.id] }"
                      >
                        <MoreVertical class="w-3.5 h-3.5" />
                      </button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent
                      align="end"
                      class="bg-white shadow-lg border-gray-200"
                      :forceMount="false"
                    >
                      <div
                        class="px-3 py-2 border-b border-gray-100 flex items-center gap-3 text-xs text-gray-500"
                      >
                        <div class="flex items-center gap-1 text-xs">
                          <Calendar class="w-3 h-3 text-gray-500" />
                          <span>{{ formatDate(conv.lastUpdated) }}</span>
                        </div>
                        <div class="flex items-center gap-1">
                          <Clock class="w-3 h-3 text-gray-500" />
                          <span>{{ formatTime(conv.lastUpdated) }}</span>
                        </div>
                        <div class="flex items-center gap-1" v-if="conv.agentCount">
                          <Bot class="w-3 h-3 text-gray-500" />
                          <span>{{ conv.agentCount }}</span>
                        </div>
                      </div>
                      <DropdownMenuItem
                        @click="
                          () => {
                            pendingEditId = conv.id
                            openDropdowns[conv.id] = false
                            startEditing(conv)
                          }
                        "
                        class="text-sm"
                      >
                        <i class="dku-icon-edit-16"></i>Rename
                      </DropdownMenuItem>
                      <DropdownMenuItem
                        @click="requestDeleteSingleConversation(conv.id)"
                        class="text-sm text-red-600"
                      >
                        <i class="dku-icon-trash-16"></i> Delete Conversation
                      </DropdownMenuItem>
                    </DropdownMenuContent>
                  </DropdownMenu>
                </div>
              </SidebarMenuButton>
            </SidebarMenuItem>
          </template>
        </SidebarMenu>
      </SidebarGroupContent>
    </Transition>

    <!-- Delete ALL conversations dialog -->
    <AlertDialog v-model:open="deleteAllOpen">
      <AlertDialogContent>
        <AlertDialogHeader>
          <AlertDialogTitle>
            <i class="dku-icon-trash-16 mr-2"></i>Delete All Conversations</AlertDialogTitle
          >
          <AlertDialogDescription>
            This action cannot be undone. All conversations will be permanently removed.
          </AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogCancel>Cancel</AlertDialogCancel>
          <AlertDialogAction
            @click="doDeleteAllConversations"
            class="bg-red-600 text-white hover:bg-red-700"
          >
            Delete all
          </AlertDialogAction>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>

    <!-- Delete ONE conversation dialog -->
    <AlertDialog v-model:open="deleteSingleOpen">
      <AlertDialogContent>
        <AlertDialogHeader>
          <AlertDialogTitle>
            <i class="dku-icon-trash-16 mr-2"></i>Delete Conversation</AlertDialogTitle
          >
          <AlertDialogDescription>
            This action cannot be undone. This conversation will be permanently removed.
          </AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogCancel>Cancel</AlertDialogCancel>
          <AlertDialogAction
            @click="doDeleteSingleConversation"
            class="bg-red-600 text-white hover:bg-red-700"
          >
            Delete the conversation
          </AlertDialogAction>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>
  </SidebarGroup>
</template>

<style scoped>
/* Smooth transition for inline editing */
input {
  transition: all 0.15s ease;
}

/* Match the input height to the text height for seamless editing */
.sidebar-menu-button input {
  line-height: 1.5;
  font-size: 13px;
}
</style>
