<template>
  <div class="flex flex-col h-full relative bg-white">
    <!-- Messages area - scrollable -->
    <div class="flex flex-col flex-1 px-3 min-h-0">
      <!-- Empty state when no agent selected & no messages -->
      <div
        v-if="showEmptyState && !draftMode"
        class="flex items-center h-full mx-auto w-full max-w-3xl px-0 md:px-0"
      >
        <div class="text-2xl text-foreground leading-8 pl-0 -translate-y-15">
          <p>Start the conversation</p>
          <p>We'll match you with the right agents</p>
        </div>
      </div>
      <!-- Prompt when an agent is selected but there are no messages yet -->
      <div
        v-else-if="showAgentPromptState && !chatDisabled && !draftMode"
        class="flex items-center h-full mx-auto w-full max-w-3xl px-0 md:px-0"
      >
        <div class="text-2xl text-foreground leading-8 pl-0 -translate-y-15">
          <p>Start the conversation</p>
        </div>
      </div>
      <div
        v-else-if="chatDisabled"
        class="flex flex-1 items-center text-foreground text-xl my-auto"
      >
        Fill in the instructions to test the agent
      </div>
      <div ref="messagesContainer" v-else class="flex-1 overflow-y-auto">
        <div class="space-y-3 mt-1 w-full lg:max-w-[768px] mx-auto">
          <div
            v-for="(msg, idx) in activeMessages"
            :key="msg.id ?? idx"
            class="px-4 py-2"
            :class="{
              'ml-auto text-gray-800 w-fit': msg.role === 'user',
              'self-start bg-white w-full relative': msg.role === 'assistant',
              'md:mt-14 mt-3': idx === 0,
            }"
          >
            <!-- User message with edit button in actions area -->
            <div v-if="msg.role === 'user'" class="flex justify-end">
              <div>
                <div class="bg-gray-50 text-gray-800 rounded-md shadow-sm">
                  <div
                    v-if="editingMessageId === msg.id"
                    class="space-y-2 p-4 border border-primary rounded-md"
                  >
                    <textarea
                      v-model="editingContent"
                      ref="editTextareaRef"
                      class="w-full resize-none focus:outline-none"
                      rows="3"
                      @keydown.enter.exact.prevent="saveEdit(msg)"
                      @keydown.escape="cancelEdit"
                    />
                    <div class="flex justify-end space-x-2">
                      <button
                        @click="cancelEdit"
                        class="px-3 py-1 text-sm text-gray-600 hover:text-gray-800 border border-gray-300 rounded-lg hover:border-gray-400"
                      >
                        Cancel
                      </button>
                      <button
                        @click="saveEdit(msg)"
                        class="px-3 py-1 text-sm bg-primary text-white rounded-lg hover:bg-primary-hover disabled:bg-primary/50 disabled:cursor-not-allowed"
                        :disabled="!editingContent.trim()"
                      >
                        Send
                      </button>
                    </div>
                  </div>
                  <div v-else class="px-4 py-2">
                    <MarkdownRenderer :content="msg.content" />
                  </div>
                </div>

                <!-- Action buttons for user messages -->
                <div v-if="editingMessageId !== msg.id" class="flex items-start gap-2">
                  <div class="flex w-full justify-end pt-2 pb-3">
                    <!-- Edit -->
                    <Tooltip>
                      <TooltipTrigger>
                        <button
                          class="inline-flex h-7 w-7 items-center justify-center rounded dark:hover:bg-slate-800 hover:bg-primary/60 hover:border-primary/80"
                          @click="startEdit(msg)"
                          :disabled="isStreaming"
                        >
                          <i class="dku-icon-edit-16"></i>
                        </button>
                      </TooltipTrigger>
                      <TooltipContent :hide-arrow="true"><span>Edit message</span></TooltipContent>
                    </Tooltip>
                    <!-- Copy -->
                    <Tooltip>
                      <TooltipTrigger>
                        <button
                          class="inline-flex h-7 w-7 items-center justify-center rounded dark:hover:bg-slate-800 hover:bg-primary/60 hover:border-primary/80"
                          @click="msg.id && copyToClipboard(msg.content, msg.id)"
                          :disabled="!msg.id"
                        >
                          <i
                            v-if="msg.id && copiedStatus[msg.id]"
                            class="dku-icon-checkmark-16"
                          ></i>
                          <i v-else class="dku-icon-copy-16"></i>
                        </button>
                      </TooltipTrigger>
                      <TooltipContent :hide-arrow="true"><span>Copy</span></TooltipContent>
                    </Tooltip>
                  </div>
                </div>
              </div>
            </div>

            <!-- Assistant message (unchanged structure) -->
            <div v-else class="w-full">
              <div class="bg-white">
                <MarkdownRenderer :content="msg.content" />
              </div>
              <template
                v-for="[artsId, plans] of Object.entries(groupPlansByArtifacts(msg))"
                v-if="msg.artifactsMetadata"
                :key="artsId"
              >
                <template
                  v-for="(artifact, artIndex) in msg.artifactsMetadata[artsId].artifacts"
                  v-if="!msg.artifactsMetadata[artsId].preview"
                >
                  <Card
                    class="mt-4 space-y-4 rounded-md"
                    v-if="groupPlansByArtifactIndex(plans)[artIndex]?.length > 0"
                  >
                    <CardHeader class="space-y-4">
                      <div class="flex items-center space-x-2">
                        <Badge class="bg-muted text-foreground text-sm">
                          <i class="dku-icon-ai-agent-12" />
                          <span> {{ msg.artifactsMetadata[artsId].agentName }}</span>
                        </Badge>
                        <div class="ml-auto">
                          <Button
                            size="sm"
                            variant="outline"
                            class="max-w-[200px] truncate whitespace-nowrap overflow-hidden"
                            @click.stop="downloadArtifacts(msg.id, artsId, artIndex)"
                          >
                            <i class="dku-icon-file-download-16"></i>
                            {{ artifact.name }}
                          </Button>
                        </div>
                      </div>
                    </CardHeader>
                    <template
                      v-for="(plan, planIdx) in groupPlansByArtifactIndex(plans)[artIndex]"
                      :key="planIdx + '-' + plan.artifact_index"
                    >
                      <div class="px-4" v-if="planIdx > 0">
                        <hr class="border-t border-gray-300" />
                      </div>
                      <CardHeader class="space-y-4">
                        <div class="flex items-center space-x-2">
                          <CardTitle v-if="plan.chart_plan.chart_data"
                            >{{ plan.chart_plan.chart_data.title || 'Generated Chart' }}
                          </CardTitle>
                          <ChartControllersButtons
                            class="ml-auto"
                            :overlay-controls="true"
                            @save-image="
                              itemRefs[
                                artsId + '-' + planIdx + '-' + plan.artifact_index
                              ]?.saveImage?.()
                            "
                            @restore="
                              itemRefs[
                                artsId + '-' + planIdx + '-' + plan.artifact_index
                              ]?.restore?.()
                            "
                          ></ChartControllersButtons>
                        </div>
                      </CardHeader>
                      <CardContent v-if="plan.chart_plan.chart_data">
                        <div class="h-80">
                          <div v-if="loadingGraph === msg.id" class="text-sm opacity-70">
                            Generating chart…
                          </div>
                          <div
                            v-else-if="genErrors.indexOf(msg.id ?? idx.toString()) > -1"
                            class="text-sm text-red-600"
                          >
                            Failed to generate
                          </div>
                          <ChartRenderer
                            v-else
                            :ref="(el: any) => setItemRef(el, artsId+'-'+planIdx + '-' + plan.artifact_index)"
                            class="h-full"
                            :data="
                              executePlan(
                                extractRecordsFromArtifactsFlat(
                                  msg.artifactsMetadata[plan.artifacts_id].artifacts
                                )[plan.artifact_index][plan.records_index],
                                plan.chart_plan.chart_data
                              )
                            "
                          />
                        </div>
                      </CardContent>
                      <CardContent v-else class="text-sm text-red-600">
                        <Alert variant="info" class="mb-3 py-2 px-2" collapsible defaultCollapsed>
                          <i class="dku-icon-info-circle-outline-16"></i>
                          <AlertTitle>No chart has been generated</AlertTitle>
                          <AlertDescription>
                            {{ plan.chart_plan.justification }}
                          </AlertDescription>
                        </Alert>
                      </CardContent>
                    </template>
                  </Card>
                </template>
                <Card
                  class="mt-4 space-y-4 rounded-md"
                  v-if="
                    !msg.artifactsMetadata[artsId].artifacts ||
                    msg.artifactsMetadata[artsId].preview
                  "
                >
                  <CardHeader class="space-y-4">
                    <div class="flex items-center space-x-2">
                      <Badge class="bg-muted text-foreground text-sm">
                        <i class="dku-icon-ai-agent-12" />
                        <span> {{ msg.artifactsMetadata[artsId].agentName }}</span>
                      </Badge>
                    </div>
                  </CardHeader>
                  <CardContent class="text-sm text-red-600">
                    <Alert variant="info" class="mb-3 py-2 px-2" collapsible defaultCollapsed>
                      <i class="dku-icon-info-circle-outline-16"></i>
                      <AlertTitle
                        >The chart cannot be generated because the record is too large</AlertTitle
                      >
                      <AlertDescription
                        >A preview of the record is available in `See details` section
                      </AlertDescription>
                    </Alert>
                  </CardContent>
                </Card>
              </template>
              <!-- “see details” button -->
              <div v-if="msg.role === 'assistant' && (msg.hasEventLog || msg.eventLog) && msg.id">
                <!-- special message actions -->
                <div class="flex pt-2 gap-2 overflow-x" v-if="shouldShowActionButtons(msg)">
                  <Button
                    variant="outline"
                    size="sm"
                    @click="createStory(msg)"
                    v-if="msg.actions?.stories?.enable_stories"
                    :disabled="loadingStory !== null"
                  >
                    <i
                      v-if="loadingStory === msg.id"
                      class="dku-icon-arrow-clockwise-16 animate-spin"
                    ></i>
                    <span :class="{ 'animate-pulse': loadingStory === msg.id }">{{
                      msg.actions?.stories?.stories_id
                        ? 'Go to Stories'
                        : loadingStory === msg.id
                        ? 'Preparing Stories'
                        : 'Continue in Stories'
                    }}</span>
                    <i
                      v-if="loadingStory !== msg.id"
                      class="dku-icon-arrow-external-link-16 mr-1"
                    ></i>
                  </Button>
                  <Button
                    variant="outline"
                    size="sm"
                    @click="createChart(msg, idx)"
                    v-if="allowChartCreation(msg)"
                    :disabled="loadingGraph !== null || loadingStory !== null"
                  >
                    <i
                      v-if="loadingGraph === msg.id"
                      class="dku-icon-arrow-clockwise-16 animate-spin"
                    ></i>
                    <i v-else class="dku-icon-bar-chart-16 mr-1"></i>
                    <span :class="{ 'animate-pulse': loadingGraph === msg.id }">
                      {{ loadingGraph === msg.id ? 'Creating chart' : 'Create charts' }}</span
                    >
                  </Button>
                  <Button
                    variant="outline"
                    size="sm"
                    @click.stop="downloadCsvsFromMsg(msg)"
                    v-if="msg.artifactsMetadata && Object.keys(msg.artifactsMetadata).length > 0"
                  >
                    <i class="dku-icon-arrow-download-16"></i>
                    <span>Downloads</span>
                  </Button>
                </div>
                <div class="flex items-start gap-2">
                  <!-- generic message actions -->
                  <div class="flex justify-start pt-2 pb-1">
                    <div
                      v-if="msg.role === 'assistant' && msg.id"
                      class="relative flex items-center"
                    >
                      <!-- Copy -->
                      <Tooltip>
                        <TooltipTrigger>
                          <button
                            class="inline-flex h-7 w-7 items-center justify-center rounded hover:bg-primary/60 hover:border-primary/80 dark:hover:bg-slate-800"
                            @click="copyToClipboard(msg.content, msg.id)"
                          >
                            <i v-if="copiedStatus[msg.id]" class="dku-icon-checkmark-16"></i>
                            <i v-else class="dku-icon-copy-16"></i>
                          </button>
                        </TooltipTrigger>
                        <TooltipContent :hide-arrow="true"><span>Copy</span></TooltipContent>
                      </Tooltip>
                      <template v-if="!draftMode">
                        <Tooltip>
                          <TooltipTrigger>
                            <button
                              class="inline-flex h-7 w-7 items-center justify-center rounded hover:bg-primary/60 hover:border-primary/80 dark:hover:bg-slate-800 disabled:opacity-50"
                              :aria-label="
                                getCurrentRating(msg) === 1 ? 'Remove like' : 'Mark helpful'
                              "
                              :disabled="sendingFeedback[msg.id]"
                              @click="toggleFeedback(msg, 'up')"
                            >
                              <i
                                class="dku-icon-thumbs-up-16"
                                :class="{
                                  'text-primary': getCurrentRating(msg) === 1,
                                }"
                              ></i>
                            </button>
                          </TooltipTrigger>
                          <TooltipContent :hide-arrow="true"><span>Helpful</span></TooltipContent>
                        </Tooltip>

                        <!-- Downvote button with its own relative positioning -->
                        <Popover
                          :open="feedbackDialog.open && feedbackDialog.msg?.id === msg.id"
                          @update:open="(v) => onFeedbackPopoverChange(v, msg)"
                        >
                          <PopoverTrigger :as-child="true">
                            <button
                              class="inline-flex h-7 w-7 items-center justify-center rounded hover:bg-primary/60 hover:border-primary/80 dark:hover:bg-slate-800 disabled:opacity-50 transition-all duration-200"
                              :class="{
                                'bg-primary/60 border-primary/80':
                                  feedbackDialog.open && feedbackDialog.msg?.id === msg.id,
                                'hover:bg-primary/60 hover:border-primary/80': !(
                                  feedbackDialog.open && feedbackDialog.msg?.id === msg.id
                                ),
                              }"
                              :style="
                                feedbackDialog.open && feedbackDialog.msg?.id === msg.id
                                  ? {
                                      background:
                                        'linear-gradient(0deg, var(--alpha-40, rgba(255, 255, 255, 0.60)) 0%, var(--alpha-40, rgba(255, 255, 255, 0.60)) 100%), var(--colors-primary, #2AB1AC)',
                                    }
                                  : {}
                              "
                              :aria-label="
                                getCurrentRating(msg) === 0 ? 'Remove dislike' : 'Mark not helpful'
                              "
                              :disabled="sendingFeedback[msg.id]"
                              @click="toggleFeedback(msg, 'down')"
                            >
                              <i
                                class="dku-icon-thumbs-down-16"
                                :class="{
                                  'text-red-600': getCurrentRating(msg) === 0,
                                }"
                              ></i>
                            </button>
                          </PopoverTrigger>
                          <Tooltip>
                            <TooltipTrigger :as-child="true">
                              <!-- The button is already the trigger via PopoverTrigger, so reference it or wrap minimally -->
                            </TooltipTrigger>
                            <TooltipContent :hide-arrow="true"
                              ><span>Not helpful</span></TooltipContent
                            >
                          </Tooltip>
                          <PopoverContent ref="feedbackPanelEl" class="w-[360px]">
                            <div>
                              <div class="flex items-center">
                                <h3 class="text-sm text-foreground">What could be improved?</h3>
                              </div>
                              <p class="text-sm text-muted-foreground">
                                Let us know why this reply wasn’t helpful
                              </p>

                              <textarea
                                ref="feedbackTextareaRef"
                                v-model="feedbackDialog.text"
                                rows="5"
                                class="feedback-textarea mt-3 w-full resize-none rounded-md border border-gray-300 p-3 text-sm outline-none focus:ring-2 focus:ring-[#2AB1AC]"
                                placeholder="Write a short note"
                              ></textarea>

                              <div class="mt-4 flex justify-end gap-1">
                                <button
                                  class="rounded-md border border-gray-300 bg-white px-4 py-1.5 text-sm text-gray-700 hover:bg-gray-50 disabled:opacity-50"
                                  :disabled="sendingFeedback[msg.id]"
                                  @click="closeDownvotePanel()"
                                >
                                  Skip
                                </button>
                                <button
                                  class="rounded-md bg-[#2AB1AC] px-4 py-1.5 text-sm font-medium text-white hover:bg-[#239C97] disabled:opacity-50 disabled:cursor-not-allowed"
                                  :disabled="sendingFeedback[msg.id] || !feedbackDialog.text.trim()"
                                  @click="submitDownvote()"
                                >
                                  Send
                                </button>
                              </div>
                            </div>
                          </PopoverContent>
                        </Popover>
                      </template>
                    </div>
                  </div>
                  <!-- First div - Event Log Button -->
                  <div class="flex row">
                    <Button variant="ghost" size="sm" @click="openEventLogPanel(msg)" class="mt-1">
                      <i class="dku-icon-text-box-16 text-primary" />
                      <span>See&nbsp;details</span>
                      <i class="dku-icon-chevron-right-16" />
                    </Button>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <!-- <AgentsAnswers
            v-if="true"
            :live-events="liveEvents"
            :has-pending-live-event="true"
          ></AgentsAnswers> -->
          <div ref="bottomRef"></div>
        </div>
      </div>

      <!-- New container to manage space for examples -->
      <div class="flex-shrink-0 relative">
        <div
          class="absolute inset-x-0 bottom-full bg-white pb-2"
          :class="{
            'min-h-[120px]':
              (showExampleQuestions && switchEnabled) ||
              (displayedAgentExampleSuggestions.length &&
                !showExampleQuestions &&
                isConversationEmpty &&
                switchEnabled &&
                !draftMode),
          }"
        >
          <!-- Examples when agent(s) are selected -->
          <div
            v-if="showExampleQuestions && switchEnabled"
            class="mt-6 space-y-2 sm:px-0 max-h-[30vh] overflow-y-auto mx-auto max-w-3xl pb-1.5"
          >
            <Card
              v-for="(ex, idx) in exampleQuestions"
              :key="`${ex.agentId}:${ex.question}:${idx}`"
              @click="handleExampleQuestion(ex)"
              class="rounded-md shadow px-2 py-2 flex flex-row gap-2 cursor-pointer hover:bg-primary/10 hover:border-primary-alpha-dark-80 hover:text-primary-alpha-dark-80 transition-colors text-sm leading-5"
            >
              <AgentPopover
                :icon="getAgentTypeIcon(toRaw(ex.agent), 16)"
                :name="ex.agent.name"
                :description="ex.agent.description"
              />
              <span class="text-foreground">{{ ex.question }}</span>
            </Card>
          </div>

          <!-- More questions button for selected agent examples -->
          <div class="mb-2 max-w-3xl mx-auto md:px-0">
            <Card
              v-if="showExampleQuestions && switchEnabled && hasMoreQuestions"
              key="more"
              class="rounded-lg p-4 py-2 text-base shadow-sm cursor-pointer hover:bg-gray-50 transition-colors mt-2 w-fit"
              @click="loadMoreExamples"
            >
              <p class="flex items-center text-foreground text-sm">
                More <i class="dku-icon-plus-16 ml-1"></i>
              </p>
            </Card>
          </div>

          <!-- All examples shown when no agents are selected -->
          <div
            v-if="
              displayedAgentExampleSuggestions.length &&
              !showExampleQuestions &&
              isConversationEmpty &&
              switchEnabled &&
              !draftMode &&
              !conversationStore.isActiveConversationInitializing
            "
            class="mt-6 space-y-2 max-h-[35vh] overflow-y-auto mx-auto max-w-3xl"
          >
            <Card
              v-for="ex in displayedAgentExampleSuggestions"
              :key="`${ex.agentId}:${ex.question}`"
              @click="handleSuggestedExampleClick(ex)"
              class="rounded-md shadow px-2 py-2 flex flex-row gap-2 cursor-pointer hover:bg-primary/10 hover:border-primary-alpha-dark-80 hover:text-primary-alpha-dark-80 transition-colors text-sm leading-5"
            >
              <AgentPopover
                :icon="getAgentTypeIcon(toRaw(ex.agent), 16)"
                :name="ex.agent.name"
                :description="ex.agent.description"
              />
              <span class="text-foreground">{{ ex.question }}</span>
            </Card>
          </div>

          <!-- More suggestions button for general examples -->
          <div class="mb-2 max-w-3xl mx-auto">
            <Card
              v-if="
                hasMoreSuggestedExamples &&
                !showExampleQuestions &&
                isConversationEmpty &&
                switchEnabled &&
                !conversationStore.isActiveConversationInitializing
              "
              key="more-suggestions"
              class="rounded-lg p-4 py-2 text-base shadow-sm cursor-pointer hover:bg-gray-50 transition-colors mt-2 w-fit"
              @click="loadMoreSuggestedExamples"
            >
              <p class="flex items-center text-foreground text-sm">
                More <i class="dku-icon-plus-16 ml-1"></i>
              </p>
            </Card>
          </div>
        </div>
        <ChatInput
          ref="inputRef"
          v-model:selectedAgents="selectedAgents"
          :allAgents="allAgents"
          :isStreaming="isStreaming"
          :chatDisabled="chatDisabled"
          :hasDeletedSelected="hasDeletedSelected"
          :inputPlaceholder="inputPlaceholder"
          :disableAgentSelection="disableAgentSelection"
          :activeOnlyAgents="props.activeOnlyAgents"
          :showLiveProgressChip="showLiveProgressChip"
          :lastLiveEventInfo="lastLiveEventInfo"
          :activeEventLogMessageId="activeEventLogMessageId"
          :openEventLogPanel="openEventLogPanel"
          :exampleQuestions="exampleQuestions"
          :placeholder="placeholder"
          :useDraft="useDraft"
          @send="handleSend"
          @cancel="handleCancel"
        />
      </div>

      <div class="text-xs p-2 pt-0 text-center" v-if="!draftMode">
        This application is powered by a Large Language Model. Review proposed outcomes in context
        with Responsible AI considerations
      </div>
      <!-- Event-log side-panel -->
      <EventLogPanel
        v-if="showEventLogPanel"
        :eventLog="eventLogToDisplay"
        :artifacts="artifactsForEventLog"
        :messageId="activeEventLogMessageId ?? ''"
        :draftMode="draftMode"
        :agentIds="agentIds"
        @close="showEventLogPanel = false"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
