<script setup lang="ts">
import type { Message } from '@/stores/chat';
import { computed, ref } from 'vue';
import MarkdownRenderer from './MarkdownRenderer.vue';

const props = defineProps<{ message: Message }>()

const isSystem = computed(() => props.message.role === 'system')
const toolExpanded = ref(false)

const timeStr = computed(() => {
  const d = new Date(props.message.timestamp)
  return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
})

function isImage(type: string): boolean {
  return type.startsWith('image/')
}

function formatSize(bytes: number): string {
  if (bytes < 1024) return bytes + ' B'
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
}

const hasAttachments = computed(() => (props.message.attachments?.length ?? 0) > 0)

const hasToolDetails = computed(() => !!(props.message.toolArgs || props.message.toolResult))

const formattedToolArgs = computed(() => {
  if (!props.message.toolArgs) return ''
  try {
    return JSON.stringify(JSON.parse(props.message.toolArgs), null, 2)
  } catch {
    return props.message.toolArgs
  }
})

const formattedToolResult = computed(() => {
  if (!props.message.toolResult) return ''
  try {
    const parsed = JSON.parse(props.message.toolResult)
    const str = JSON.stringify(parsed, null, 2)
    // Truncate very long output
    if (str.length > 2000) return str.slice(0, 2000) + '\n... (truncated)'
    return str
  } catch {
    const raw = props.message.toolResult
    if (raw.length > 2000) return raw.slice(0, 2000) + '\n... (truncated)'
    return raw
  }
})
</script>

<template>
  <div class="message" :class="[message.role]">
    <template v-if="message.role === 'tool'">
      <div class="tool-line" :class="{ expandable: hasToolDetails }" @click="hasToolDetails && (toolExpanded = !toolExpanded)">
        <svg v-if="hasToolDetails" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="tool-chevron" :class="{ rotated: toolExpanded }"><polyline points="9 18 15 12 9 6"/></svg>
        <svg v-else width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="tool-icon"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>
        <span class="tool-name">{{ message.toolName }}</span>
        <span v-if="message.toolPreview && !toolExpanded" class="tool-preview">{{ message.toolPreview }}</span>
        <span v-if="message.toolStatus === 'running'" class="tool-spinner"></span>
        <span v-if="message.toolStatus === 'error'" class="tool-error-badge">error</span>
      </div>
      <div v-if="toolExpanded && hasToolDetails" class="tool-details">
        <div v-if="formattedToolArgs" class="tool-detail-section">
          <div class="tool-detail-label">Arguments</div>
          <pre class="tool-detail-code">{{ formattedToolArgs }}</pre>
        </div>
        <div v-if="formattedToolResult" class="tool-detail-section">
          <div class="tool-detail-label">Result</div>
          <pre class="tool-detail-code">{{ formattedToolResult }}</pre>
        </div>
      </div>
    </template>
    <template v-else>
      <div class="msg-body">
        <img v-if="message.role === 'assistant'" src="/assets/logo.png" alt="Hermes" class="msg-avatar" />
        <div class="msg-content" :class="message.role">
          <div class="message-bubble" :class="{ system: isSystem }">
            <div v-if="hasAttachments" class="msg-attachments">
              <div
                v-for="att in message.attachments"
                :key="att.id"
                class="msg-attachment"
                :class="{ image: isImage(att.type) }"
              >
                <template v-if="isImage(att.type) && att.url">
                  <img :src="att.url" :alt="att.name" class="msg-attachment-thumb" />
                </template>
                <template v-else>
                  <div class="msg-attachment-file">
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
                    <span class="att-name">{{ att.name }}</span>
                    <span class="att-size">{{ formatSize(att.size) }}</span>
                  </div>
                </template>
              </div>
            </div>
            <MarkdownRenderer v-if="message.content" :content="message.content" />
            <span v-if="message.isStreaming" class="streaming-cursor"></span>
            <div v-if="message.isStreaming && !message.content" class="streaming-dots">
              <span></span><span></span><span></span>
            </div>
          </div>
          <div class="message-time">{{ timeStr }}</div>
        </div>
      </div>
    </template>
  </div>
</template>

<style scoped lang="scss">
@use '@/styles/variables' as *;

