<script setup>
import { computed } from 'vue'
import { formatDistanceToNow } from 'date-fns'
import { zhCN } from 'date-fns/locale'

import styles from './SearchResultItem.module.scss'
import defaultIcon from '@/assets/images/default.png'

const props = defineProps({
  result: {
    type: Object,
    required: true,
  },
  active: {
    type: Boolean,
    default: false,
  },
})

const emit = defineEmits(['select'])

const link = computed(() => props.result.link)

function buildSegments(text, ranges = []) {
  if (!text) return []
  if (!ranges || ranges.length === 0) return [{ value: text, highlight: false }]
  const segments = []
  let cursor = 0
  ranges.forEach(([start, end]) => {
    if (start > cursor) {
      segments.push({ value: text.slice(cursor, start), highlight: false })
    }
    segments.push({ value: text.slice(start, end + 1), highlight: true })
    cursor = end + 1
  })
  if (cursor < text.length) {
    segments.push({ value: text.slice(cursor), highlight: false })
  }
  return segments
}

const titleSegments = computed(() => buildSegments(link.value.title, props.result.highlights.title))
const descriptionSegments = computed(() =>
  buildSegments(link.value.description ?? '', props.result.highlights.description)
)
const urlSegments = computed(() => buildSegments(link.value.url, props.result.highlights.url))

const tagHighlights = computed(() => {
  const ranges = props.result.highlights.tags ?? []
  const tags = Array.isArray(link.value.tags) ? link.value.tags : []
  if (!ranges.length) {
    return tags.map((tag) => ({ tag, highlight: false }))
  }

  const highlightSet = new Set()
  const tagsJoined = tags.join(' ')

  ranges.forEach(([start, end]) => {
    const matched = tagsJoined.slice(start, end + 1).toLowerCase()
    tags.forEach((tag) => {
      if (matched && tag.toLowerCase().includes(matched)) {
        highlightSet.add(tag)
      }
    })
  })

  return tags.map((tag) => ({
    tag,
    highlight: highlightSet.has(tag),
  }))
})

const faviconUrl = computed(() => {
  if (link.value.icon) return link.value.icon
  if (!link.value.url) return defaultIcon
  try {
    const { origin } = new URL(link.value.url)
    return `https://t2.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=${encodeURIComponent(
      origin
    )}&size=32`
  } catch {
    return defaultIcon
  }
})

const fallbackInitial = computed(() => {
  if (link.value.title) {
    const first = link.value.title.trim()[0]
    return first ? first.toUpperCase() : 'B'
  }
  return 'B'
})

const visitMeta = computed(() => {
  const count = link.value.visitCount ?? 0
  if (count === 0) return '尚未访问'
  const lastVisit = link.value.lastVisitTime
  if (!lastVisit) return `共 ${count} 次访问`
  const distance = formatDistanceToNow(new Date(lastVisit), { addSuffix: true, locale: zhCN })
  return `共 ${count} 次访问 · ${distance}`
})

function handleSelect() {
  emit('select', link.value)
}
</script>

<template>
  <li
    :class="[styles.item, { [styles.itemActive]: active }]"
    role="option"
    :aria-selected="active"
    @click="handleSelect"
  >
    <div :class="styles.icon" aria-hidden="true">
      <img v-if="faviconUrl" :src="faviconUrl" alt="" />
      <span v-else>{{ fallbackInitial }}</span>
    </div>

    <div :class="styles.content">
      <div :class="styles.titleRow">
        <h3 :class="styles.title">
          <template v-for="(segment, index) in titleSegments" :key="index">
            <span v-if="segment.highlight" :class="styles.highlight">{{ segment.value }}</span>
            <template v-else>{{ segment.value }}</template>
          </template>
        </h3>
      </div>

      <p v-if="link.description" :class="styles.description">
        <template v-for="(segment, index) in descriptionSegments" :key="index">
          <span v-if="segment.highlight" :class="styles.highlight">{{ segment.value }}</span>
          <template v-else>{{ segment.value }}</template>
        </template>
      </p>

      <div v-if="link.tags?.length" :class="styles.tags">
        <span
          v-for="({ tag, highlight }, index) in tagHighlights"
          :key="tag + index"
          :class="[styles.tag, { [styles.highlight]: highlight }]"
        >
          {{ tag }}
        </span>
      </div>

      <div :class="styles.meta">
        <span :class="styles.url">
          <template v-for="(segment, index) in urlSegments" :key="index">
            <span v-if="segment.highlight" :class="styles.highlight">{{ segment.value }}</span>
            <template v-else>{{ segment.value }}</template>
          </template>
        </span>
        <span>{{ visitMeta }}</span>
      </div>
    </div>
  </li>
</template>