/* ------------------------------------------------------------------ */
import { ref, reactive, onMounted, onBeforeUnmount, watch, computed, nextTick, toRaw } from 'vue'
import { toast } from 'vue-sonner'
import { API } from '@/Api'
import MarkdownRenderer from '@/components/MarkdownRenderer.vue'
import { useAgents } from '@/composables/useAgents'
import { isAgentDeleted } from '@/composables/useAgents'
import AgentPopover from '@/components/AgentPopover.vue'
import EventLogPanel from './EventLogPanel.vue'
import ChatInput from './ChatInput.vue'
import { formatEvtValue, getEventInfoAsHtml } from '@/constants/events'
import throttle from 'lodash/throttle'
import { useConversationStreaming } from '@/composables/useConversationStreaming'
import { useConversationStore } from '@/store/conversationStore'
import { Card } from '@/components/ui/card'
import { executePlan } from '@/lib/executePlan'
import ChartRenderer from './charts/ChartRenderer.vue'
import CardHeader from './ui/card/CardHeader.vue'
import CardTitle from './ui/card/CardTitle.vue'
import CardContent from './ui/card/CardContent.vue'
import type { ActionsChart, EventLogEntry, InitialDraft, Message } from '@/types/messages'
import type { SuggestedExample } from '@/types/agent'
import { usePrefStore } from '@/store/prefStore'
import { storeToRefs } from 'pinia'
import { extractRecordsFromArtifactsFlat } from '@/lib/utils'
import { downloadArtifacts, downloadCsvsFromMsg } from '@/lib/downloadUtils'
import Button from './ui/button/Button.vue'
import Tooltip from './ui/tooltip/Tooltip.vue'
import { TooltipContent, TooltipTrigger } from './ui/tooltip'
import { Popover, PopoverContent, PopoverTrigger } from './ui/popover'
import { useAgentStore } from '@/store/agentStore'
import { useStreamingStore } from '@/store/streamingStore'
import { getAgentTypeIcon } from '@/lib/agentUtils'
import { WT1iser } from '@/lib/wt1'
import { Badge } from '@/components/ui/badge'
import Alert from './ui/alert/Alert.vue'
import AlertTitle from './ui/alert/AlertTitle.vue'
import AlertDescription from './ui/alert/AlertDescription.vue'
import ChartControllersButtons from './charts/ChartControllersButtons.vue'
// import { MOCKED_MSG1 } from '@/lib/mockedMsg'
const STORIES_LOCAL_STORAGE_KEY = 'stories.autoStartPrompts'