.message {
  display: flex;
  flex-direction: column;

  &.user {
    align-items: flex-end;

    .msg-body {
      max-width: 75%;
    }

    .msg-content.user {
      align-items: flex-end;
    }

    .message-bubble {
      background-color: $msg-user-bg;
      border-radius: $radius-md $radius-md 4px $radius-md;
    }
  }

  &.assistant {
    flex-direction: row;
    align-items: flex-start;
    gap: 8px;

    .msg-body {
      max-width: 80%;
    }

    .msg-avatar {
      width: 28px;
      height: 28px;
      border-radius: 4px;
      flex-shrink: 0;
      margin-top: 2px;
    }

    .message-bubble {
      background-color: $msg-assistant-bg;
      border-radius: $radius-md $radius-md $radius-md 4px;
    }
  }

  &.tool {
    align-items: flex-start;
  }

  &.system {
    align-items: flex-start;

    .message-bubble.system {
      border-left: 3px solid $warning;
      border-radius: $radius-sm;
      max-width: 80%;
      background-color: rgba($warning, 0.06);
    }
  }
}

.msg-body {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  max-width: 85%;
}

.msg-content {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.message-bubble {
  padding: 10px 14px;
  font-size: 14px;
  line-height: 1.65;
  word-break: break-word;
}

.msg-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}

.msg-attachment {
  border-radius: $radius-sm;
  overflow: hidden;
  background-color: rgba(0, 0, 0, 0.04);
  border: 1px solid $border-light;

  &.image {
    max-width: 200px;
  }
}

.msg-attachment-thumb {
  display: block;
  max-width: 200px;
  max-height: 160px;
  object-fit: contain;
}

.msg-attachment-file {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  font-size: 12px;
  color: $text-secondary;

  .att-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 160px;
  }

  .att-size {
    color: $text-muted;
    font-size: 11px;
    flex-shrink: 0;
  }
}

.message-time {
  font-size: 11px;
  color: $text-muted;
  margin-top: 4px;
  padding: 0 4px;
}

.tool-line {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: $text-muted;
  padding: 2px 4px;
  border-radius: $radius-sm;

  &.expandable {
    cursor: pointer;

    &:hover {
      background: rgba(0, 0, 0, 0.03);
    }
  }

  .tool-name {
    font-family: $font-code;
    flex-shrink: 0;
  }

  .tool-preview {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 400px;
  }
}

.tool-chevron {
  flex-shrink: 0;
  transition: transform 0.15s ease;

  &.rotated {
    transform: rotate(90deg);
  }
}

.tool-spinner {
  width: 10px;
  height: 10px;
  border: 1.5px solid $text-muted;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
  flex-shrink: 0;
}

.tool-error-badge {
  font-size: 9px;
  color: $error;
  background: rgba($error, 0.08);
  padding: 0 4px;
  border-radius: 3px;
  line-height: 14px;
}

.tool-details {
  margin-left: 16px;
  margin-top: 2px;
  border-left: 2px solid $border-light;
  padding-left: 10px;
}

.tool-detail-section {
  margin-bottom: 6px;
}

.tool-detail-label {
  font-size: 10px;
  font-weight: 600;
  color: $text-muted;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  margin-bottom: 2px;
}

.tool-detail-code {
  font-family: $font-code;
  font-size: 11px;
  line-height: 1.5;
  color: $text-secondary;
  background: $code-bg;
  border-radius: $radius-sm;
  padding: 6px 8px;
  margin: 0;
  overflow-x: auto;
  max-height: 300px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-all;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.streaming-cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  background-color: $text-muted;
  margin-left: 2px;
  vertical-align: text-bottom;
  animation: blink 0.8s infinite;
}

.streaming-dots {
  display: flex;
  gap: 4px;
  padding: 4px 0;

  span {
    width: 6px;
    height: 6px;
    background-color: $text-muted;
    border-radius: 50%;
    animation: pulse 1.4s infinite ease-in-out;

    &:nth-child(2) { animation-delay: 0.2s; }
    &:nth-child(3) { animation-delay: 0.4s; }
  }
}

@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}

@keyframes pulse {
  0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); }
  40% { opacity: 1; transform: scale(1); }
}
</style>
