<!-- Gordon AI Chat Panel -->
<script>
  window.GORDON_BASE_URL = {{ if eq hugo.Environment "production" -}}
    'https://ai-backend-service.docker.com'
  {{- else if getenv "HUGO_GORDON_URL" -}}
    '{{ getenv "HUGO_GORDON_URL" }}'
  {{- else -}}
    'https://ai-backend-service-stage.docker.com'
  {{- end }};
</script>
<div
  x-data="{
    isLoading: false,
    error: null,
    messages: $persist([]).using(sessionStorage).as('gordon-messages'),
    currentQuestion: '',
    threadId: $persist(null).using(sessionStorage).as('gordon-threadId'),
    includePageContext: $persist(true).using(sessionStorage).as('gordon-includePageContext'),
    maxTurnsPerThread: 10,

    init() {
      // Clean up any streaming messages that might be persisted
      this.messages = this.messages.filter(m => !m.isStreaming)

      // Watch for store changes to focus input
      this.$watch('$store.gordon.isOpen', (isOpen) => {
        if (isOpen) {
          this.$nextTick(() => {
            this.$refs.input?.focus()
          })
        }
      })

      // Watch for query from store and populate input
      this.$watch('$store.gordon.query', (query) => {
        if (query) {
          this.currentQuestion = query
          const shouldAutoSubmit = this.$store.gordon.autoSubmit
          this.$nextTick(() => {
            if (shouldAutoSubmit) {
              this.askQuestion()
            } else {
              this.$refs.input?.focus()
              this.$refs.input?.select()
            }
          })
          // Clear the store query and autoSubmit flag after using them
          this.$store.gordon.query = ''
          this.$store.gordon.autoSubmit = false
        }
      })
    },

    getTurnCount() {
      return this.messages.filter(m => m.role === 'user').length
    },

    getRemainingTurns() {
      return this.maxTurnsPerThread - this.getTurnCount()
    },

    isThreadLimitReached() {
      return this.getTurnCount() >= this.maxTurnsPerThread
    },

    shouldShowCountdown() {
      const remaining = this.getRemainingTurns()
      return remaining > 0 && remaining <= 3
    },

    async askQuestion() {
      const question = this.currentQuestion.trim()
      if (!question || this.isLoading || this.isThreadLimitReached()) {
        return
      }

      // Add user message to UI
      this.messages.push({
        role: 'user',
        content: question
      })

      this.currentQuestion = ''
      // Reset textarea height
      this.$nextTick(() => {
        if (this.$refs.input) {
          this.$refs.input.style.height = 'auto'
        }
      })
      this.isLoading = true
      this.error = null

      // Add placeholder for assistant response
      const responseIndex = this.messages.length
      this.messages.push({
        role: 'assistant',
        content: '',
        isStreaming: true,
        questionAnswerId: null,
        feedback: null,
        copied: false
      })

      this.$nextTick(() => {
        this.$refs.messagesContainer?.scrollTo({
          top: this.$refs.messagesContainer.scrollHeight,
          behavior: 'smooth'
        })
      })

      try {
        await this.streamGordonResponse(responseIndex)
      } catch (err) {
        // Only set error if messages weren't cleared
        if (this.messages.length > 0) {
          if (err.message === 'RATE_LIMIT_EXCEEDED') {
            this.error = 'You\'ve exceeded your question quota for the day. Please come back tomorrow.'
          } else {
            this.error = 'Failed to get response. Please try again.'
          }
        }
        console.error('Gordon API error:', err)
        // Only try to remove message if it still exists
        if (this.messages[responseIndex]) {
          this.messages.splice(responseIndex, 1)
        }
      } finally {
        this.isLoading = false
      }
    },

    getSessionId() {
      let sessionId = sessionStorage.getItem('gordon-session-id')
      if (!sessionId) {
        sessionId = `docs-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
        sessionStorage.setItem('gordon-session-id', sessionId)
      }
      return sessionId
    },

    async streamGordonResponse(responseIndex) {

      // Build API request from messages, excluding the streaming placeholder
      // The placeholder is at responseIndex, so we take everything before it
      const conversationMessages = this.messages.slice(0, responseIndex).map((msg, i) => {
        const message = {
          role: msg.role,
          content: msg.content
        }

        // Add copilot_references to the last message (most recent user question)
        if (i === responseIndex - 1) {
          message.copilot_references = [
            {
              data: {
                origin: 'docs-website',
                email: 'docs@docker.com',
                uuid: this.getSessionId(),
                action: 'AskGordon',
                ...(this.includePageContext && {
                  page_url: window.location.href,
                  {{ with .Title }}page_title: {{ . | jsonify }}{{ end }}
                })
              }
            }
          ]
        }

        return message
      })

      const isNewConversation = !this.threadId
      const payload = {
        messages: conversationMessages,
        ...(this.threadId && { thread_uuid: this.threadId })
      }

      const response = await fetch(window.GORDON_BASE_URL + '/public/ask', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
      })

      if (!response.ok) {
        if (response.status === 429) {
          throw new Error('RATE_LIMIT_EXCEEDED')
        }
        throw new Error(`HTTP ${response.status}: ${response.statusText}`)
      }

      const reader = response.body.getReader()
      const decoder = new TextDecoder()

      while (true) {
        const { done, value } = await reader.read()
        if (done) break

        const chunk = decoder.decode(value, { stream: true })
        const lines = chunk.split('\n')

        for (const line of lines) {
          if (!line.trim() || !line.startsWith('data: ')) continue

          const data = line.slice(6)
          if (data === '[DONE]') continue

          try {
            const parsed = JSON.parse(data)

            // Capture thread_id for new conversations
            if (parsed.thread_id) {
              if (isNewConversation) {
                this.threadId = parsed.thread_id  // $persist auto-saves to sessionStorage
              } else if (parsed.thread_id !== this.threadId) {
                console.warn('Backend returned unexpected thread_id:', parsed.thread_id)
              }
              continue
            }

            // Capture question_answer_id for feedback
            if (parsed.question_answer_id) {
              this.messages[responseIndex].questionAnswerId = parsed.question_answer_id
              continue
            }

            if (parsed.choices && parsed.choices[0]?.delta?.content) {
              const content = parsed.choices[0].delta.content
              this.messages[responseIndex].content += content

              this.$nextTick(() => {
                const container = this.$refs.messagesContainer
                if (container) {
                  const isNearBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 100
                  if (isNearBottom) {
                    container.scrollTop = container.scrollHeight
                  }
                }
              })
            }
          } catch (e) {
            console.error('Failed to parse SSE data:', e)
          }
        }
      }

      this.messages[responseIndex].isStreaming = false
    },

    clearChat() {
      if (confirm('Clear all messages?')) {
        this.messages = []      // $persist auto-saves empty array
        this.threadId = null    // $persist auto-removes from sessionStorage
        this.error = null
      }
    },

    formatMessageContent(content) {
      return this.$markdown(content)
    },

    async submitFeedback(messageIndex, feedbackType) {
      const message = this.messages[messageIndex]

      if (message.feedback === feedbackType) {
        return
      }

      // Clear any previous error
      message.feedbackError = null

      if (!message.questionAnswerId) {
        message.feedbackError = 'Unable to submit feedback'
        console.error('No question_answer_id available for feedback')
        return
      }

      try {
        const response = await fetch(window.GORDON_BASE_URL + '/feedback', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            id: message.questionAnswerId,
            feedback: feedbackType
          })
        })

        if (response.ok) {
          message.feedback = feedbackType  // $persist auto-saves
        } else {
          message.feedbackError = 'Unable to submit feedback'
          console.error('Failed to submit feedback:', response.status, response.statusText)
        }
      } catch (err) {
        message.feedbackError = 'Unable to submit feedback'
        console.error('Error submitting feedback:', err)
      }
    },

    async copyAnswer(messageIndex) {
      const message = this.messages[messageIndex]
      if (!message.content) return

      try {
        await navigator.clipboard.writeText(message.content)
        message.copied = true
        this.$nextTick(() => {
          setTimeout(() => {
            message.copied = false
          }, 2000)
        })
      } catch (err) {
        console.error('Failed to copy:', err)
      }
    }
  }"
  x-cloak
  @keydown.escape.window="$store.gordon.close()"
>
  <!-- Overlay backdrop -->
  <div
    x-show="$store.gordon.isOpen"
    x-transition.opacity.duration.300ms
    @click="$store.gordon.close()"
    class="fixed inset-0 z-40 bg-black/50"
  ></div>

  <!-- Chat panel sliding in from right -->
  <div
    id="gordon-chat"
    x-show="$store.gordon.isOpen"
    x-transition:enter="transition ease-out duration-200"
    x-transition:enter-start="translate-x-full"
    x-transition:enter-end="translate-x-0"
    x-transition:leave="transition ease-in duration-200"
    x-transition:leave-start="translate-x-0"
    x-transition:leave-end="translate-x-full"
    class="fixed top-0 right-0 z-50 flex h-screen w-full flex-col overflow-hidden rounded-lg bg-white shadow-2xl transition-all duration-200 md:top-2 md:right-2 md:h-[calc(100vh-1rem)] md:w-[min(80ch,90vw)] dark:bg-gray-900"
  >
    <!-- Header -->
    <div
      class="flex items-center justify-between rounded-t-lg border-b border-gray-200 bg-blue-600 px-6 py-3 dark:border-gray-700"
    >
      <div class="flex items-center gap-3">
        {{ partial "utils/svg.html" "images/gordon-logo.svg" }}
      </div>
      <div class="flex items-center gap-2">
        <button
          @click="clearChat()"
          title="Clear chat"
          class="cursor-pointer rounded p-2 text-white/80 transition-colors hover:bg-blue-500 hover:text-white"
          :disabled="messages.length === 0"
          :class="{ 'opacity-50 cursor-not-allowed': messages.length === 0 }"
        >
          <span class="icon-svg">
            {{ partialCached "icon" "refresh" "refresh" }}
          </span>
        </button>
        <button
          @click="$store.gordon.close()"
          class="cursor-pointer rounded p-2 text-white/80 transition-colors hover:bg-blue-500 hover:text-white"
          title="Close chat"
          aria-label="Close chat"
        >
          <span class="icon-svg">
            {{ partialCached "icon" "close" "close" }}
          </span>
        </button>
      </div>
    </div>

    <!-- Messages container -->
    <div
      x-ref="messagesContainer"
      class="flex-1 space-y-4 p-6"
      :class="{ 'overflow-y-auto': messages.length > 0 }"
    >
      <!-- Welcome message when empty -->
      <template x-if="messages.length === 0">
        <div
          class="flex h-full flex-col items-center justify-center text-center"
        >
          <div class="mb-4 rounded-full bg-blue-100 p-4 dark:bg-blue-900">
            <span class="icon-svg text-blue-600 dark:text-blue-400">
              {{ partialCached "icon" "icons/sparkle.svg" "icons/sparkle.svg" }}
            </span>
          </div>
          <h3 class="mb-2 text-xl font-semibold text-gray-900 dark:text-white">
            Ask me about Docker
          </h3>
          <p class="max-w-sm text-gray-600 dark:text-gray-400">
            Get instant answers to your Docker questions. I can help with
            commands, concepts, troubleshooting, and best practices.
          </p>
          <div class="mt-8 flex flex-col items-center gap-3 text-sm">
            <p class="mb-1 text-gray-500 dark:text-gray-400">Try asking:</p>
            <button
              @click="currentQuestion = 'How do Docker Hardened Images work?'; askQuestion()"
              class="cursor-pointer rounded-lg border border-gray-200 bg-gray-50 px-4 py-2.5 text-gray-700 transition-opacity hover:opacity-70 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300"
            >
			  How do Docker Hardened Images work?
            </button>
            <button
              @click="currentQuestion = 'What is MCP Toolkit?'; askQuestion()"
              class="cursor-pointer rounded-lg border border-gray-200 bg-gray-50 px-4 py-2.5 text-gray-700 transition-opacity hover:opacity-70 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300"
            >
			  What is MCP Toolkit?
            </button>
            <button
              @click="currentQuestion = 'How do I create an org?'; askQuestion()"
              class="cursor-pointer rounded-lg border border-gray-200 bg-gray-50 px-4 py-2.5 text-gray-700 transition-opacity hover:opacity-70 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300"
            >
              How do I create an org?
            </button>
          </div>
        </div>
      </template>

      <!-- Messages -->
      <template x-for="(message, index) in messages" :key="index">
        <div
          :class="message.role === 'user' ? 'flex justify-end' : 'flex justify-start'"
        >
          <div class="flex max-w-full flex-col gap-2">
            <div
              :class="message.role === 'user' ? 'bg-blue-500 dark:bg-blue-800 text-white' : 'max-w-none bg-gray-100 dark:bg-gray-800'"
              class="prose prose-sm dark:prose-invert rounded-lg px-4"
            >
              <template x-if="!message.content && message.isStreaming">
                <div class="flex gap-1 py-3">
                  <span
                    class="inline-block h-2 w-2 animate-bounce rounded-full bg-current"
                    style="animation-delay: 0ms"
                  ></span>
                  <span
                    class="inline-block h-2 w-2 animate-bounce rounded-full bg-current"
                    style="animation-delay: 150ms"
                  ></span>
                  <span
                    class="inline-block h-2 w-2 animate-bounce rounded-full bg-current"
                    style="animation-delay: 300ms"
                  ></span>
                </div>
              </template>
              <template x-if="message.content">
                <div x-html="formatMessageContent(message.content)"></div>
              </template>
            </div>
            <!-- Feedback buttons for assistant messages -->
            <template
              x-if="message.role === 'assistant' && !message.isStreaming"
            >
              <div class="flex flex-col gap-2">
                <div class="flex items-center gap-3 text-xs">
                  <!-- "Was this helpful?" prompt with sparkle icon -->
                  <div class="flex items-center gap-1.5 text-gray-600 dark:text-gray-400">
                    <span class="icon-svg icon-xs text-blue-500 dark:text-blue-400">
                      {{ partialCached "icon" "icons/sparkle.svg" "icons/sparkle.svg" }}
                    </span>
                    <span class="font-medium">Was this helpful?</span>
                  </div>

                  <!-- Feedback buttons group -->
                  <div class="flex items-center gap-2">
                    <!-- Thumbs up - Helpful -->
                    <button
                      @click="submitFeedback(index, 'positive')"
                      :class="message.feedback === 'positive'
                        ? 'bg-green-100 text-green-700 ring ring-green-500 dark:bg-green-900/50 dark:text-green-400 dark:ring-green-600'
                        : 'bg-gray-100 text-gray-600 hover:bg-green-50 hover:text-green-600 hover:ring hover:ring-green dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-green-900/30 dark:hover:text-green-400 dark:hover:ring-green'"
                      class="cursor-pointer rounded-full px-3 py-1.5 transition-all duration-200 flex items-center gap-1.5"
                      title="Helpful"
                    >
                      <span class="icon-svg icon-sm transition-transform">
                        {{ partialCached "icon" "thumb_up" "thumb_up" }}
                      </span>
                      <span class="hidden sm:inline font-medium">Helpful</span>
                    </button>

                    <!-- Thumbs down - Not quite -->
                    <button
                      @click="submitFeedback(index, 'negative')"
                      :class="message.feedback === 'negative'
                        ? 'bg-red-100 text-red-700 ring ring-red-500 dark:bg-red-900/50 dark:text-red-400 dark:ring-red-600'
                        : 'bg-gray-100 text-gray-600 hover:bg-red-50 hover:text-red-600 hover:ring hover:ring-red dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-red-900/30 dark:hover:text-red-400 dark:hover:ring-red'"
                      class="cursor-pointer rounded-full px-3 py-1.5 transition-all duration-200 flex items-center gap-1.5"
                      title="Not quite"
                    >
                      <span class="icon-svg icon-sm transition-transform">
                        {{ partialCached "icon" "thumb_down" "thumb_down" }}
                      </span>
                      <span class="hidden sm:inline font-medium">Not quite</span>
                    </button>
                  </div>

                  <!-- Separator -->
                  <div class="h-4 w-px bg-gray-300 dark:bg-gray-600"></div>

                  <!-- Copy button -->
                  <button
                    @click="copyAnswer(index)"
                    class="cursor-pointer rounded-full px-3 py-1.5 transition-all duration-200 flex items-center gap-1.5 bg-gray-100 text-gray-600 hover:bg-blue-50 hover:text-blue-700 hover:ring hover:ring-blue dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-blue-900/30 dark:hover:text-blue-300 dark:hover:ring-blue-400"
                    :title="message.copied ? 'Copied!' : 'Copy answer'"
                  >
                    <span
                      x-show="message.copied !== true"
                      class="icon-svg icon-sm"
                    >
                      {{ partialCached "icon" "content_copy" "content_copy" }}
                    </span>
                    <span
                      x-show="message.copied === true"
                      class="icon-svg icon-sm"
                    >
                      {{ partialCached "icon" "check_circle" "check_circle" }}
                    </span>
                    <span class="hidden sm:inline font-medium">Copy</span>
                  </button>
                </div>

                <!-- Error message -->
                <template x-if="message.feedbackError">
                  <div
                    x-transition:enter="transition ease-out duration-200"
                    x-transition:enter-start="opacity-0 translate-y-1"
                    x-transition:enter-end="opacity-100 translate-y-0"
                    class="flex items-center gap-1.5 text-xs text-red-600 dark:text-red-400"
                  >
                    <span x-text="message.feedbackError"></span>
                  </div>
                </template>
              </div>
            </template>
          </div>
        </div>
      </template>

      <!-- Error message -->
      <template x-if="error">
        <div
          class="rounded-lg border border-red-200 bg-red-50 p-4 text-red-800 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400"
        >
          <p class="text-sm" x-text="error"></p>
        </div>
      </template>

      <!-- Countdown warning when approaching limit -->
      <template x-if="shouldShowCountdown()">
        <div
          class="rounded-lg border border-yellow-200 bg-yellow-50 p-3 text-yellow-800 dark:border-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-400"
        >
          <p class="text-sm">
            <span x-text="getRemainingTurns()"></span>
            <span
              x-text="getRemainingTurns() === 1 ? 'question' : 'questions'"
            ></span>
            remaining in this thread.
          </p>
        </div>
      </template>

      <!-- Thread limit warning -->
      <template x-if="isThreadLimitReached()">
        <div
          class="rounded-lg border border-blue-200 bg-blue-50 p-4 text-blue-800 dark:border-blue-800 dark:bg-blue-900/20 dark:text-blue-400"
        >
          <p class="mb-3 text-sm">
            You've reached the maximum of
            <span x-text="maxTurnsPerThread"></span> questions per thread. For
            better answer quality, start a new thread.
          </p>
          <button
            @click="clearChat()"
            class="cursor-pointer rounded-lg bg-blue-600 px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600"
          >
            Start a new thread
          </button>
        </div>
      </template>
    </div>

    <!-- Input area -->
    <div class="border-t border-gray-200 p-4 dark:border-gray-700">
      <form @submit.prevent="askQuestion()" class="space-y-2">
        <div class="flex items-center gap-2">
          <div class="relative flex-1 self-stretch">
            <textarea
              x-ref="input"
              x-model="currentQuestion"
              @input="$el.style.height = 'auto'; $el.style.height = $el.scrollHeight + 'px'"
              @keydown.enter="if (!$event.shiftKey) { $event.preventDefault(); askQuestion() }"
              placeholder="Ask a question about Docker..."
              rows="1"
              :disabled="isLoading || isThreadLimitReached()"
              class="block min-h-[3rem] w-full resize-none rounded-lg border border-gray-300 p-3 leading-normal focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 focus:outline-none disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-white dark:focus:border-blue-400"
              :class="{ 'cursor-not-allowed': isThreadLimitReached() }"
            ></textarea>
          </div>
          <button
            type="submit"
            :disabled="!currentQuestion.trim() || isLoading || isThreadLimitReached()"
            :title="isLoading ? 'Sending...' : (isThreadLimitReached() ? 'Thread limit reached. Start a new thread.' : 'Send question')"
            class="cursor-pointer rounded-lg bg-blue-600 px-4 py-3 font-semibold text-white transition-colors hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50"
          >
            <template x-if="!isLoading">
              <span class="icon-svg">
                {{ partialCached "icon" "send" "send" }}
              </span>
            </template>
            <template x-if="isLoading">
              <span class="icon-svg animate-spin">
                {{ partialCached "icon" "progress_activity" "progress_activity" }}
              </span>
            </template>
          </button>
        </div>
        <div class="flex items-center justify-between" x-data="{ showTooltip: false }">
          <div class="relative">
            <!-- Tooltip -->
            <div
              x-show="showTooltip"
              x-transition:enter="transition ease-out duration-100"
              x-transition:enter-start="opacity-0 scale-95"
              x-transition:enter-end="opacity-100 scale-100"
              x-transition:leave="transition ease-in duration-75"
              x-transition:leave-start="opacity-100 scale-100"
              x-transition:leave-end="opacity-0 scale-95"
              class="absolute bottom-full left-0 mb-2 w-56 rounded-lg bg-gray-900 p-2.5 text-xs text-white shadow-lg dark:bg-gray-700"
              style="display: none;"
            >
              <div class="relative">
                <p>
                  When enabled, Gordon considers the current page you're viewing
                  to provide more relevant answers.
                </p>
                <!-- Arrow -->
                <div
                  class="absolute -bottom-3 left-4 h-2 w-2 rotate-45 bg-gray-900 dark:bg-gray-700"
                ></div>
              </div>
            </div>
          </div>
          <a
            href="https://github.com/docker/docs/issues/23966"
            target="_blank"
            rel="noopener noreferrer"
            class="text-xs text-gray-500 underline hover:text-blue-600 dark:text-gray-400 dark:hover:text-blue-400"
          >
            Share feedback
          </a>
        </div>
      </form>
    </div>

    <!-- Disclaimer -->
    <div
      class="rounded-b-lg border-t border-gray-200 bg-blue-50 px-4 py-3 text-xs text-gray-600 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400"
    >
      Answers are generated based on the documentation.
    </div>
  </div>
</div>

<!-- Styles for Gordon chat -->
<style>
  /* Code block styles */
  #gordon-chat pre {
    background: #0d1117;
    border-radius: 0.25rem;
    padding: 0;
    margin: 0.5rem 0;
    overflow-x: auto;
    white-space: pre;
  }

  #gordon-chat pre code {
    background: #0d1117;
    color: #c9d1d9;
    padding: 1rem;
    display: block;
    font-family: "Roboto Mono", monospace;
    font-size: 0.875rem;
    line-height: 1.5;
    white-space: pre;
    overflow-x: auto;
  }

  #gordon-chat pre code * {
    white-space: pre;
  }

  /* Inline code styling (not in pre blocks) */
  #gordon-chat .prose code.not-prose {
    background-color: rgb(229 231 235);
    color: rgb(17 24 39);
    padding: 0.2em 0.4em;
    border-radius: 0.25rem;
    font-family: "Roboto Mono", monospace;
    font-size: 0.875em;
  }

  .dark #gordon-chat .prose code.not-prose {
    background-color: rgb(55 65 81);
    color: rgb(229 231 235);
  }
</style>