/* Props & Emits */
const props = defineProps<{
  agentIds: string[]
  conversationId: string
  disableAgentSelection?: boolean
  chatDisabled?: boolean
  activeOnlyAgents?: boolean
  draftMode?: boolean
  initialDraft?: InitialDraft | null
  skipInitialLoad?: boolean
  initialMessage?: string | null
  submit?: boolean
  placeholder: string
  useDraft?: boolean
}>()

const emits = defineEmits<{
  (e: 'conversationCreated', p: { conversationId: string }): void
  (e: 'conversationUpdated', p: { conversationId: string; agentIds: string[] }): void
  (e: 'initialMessageSent'): void
}>()

const prefStore = usePrefStore()
const { uiConf } = storeToRefs(prefStore)

// Stores and composables
const conversationStore = useConversationStore()
const { sendMessage, cancelStream, switchToConversation, isConnected } = useConversationStreaming()
const streamingstore = useStreamingStore()

const disableAgentSelection = computed(() => !!props.disableAgentSelection)
const chatDisabled = computed(() => !!props.chatDisabled)

/* Local UI state */
const genErrors = ref<Array<string>>([])
const copiedStatus = ref<Record<string, boolean>>({})
const sendingFeedback = ref<Record<string, boolean>>({})

// Store refs in an array
const itemRefs = ref<Record<string, InstanceType<typeof ChartRenderer>>>({})

