<template>
  <div class="pipe-log">
    <div class="pipe-log__toolbar">
      <div class="pipe-log__status">
        <span class="pipe-log__status-dot" :class="statusClass"></span>
        <span class="pipe-log__toolbar-text">{{ pipeStore.statusText }}</span>
        <span class="pipe-log__count">{{ pipeStore.logs.length }} lines</span>
      </div>
      <el-button class="pipe-log__clear" text size="small" @click="pipeStore.clear()">
        Clear
      </el-button>
    </div>

    <div ref="listRef" class="pipe-log__terminal" role="log" aria-live="polite">
      <div v-if="!pipeStore.logs.length" class="pipe-log__empty">
        <span class="pipe-log__prompt">$</span>
        <span class="pipe-log__empty-text">Waiting for pipe events…</span>
      </div>

      <template v-for="item in pipeStore.logs" :key="item.id">
        <div class="pipe-log__line" :class="[`is-${item.level}`]">
          <span class="pipe-log__prompt" aria-hidden="true">$</span>
          <span class="pipe-log__ts">[{{ formatTime(item.timestamp) }}]</span>
          <span class="pipe-log__dir" :class="`dir-${item.direction}`">{{
            padDirection(getDirectionLabel(item.direction))
          }}</span>
          <span class="pipe-log__cat">{{ padCategory(getCategoryLabel(item.category)) }}</span>
          <span v-if="item.msgId !== undefined" class="pipe-log__msgid">
            {{ item.msgName || 'UNKNOWN' }}/0x{{
              item.msgId.toString(16).toUpperCase().padStart(4, '0')
            }}
          </span>
          <span class="pipe-log__body">{{ item.message }}</span>
        </div>
        <pre v-if="item.detail" class="pipe-log__detail">{{ item.detail }}</pre>
      </template>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue'
import { usePipeStore } from '@/store/modules/pipe'

const pipeStore = usePipeStore()
const listRef = ref<HTMLDivElement>()

const statusClass = computed(() => {
  if (pipeStore.authenticated) return 'is-authenticated'
  if (pipeStore.connected) return 'is-connected'
  return 'is-idle'
})

watch(
  () => pipeStore.logs.length,
  async () => {
    await nextTick()
    if (listRef.value) {
      listRef.value.scrollTop = listRef.value.scrollHeight
    }
  }
)

function formatTime(timestamp: string) {
  if (!timestamp) return '--:--:--'
  return new Date(timestamp).toLocaleTimeString('en-GB', { hour12: false })
}

function getDirectionLabel(direction: 'system' | 'recv' | 'send') {
  if (direction === 'recv') return 'Recv'
  if (direction === 'send') return 'Send'
  return 'System'
}

function getCategoryLabel(category: 'connection' | 'auth' | 'message') {
  if (category === 'connection') return 'Connection'
  if (category === 'auth') return 'Auth'
  return 'Message'
}

function padDirection(label: string) {
  return label.padEnd(6, ' ')
}

function padCategory(label: string) {
  return label.padEnd(10, ' ')
}
</script>

<style scoped>
.pipe-log {
  --log-term-fg: #c9d1d9;
  --log-term-dim: #6e7681;
  --log-term-border: #30363d;
  --log-term-info: #58a6ff;
  --log-term-success: #3fb950;
  --log-term-warning: #d29922;
  --log-term-error: #f85149;
  --log-term-prompt: #7ee787;
  --log-term-send: #79c0ff;
  --log-term-recv: #ffa657;

  height: 100%;
  display: flex;
  flex-direction: column;

  color: var(--log-term-fg);
  font-family:
    ui-monospace, 'Cascadia Code', 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace;
  font-size: 12px;
  line-height: 1.45;
}

.pipe-log__toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-shrink: 0;
  padding: 8px 12px;
  border-bottom: 1px solid var(--log-term-border);
}

.pipe-log__status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
}

.pipe-log__toolbar-text {
  color: var(--log-term-fg);
}

.pipe-log__status-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: #484f58;
  flex-shrink: 0;
}

.pipe-log__status-dot.is-connected {
  background: var(--log-term-warning);
  box-shadow: 0 0 6px color-mix(in srgb, var(--log-term-warning) 55%, transparent);
}

.pipe-log__status-dot.is-authenticated {
  background: var(--log-term-success);
  box-shadow: 0 0 6px color-mix(in srgb, var(--log-term-success) 45%, transparent);
}

.pipe-log__count {
  color: var(--log-term-dim);
  margin-left: 4px;
}

.pipe-log__clear {
  color: var(--log-term-info) !important;
}

.pipe-log__clear:hover {
  color: #79b8ff !important;
}

.pipe-log__terminal {
  flex: 1;
  overflow: auto;
  padding: 10px 12px 14px;
  min-height: 0;
  tab-size: 2;
}

.pipe-log__terminal::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

.pipe-log__terminal::-webkit-scrollbar-track {
  background: #010409;
}

.pipe-log__terminal::-webkit-scrollbar-thumb {
  background: #484f58;
  border-radius: 5px;
}

.pipe-log__empty {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 100%;
  min-height: 120px;
  padding-left: 4px;
  color: var(--log-term-dim);
}

.pipe-log__empty-text {
  font-style: italic;
}

.pipe-log__line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4em 0.65em;
  margin: 0 0 2px;
  padding: 2px 0;
  border-left: 2px solid transparent;
  padding-left: 6px;
  margin-left: -6px;
}

.pipe-log__line.is-info {
  border-left-color: color-mix(in srgb, var(--log-term-info) 55%, transparent);
}

.pipe-log__line.is-success {
  border-left-color: color-mix(in srgb, var(--log-term-success) 60%, transparent);
}

.pipe-log__line.is-warning {
  border-left-color: color-mix(in srgb, var(--log-term-warning) 65%, transparent);
}

.pipe-log__line.is-error {
  border-left-color: color-mix(in srgb, var(--log-term-error) 70%, transparent);
}

.pipe-log__prompt {
  color: var(--log-term-prompt);
  font-weight: 600;
  user-select: none;
  margin-right: 2px;
}

.pipe-log__ts {
  color: var(--log-term-dim);
  flex-shrink: 0;
}

.pipe-log__dir {
  color: var(--log-term-dim);
  flex-shrink: 0;
  letter-spacing: 0.02em;
}

.pipe-log__dir.dir-send {
  color: var(--log-term-send);
}

.pipe-log__dir.dir-recv {
  color: var(--log-term-recv);
}

.pipe-log__cat {
  color: #a371f7;
  flex-shrink: 0;
}

.pipe-log__msgid {
  color: #8b949e;
  flex-shrink: 0;
}

.pipe-log__body {
  color: var(--log-term-fg);
  word-break: break-word;
  min-width: 0;
}

.pipe-log__line.is-success .pipe-log__body {
  color: #56d364;
}

.pipe-log__line.is-warning .pipe-log__body {
  color: #e3b341;
}

.pipe-log__line.is-error .pipe-log__body {
  color: #ff7b72;
}

.pipe-log__line.is-info .pipe-log__body {
  color: #79c0ff;
}

.pipe-log__detail {
  margin: 0 0 8px 18px;
  padding: 6px 10px;
  white-space: pre-wrap;
  word-break: break-all;
  line-height: 1.5;
  color: #8b949e;
  background: #010409;
  border: 1px solid var(--log-term-border);
  border-radius: 4px;
  font-family: inherit;
  font-size: 11.5px;
}
</style>