function setItemRef(el: InstanceType<typeof ChartRenderer>, index: string) {
  if (el) {
    itemRefs.value[index] = el
  }
}
const switchEnabled = computed({
  get: () => prefStore.showChatExamples,
  set: (value) => {
    prefStore.setShowChatExamples(value)
  },
})

const inputRef = ref<InstanceType<typeof ChatInput> | null>(null)
const messagesContainer = ref<HTMLElement | null>(null)
const bottomRef = ref<HTMLElement | null>(null)
const userScrolledAway = ref(false)

const showEventLogPanel = ref(false)
const detailedEventLog = ref<Array<EventLogEntry>>([])
const detailedEventLogs = ref<Record<string, Array<EventLogEntry>>>({})
const activeEventLogMessageId = ref<string | null>(null)
const pendingEvents = ref<Array<EventLogEntry> | null>(null)

/* Agents */
const selectedAgents = computed<string[]>({
  get: () => {
    const conv = conversationStore.getConversation(props.conversationId)
    return conv ? [...conv.agentIds] : [...props.agentIds]
  },
  set: (ids) => {
    conversationStore.updateAgentIds(props.conversationId, ids)
  },
})
watch(
  () => props.agentIds,
  (ids) => (selectedAgents.value = [...ids])
)

const { agents: allAgents, activeAgents, agentsById, fetchAgents } = useAgents()
onMounted(() => fetchAgents())

/* Computed properties from conversation store */
const activeMessages = computed(() => conversationStore.activeMessages)
const isStreaming = computed(() => conversationStore.activeConversation?.isStreaming || false)
const hasQuestionBeingAsked = computed(
  () => streamingstore.replyBuffers[props.conversationId]?.userMessage !== undefined
)
const isConversationEmpty = computed(
  () => conversationStore.isConversationEmpty && !hasQuestionBeingAsked.value
)
const showEmptyState = computed(() => conversationStore.showEmptyState)
const showAgentPromptState = computed(() => conversationStore.showAgentPromptState)
const hasSelectedAgents = computed(() => conversationStore.hasSelectedAgents)

/* Counts */
const deletedCount = computed(
  () => selectedAgents.value.filter((id) => isAgentDeleted(id, allAgents.value)).length
)
const hasDeletedSelected = computed(() => deletedCount.value > 0)

const eventLogToDisplay = computed(() => {
  const streaming = isStreaming.value
  const liveEvents = conversationStore.activeConversation?.liveEvents || []

  if (streaming && showEventLogPanel.value && liveEvents.length > 0) {
    return liveEvents.map((event) => ({
      eventKind: event.kind,
      eventData: event.data || {},
    }))
  }
  // if streaming just ended and we cached pending events but no message id yet
  if (
    showEventLogPanel.value &&
    !streaming &&
    !activeEventLogMessageId.value &&
    pendingEvents.value
  ) {
    return pendingEvents.value
  }

  if (activeEventLogMessageId.value && detailedEventLogs.value[activeEventLogMessageId.value]) {
    return detailedEventLogs.value[activeEventLogMessageId.value]
  }
  return []
})
const artifactsForEventLog = computed(() => {
  if (!activeEventLogMessageId.value) return {}
  const msg = activeMessages.value.find((m) => m.id === activeEventLogMessageId.value)
  return msg?.artifactsMetadata || {}
})
watch(
  () => isStreaming.value,
  (newIsStreaming, oldIsStreaming) => {
    if (oldIsStreaming && !newIsStreaming && showEventLogPanel.value) {
      const liveEvents = conversationStore.activeConversation?.liveEvents || []
      if (liveEvents.length === 0) return

      const transformedEvents = liveEvents.map((event) => ({
        eventKind: event.kind,
        eventData: event.data || {},
      }))

      const lastAssistantMessage = [...activeMessages.value]
        .reverse()
        .find((msg) => msg.role === 'assistant' && msg.id)

      if (lastAssistantMessage?.id) {
        detailedEventLogs.value[lastAssistantMessage.id] = transformedEvents
        activeEventLogMessageId.value = lastAssistantMessage.id
        pendingEvents.value = null
      } else {
        // Assistant message not yet materialized; hold events temporarily
        pendingEvents.value = transformedEvents
      }
    }
  },
  { flush: 'sync' }
)
// Update the activeEventLogMessageId with the last assistant message
watch(
  () => activeMessages.value.map((m) => m.id),
  () => {
    if (!pendingEvents.value || isStreaming.value) return
    const lastAssistantMessage = [...activeMessages.value]
      .reverse()
      .find((msg) => msg.role === 'assistant' && msg.id)
    if (lastAssistantMessage?.id && !detailedEventLogs.value[lastAssistantMessage.id]) {
      detailedEventLogs.value[lastAssistantMessage.id] = pendingEvents.value
      activeEventLogMessageId.value = lastAssistantMessage.id
      pendingEvents.value = null
    }
  }
)

/* Conversation management */
async function handleConversationChange(newId: string, oldId?: string) {
  if (!newId || newId === oldId) return

  // Initialize conversation if it doesn't exist
  if (!conversationStore.hasConversation(newId)) {
    conversationStore.initializeConversation(newId, props.agentIds, {
      draftMode: props.draftMode,
      initialDraft: props.initialDraft,
      skipInitialLoad: props.skipInitialLoad,
    })
  }

  // Load conversation data
  if (!isStreaming.value) {
    await conversationStore.loadConversation(newId, {
      draftMode: props.draftMode,
      initialDraft: props.initialDraft,
      skipInitialLoad: props.skipInitialLoad,
      agentIds: props.agentIds,
    })
  }

  // Switch to conversation and restore streaming state
  await switchToConversation(newId)

  // Update selected agents
  const conversation = conversationStore.getConversation(newId)
  if (conversation) {
    selectedAgents.value = [...conversation.agentIds]
  }

  await nextTick(() => {
    // Initialize scroll position
    const container = messagesContainer.value
    if (container) {
      container.scrollTop = container.scrollHeight
    }
    userScrolledAway.value = false

    if (props.initialMessage && props.submit) {
      handleSend(props.initialMessage)
    }
    emits('initialMessageSent')
    focusInput()
  })
}

watch(() => props.conversationId, handleConversationChange, { immediate: true })

/* Send message */
function handleSend(text: string) {
  if (!text || !isConnected.value) return

  sendMessage(props.conversationId, text, selectedAgents.value, !!props.draftMode)
  nextTick(forceScrollToBottom)
}

function handleCancel() {
  cancelStream(props.conversationId)
}

/* Event-log helper */
async function openEventLogPanel(msg: Message) {
  WT1iser.messageViewEventLog()
  await getMessageEvents(msg)
  showEventLogPanel.value = true
}

// const getAssistantMessagesEvents = async () => {
//   const params: Record<string, string> = {}
//   if (props.draftMode) {
//     params.draft = '1'
//     params.agentId = props.agentIds[0]
//   }
// }
const getMessageEvents = async (msg: Message) => {
  if (!msg.id) return
  if (activeEventLogMessageId.value === msg.id && detailedEventLog.value) {
    return
  }
  if (detailedEventLogs.value[msg.id]) {
    detailedEventLog.value = detailedEventLogs.value[msg.id]
  } else {
    const params: Record<string, string> = {}
    if (props.draftMode) {
      params.draft = '1'
      params.agentId = props.agentIds[0]
    }
    try {
      const resp = await API.getMessageEvents(msg.id, params)
      const events = resp.data.events || []
      // Store in both the cache AND the current display
      detailedEventLogs.value[msg.id] = events
      detailedEventLog.value = events
      activeEventLogMessageId.value = msg.id
    } catch (err) {
      console.error('Error fetching events', err)
      return
    }
  }
  activeEventLogMessageId.value = msg.id || null
}
const loadingStory = ref<string | null>(null)
const loadingGraph = ref<string | null>(null)
const createStory = async (msg: Message) => {
  let storyId = null
  if (!msg.id || !msg.actions?.stories?.tables) return
  loadingStory.value = msg.id
  if (msg.actions.stories.stories_id) {
    storyId = msg.actions.stories.stories_id
    WT1iser.messageViewStory()
  } else {
    try {
      WT1iser.messageCreateStory(msg.actions.stories.tables.length)
      const resp = await API.createStory({
        agent_id: msg.actions.stories.agent_id, //TODO should handle multiple agents with stories
        msg_id: msg.id,
        conv_id: props.conversationId,
        references: Array.from(msg.actions.stories.tables),
      })
      if (resp && resp.data) {
        storyId = resp.data['id']
        const storageData: Record<string, any> = {}
        storageData[storyId] = {
          prompt: resp.data['prompt'],
        }
        localStorage.setItem(STORIES_LOCAL_STORAGE_KEY, JSON.stringify(storageData))
        msg['actions']['stories'] = { ...msg.actions.stories, stories_id: storyId }
        updateMsg(msg)
      } else {
        throw Error('Failed to get id')
      }
    } catch (e) {
      console.error(e)
      // Handle error
      toast.error('Oops! We couldn’t create Dataiku Stories this time.')
      loadingStory.value = null
      return
    }
  }
  loadingStory.value = null
  if (storyId) {
    //Open story
    window.open(`${window.location.origin}/stories/slide/${storyId}`, '_blank')
  }
}
const updateMsg = (msg: Message) => {
  conversationStore.updateMessage(props.conversationId, msg.id!, msg)
}
const allowChartCreation = (msg: Message) => {
  return (
    uiConf.value?.visualization_mode === 'ON_DEMAND' &&
    msg.artifactsMetadata &&
    Object.values(msg.artifactsMetadata).filter((art) => art.has_records && art.artifacts).length >
      0 &&
    !msg.actions?.chart_plans?.length
  )
}
const groupPlansByArtifactIndex = (plans: ActionsChart[]) => {
  const grouped: Record<number, ActionsChart[]> = {}
  for (const plan of plans) {
    const key = plan.artifact_index
    if (!grouped[key]) grouped[key] = []
    grouped[key].push(plan)
  }
  return grouped
}
const groupPlansByArtifacts = (msg: any) => {
  if (!msg.actions || !msg.actions.chart_plans) return {}
  const grouped: Record<string, ActionsChart[]> = {}
  for (const plan of msg.actions.chart_plans) {
    if (!grouped[plan.artifacts_id]) grouped[plan.artifacts_id] = []
    grouped[plan.artifacts_id].push(plan)
  }
  return grouped
}
const createChart = async (msg: Message, msgIndex: number) => {
  if (!msg.id || !msg.actions || !msg.artifactsMetadata) return
  loadingGraph.value = msg.id
  try {
    // For now we generate charts sequentially for each record in each artifact
    // In the future we might want to parallelize this or have a batch endpoint
    for (const [artifact_id, meta] of Object.entries(msg.artifactsMetadata)) {
      const recordsPerArtifact = extractRecordsFromArtifactsFlat(meta.artifacts)
      for (let artIdx = 0; artIdx < meta.artifacts.length; artIdx++) {
        // if (Object.values(recordsPerArtifact).length < 1) throw Error('No records')
        const records = recordsPerArtifact[artIdx]
        for (let index = 0; index < records.length; index++) {
          const record = records[index]
          if (!record || !record.data || record.data.length === 0) continue
          WT1iser.messageGenerateChart(records[index].data.length)
          loadingGraph.value = msg.id
          const resp = await API.createChartPlan({
            msg_id: msg.id,
            msg_index: msgIndex,
            conv_id: props.conversationId,
            data: record.data,
            columns: record.columns,
            records_index: index,
            artifact_index: artIdx,
            artifacts_id: artifact_id,
            query: meta.query,
            agent_name: meta.agentName,
          })
          if (resp && resp.data && resp.data && resp.data.chart_plan) {
            const plans: ActionsChart[] = msg.actions.chart_plans || []
            plans.push(resp.data)
            msg.actions = {
              ...msg.actions,
              chart_plans: plans,
            }
            updateMsg(msg)
          } else {
            throw Error('Failed to get chart plan')
          }
        }
      }
    }
  } catch (err) {
    console.error('Error', err)
    genErrors.value.push(msg.id)
    toast.error('Oops! We couldn’t generate the chart this time.')
  } finally {
    loadingGraph.value = null
  }
}

function getCurrentRating(msg: any): 0 | 1 | undefined {
  const r = msg?.feedback?.rating
  if (r === 0 || r === 1) return r
  if (r === '0') return 0
  if (r === '1') return 1
  return undefined
}

async function toggleFeedback(msg: any, thumb: 'up' | 'down') {
  if (!msg?.id) return
  const id = msg.id as string
  const desired: 0 | 1 = thumb === 'up' ? 1 : 0
  const current = getCurrentRating(msg)
  if (current === desired) {
    try {
      sendingFeedback.value[id] = true
      await API.clearMessageFeedback(id)
      msg.feedback = {}
      // toast?.message?.('Feedback removed.')
    } catch (e) {
      console.error('Failed to clear feedback', e)
      // toast?.error?.('Could not clear feedback.')
    } finally {
      sendingFeedback.value[id] = false
    }
    if (feedbackDialog.msg?.id === id) {
      closeDownvotePanel()
    }
    return
  }
  try {
    sendingFeedback.value[id] = true
    const { data } = await API.upsertMessageFeedback(id, { rating: desired })
    msg.feedback = data?.feedback ?? { rating: desired }
    if (thumb === 'up') {
      WT1iser.messageFeedback(thumb)
      toast?.success?.('Thanks for the feedback!')
    } else {
      WT1iser.messageFeedback('down', false)
      openDownvoteDialog(msg)
    }
  } catch (e) {
    console.error('Failed to submit feedback', e)
    toast?.error?.('Could not submit feedback.')
  } finally {
    sendingFeedback.value[id] = false
  }
}

const feedbackTextareaRef = ref<HTMLTextAreaElement | null>(null)

const feedbackPanelEl = ref<HTMLElement | null>(null)

const feedbackDialog = reactive<{ open: boolean; msg: any | null; text: string }>({
  open: false,
  msg: null,
  text: '',
})

function openDownvoteDialog(msg: any) {
  feedbackDialog.msg = msg
  feedbackDialog.text = (msg?.feedback?.text as string) ?? ''
  feedbackDialog.open = true

  nextTick(() => {
    const el =
      (feedbackTextareaRef.value as unknown as HTMLElement | null) ??
      (feedbackPanelEl.value?.querySelector('textarea') as HTMLTextAreaElement | null)

    if (el && typeof (el as any).focus === 'function') {
      ;(el as any).focus()
    }
  })
}

function closeDownvotePanel() {
  feedbackDialog.open = false
  feedbackDialog.msg = null
  feedbackDialog.text = ''
}

// Updated submitDownvote with as const for body
async function submitDownvote() {
  const msg = feedbackDialog.msg
  if (!msg?.id) {
    closeDownvotePanel()
    return
  }
  const id = msg.id as string
  const text = feedbackDialog.text.trim()
  if (!text) {
    closeDownvotePanel()
    return
  }
  const body = { rating: 0, text } as const
  try {
    WT1iser.messageFeedback('down', true)
    sendingFeedback.value[id] = true
    const { data } = await API.upsertMessageFeedback(id, body)
    msg.feedback = data?.feedback ?? {
      rating: 0,
      text,
    }
    toast?.success?.("Thanks — we'll use this to improve.")
    closeDownvotePanel()
  } catch (e) {
    console.error('Failed to submit downvote', e)
    toast?.error?.('Could not submit feedback.')
  } finally {
    sendingFeedback.value[id] = false
  }
}

function onFeedbackPopoverChange(open: boolean, msg: any) {
  // Sync controlled popover with local dialog state
  const current = getCurrentRating(msg)
  if (open) {
    if (!feedbackDialog.open && current !== 0) {
      openDownvoteDialog(msg)
    }
  } else {
    if (feedbackDialog.open && feedbackDialog.msg?.id === msg?.id) {
      closeDownvotePanel()
    }
  }
}

function handleGlobalKey(e: KeyboardEvent) {
  if (e.key === 'Escape' && feedbackDialog.open) closeDownvotePanel()
}

/* Scroll */
const handleScroll = throttle(() => {
  const container = messagesContainer.value
  if (!container) return
  const distanceToBottom = container.scrollHeight - container.scrollTop - container.clientHeight
  userScrolledAway.value = distanceToBottom > 50
}, 100)

// Ensure scroll listener attaches when the container appears (e.g., first message renders)
watch(
  () => messagesContainer.value,
  (el, oldEl) => {
    if (oldEl) {
      oldEl.removeEventListener('scroll', handleScroll)
    }
    if (el) {
      el.addEventListener('scroll', handleScroll)
    }
  },
  { immediate: true }
)

const forceScrollToBottom = () => {
  const container = messagesContainer.value
  if (!container) return
  container.scrollTo({
    top: container.scrollHeight,
    behavior: 'smooth',
  })
  userScrolledAway.value = false
}
const conditionalScrollToBottom = throttle(
  () => {
    const container = messagesContainer.value
    if (!container) return
    const distanceToBottom = container.scrollHeight - container.scrollTop - container.clientHeight
    if (userScrolledAway.value && distanceToBottom > 50) return
    // Use immediate jump to avoid jank during frequent token updates
    container.scrollTop = container.scrollHeight
  },
  200,
  { trailing: true }
)

/* Example questions to suggest to the user */
const allExampleQuestions = computed<SuggestedExample[]>(() => {
  const ids = selectedAgents.value
  if (ids.length === 0) return []

  const draft = useAgentStore().draft
  const resolveAgent = (id: string) => (draft && id === draft.id ? draft : agentsById.value.get(id))
  const getQuestions = (agent: any): string[] =>
    ((agent?.sample_questions ?? agent?.exampleQuestions ?? []) as string[]).filter(
      (q) => q && q.trim().length > 0
    )
  const asItems = (agent: any, qs: string[]): SuggestedExample[] =>
    qs.map((question) => ({ question, agent, agentId: agent.id }))

  if (props.draftMode) {
    const a = resolveAgent(ids[0])
    if (!a) return []
    return asItems(a, getQuestions(a))
  }

  // Single agent as before
  if (ids.length === 1) {
    const a = resolveAgent(ids[0])
    if (!a) return []
    return asItems(a, getQuestions(a))
  }

  // N agents: take ALL selected agents (in selection order) that have examples
  const resolved = ids.map(resolveAgent).filter(Boolean)
  const candidates: { agent: any; qs: string[] }[] = []

  for (const a of resolved) {
    const qs = getQuestions(a)
    if (qs.length > 0) {
      candidates.push({ agent: a, qs })
    }
  }

  if (candidates.length === 0) {
    // none of the selected agents have examples
    return []
  }

  if (candidates.length === 1) {
    // only one selected agent has examples
    return asItems(candidates[0].agent, candidates[0].qs)
  }

  const maxLen = Math.max(...candidates.map((c) => c.qs.length))
  const combined: SuggestedExample[] = []
  for (let i = 0; i < maxLen; i++) {
    for (const c of candidates) {
      if (c.qs[i] !== undefined) {
        combined.push({ question: c.qs[i], agent: c.agent, agentId: c.agent.id })
      }
    }
  }
  return combined
})
const examplesToShow = ref(3)
const exampleQuestions = computed<SuggestedExample[]>(() =>
  allExampleQuestions.value.slice(0, examplesToShow.value)
)
const hasMoreQuestions = computed(() => {
  return examplesToShow.value < allExampleQuestions.value.length
})
const showExampleQuestions = computed(
  () => showAgentPromptState.value && hasSelectedAgents.value && !isStreaming.value
)

function loadMoreExamples() {
  examplesToShow.value = allExampleQuestions.value.length
}

/* Progressive loading of agent suggestions */
const suggestionsToShow = ref(3)
const agentSuggestions = computed(() => activeAgents.value.slice(0, suggestionsToShow.value))
const hasMoreAgentSuggestions = computed(() => suggestionsToShow.value < activeAgents.value.length)

function loadMoreAgentSuggestions() {
  suggestionsToShow.value = Math.min(suggestionsToShow.value + 3, activeAgents.value.length)
}

function handleExampleQuestion(example: SuggestedExample) {
  WT1iser.selectExampleQuery()
  inputRef.value?.setMessage(example.question)
}

const inputPlaceholder = computed(() => {
  if (hasDeletedSelected.value) return 'Cannot send — selected agent was deleted'
  return props.placeholder
})

const lastLiveEventInfo = computed(() => {
  const active = conversationStore.activeConversation
  if (!active) return { label: '', icon: () => null }

  const ev = active.liveEvents.length ? active.liveEvents[active.liveEvents.length - 1] : undefined
  return ev
    ? {
        ...getEventInfoAsHtml(ev.kind, [
          ev.data?.agentName,
          formatEvtValue(ev.data?.toolName, 'toolName'),
          formatEvtValue(ev.data?.agentAsToolName, 'agentAsToolName'),
        ]),
      }
    : { label: '', icon: () => null, name: '' }
})

const showLiveProgressChip = computed(
  () => isStreaming.value && conversationStore.activeConversation?.hasPendingLiveEvent
)

const agentExampleSuggestions = computed<SuggestedExample[]>(() => {
  if (props.draftMode) return []
  return agentSuggestions.value.flatMap((a) => {
    const questions = (a.exampleQuestions ?? []).filter((q) => q && q.trim().length > 0)
    return questions.map((q) => ({
      agentId: a.id,
      question: q,
      agent: a,
    }))
  })
})

const suggestedExamplesToShow = ref(3)

const displayedAgentExampleSuggestions = computed(() =>
  agentExampleSuggestions.value.slice(0, suggestedExamplesToShow.value)
)

const hasMoreSuggestedExamples = computed(
  () =>
    suggestedExamplesToShow.value < agentExampleSuggestions.value.length ||
    hasMoreAgentSuggestions.value
)

function loadMoreSuggestedExamples() {
  // Load ALL remaining agents so their examples are available
  while (hasMoreAgentSuggestions.value) {
    loadMoreAgentSuggestions()
  }

  // Reveal ALL examples
  nextTick(() => {
    suggestedExamplesToShow.value = agentExampleSuggestions.value.length
  })
}

function handleSuggestedExampleClick(ex: SuggestedExample) {
  WT1iser.selectExampleQuery()
  selectedAgents.value = [ex.agentId]
  conversationStore.updateAgentIds(props.conversationId, [ex.agentId])
  inputRef.value?.setMessage(ex.question)
}

/** Focus helper to keep textarea focused after loads */
function focusInput() {
  // Don't steal focus while editing a message or in draft mode
  if (editingMessageId.value || props.draftMode) {
    console.debug('[ChatInterface] focusInput: skipped (editingMessageId set) or draftMode')
    return
  }

  const refNow = inputRef.value
  console.debug('[ChatInterface] focusInput: called', {
    hasRef: !!refNow,
  })

  nextTick(() => {
    const c = inputRef.value
    if (!c) {
      console.debug('[ChatInterface] focusInput: no child ref -> global textarea fallback')
      const ta = document.querySelector('textarea') as HTMLTextAreaElement | null
      ta?.focus()
      console.debug('[ChatInterface] global textarea focus', { success: !!ta })
      return
    }

    if (typeof (c as any).focusInput === 'function') {
      console.debug('[ChatInterface] focusInput: using child.focusInput()')
      ;(c as any).focusInput()
      return
    }
    if (typeof (c as any).focus === 'function') {
      console.debug('[ChatInterface] focusInput: using child.focus()')
      ;(c as any).focus()
      return
    }
    const root: any = (c as any).$el ?? c
    const ta = root?.querySelector?.('textarea') as HTMLTextAreaElement | null
    if (ta) {
      console.debug('[ChatInterface] focusInput: using querySelector("textarea")')
      ta.focus()
    } else {
      console.debug('[ChatInterface] focusInput: no focus path found')
    }
  })
}

// Keep view pinned to bottom while streaming if user hasn't scrolled away
watch(
  () => conversationStore.activeConversation?.streamingReply,
  () => nextTick(conditionalScrollToBottom)
)

// Also react when messages array changes (e.g., assistant/user message appended)
watch(activeMessages, () => nextTick(conditionalScrollToBottom))

/* Edit message state */
const editingMessageId = ref<string | null>(null)
const editingContent = ref('')

/* Edit message functions */
function startEdit(msg: Message) {
  if (msg.role !== 'user' || isStreaming.value) return
  editingMessageId.value = msg.id || null
  editingContent.value = msg.content
}

function cancelEdit() {
  editingMessageId.value = null
  editingContent.value = ''
}

async function saveEdit(msg: Message) {
  const newContent = editingContent.value.trim()

  if (!newContent || newContent === msg.content) {
    cancelEdit()
    return
  }

  try {
    const msgIndex = conversationStore.activeMessages.findIndex((m) => m.id === msg.id)
    if (msgIndex === -1) {
      throw new Error('Message not found')
    }

    const updatedMessage = { ...msg, content: newContent }
    const messagesToKeep = conversationStore.activeMessages.slice(0, msgIndex + 1)
    messagesToKeep[msgIndex] = updatedMessage

    conversationStore.setMessages(props.conversationId, messagesToKeep)
    if (msg.id && !props.draftMode) {
      WT1iser.messageEditMessage()
      await API.updateMessage(props.conversationId, msg.id, {
        content: newContent,
      })
    }

    cancelEdit()
    toast.success('Message updated')

    await regenerateFromMessage(updatedMessage)
  } catch (error) {
    console.error('Error updating message:', error)
    toast.error('Failed to update message')
  }
}

// Function to regenerate response after edit
async function regenerateFromMessage(editedMessage: Message) {
  if (!isConnected.value) {
    console.warn('Socket not connected, cannot regenerate')
    return
  }

  conversationStore.setStreamingState(props.conversationId, true)
  conversationStore.setLiveEvents(props.conversationId, [])
  conversationStore.setDetailedEventLog(props.conversationId, [])
  conversationStore.setPendingLiveEvent(props.conversationId, false)

  sendMessage(props.conversationId, editedMessage.content, selectedAgents.value, !!props.draftMode)
  nextTick(forceScrollToBottom)
}

/* Copy to clipboard */
const copyToClipboard = async (text: string, id: string) => {
  try {
    await navigator.clipboard.writeText(text)
    copiedStatus.value[id] = true
    setTimeout(() => {
      copiedStatus.value[id] = false
    }, 2000)
  } catch (err) {
    console.error('Failed to copy: ', err)
    toast.error('Could not copy to clipboard.')
  }
}

/* Lifecycle */
onMounted(() => {
  document.addEventListener('keydown', handleGlobalKey)
})

onBeforeUnmount(() => {
  document.removeEventListener('keydown', handleGlobalKey)
  const container = messagesContainer.value
  if (container) {
    container.removeEventListener('scroll', handleScroll)
  }
})
function shouldShowActionButtons(msg: Message) {
  const hasStoryButton = msg.actions?.stories?.enable_stories
  const hasChartButton =
    uiConf.value?.visualization_mode === 'ON_DEMAND' &&
    msg.artifactsMetadata &&
    Object.values(msg.artifactsMetadata).filter((art) => art.has_records).length > 0 &&
    !msg.actions?.chart_plans
  const hasDownloadButton =
    msg.artifactsMetadata &&
    Object.values(msg.artifactsMetadata).filter((art) => art.has_records).length > 0

  return hasStoryButton || hasChartButton || hasDownloadButton
}
</script>

<style scoped>
/* Auto-resize textarea */
textarea {
  field-sizing: content;
  min-height: 2.5rem;
  max-height: 10rem;
}

.feedback-textarea {
  field-sizing: initial;
  min-height: 7rem;
  height: 7rem;
}
</style>
