<template>
  <component
    :is="linkable ? NuxtLink : 'div'"
    :to="linkable ? resolvedLink : undefined"
    class="block"
    :class="{ 'cursor-pointer': selectable }"
    @click="selectable && $emit('select')"
    @mouseenter="$emit('hover', true)"
    @mouseleave="$emit('hover', false)"
  >
    <Card
      padding="small"
      :interactive="linkable || selectable"
      :class="[
        isSelected && 'ring-2 ring-primary ring-offset-2'
      ]"
    >
      <div class="flex flex-col gap-1">
        <!-- Title + distance/compass -->
        <div class="flex items-start justify-between gap-2">
          <Text size="base" weight="semibold" class="truncate">{{ hub.name }}</Text>
          <div class="flex items-center gap-2 text-xs text-base-content/60 whitespace-nowrap">
            <Text v-if="distanceLabel" size="xs" class="text-base-content/60">{{ distanceLabel }}</Text>
            <div v-if="bearing !== null" class="flex items-center gap-1">
              <div class="w-6 h-6 rounded-full border border-base-content/10 bg-base-200/40 flex items-center justify-center">
                <Icon
                  name="lucide:arrow-up"
                  size="12"
                  class="text-base-content/60"
                  :style="{ transform: `rotate(${bearing}deg)` }"
                />
              </div>
            </div>
          </div>
        </div>
        <!-- Country -->
        <div class="flex items-center justify-between">
          <Text tone="muted" size="sm">
            {{ countryFlag }} {{ hub.country || t('catalogMap.labels.country_unknown') }}
          </Text>
        </div>
        <!-- Transport icons bottom -->
        <div v-if="hub.transport_types?.length" class="flex items-center gap-1 pt-1">
          <Icon v-if="hasTransport('auto')" name="lucide:truck" size="14" class="text-base-content/50" />
          <Icon v-if="hasTransport('rail')" name="lucide:train-front" size="14" class="text-base-content/50" />
          <Icon v-if="hasTransport('sea')" name="lucide:ship" size="14" class="text-base-content/50" />
          <Icon v-if="hasTransport('air')" name="lucide:plane" size="14" class="text-base-content/50" />
        </div>
      </div>
    </Card>
  </component>
</template>

<script setup lang="ts">
import { NuxtLink } from '#components'

interface Hub {
  uuid?: string | null
  name?: string | null
  country?: string | null
  country_code?: string | null
  latitude?: number | null
  longitude?: number | null
  distance?: string
  distance_km?: number | null
  transport_types?: (string | null)[] | null
}

const props = defineProps<{
  hub: Hub
  origin?: { latitude: number; longitude: number } | null
  selectable?: boolean
  isSelected?: boolean
  linkTo?: string
}>()

defineEmits<{
  (e: 'select'): void
  (e: 'hover', hovered: boolean): void
}>()

const localePath = useLocalePath()
const { t } = useI18n()

const linkable = computed(() => !props.selectable && !!(props.linkTo || props.hub.uuid))
const resolvedLink = computed(() => props.linkTo || localePath(`/catalog/hubs/${props.hub.uuid}`))

// ISO code to emoji flag
const isoToEmoji = (code: string): string => {
  return code.toUpperCase().split('').map(char => String.fromCodePoint(0x1F1E6 - 65 + char.charCodeAt(0))).join('')
}

const countryFlag = computed(() => {
  if (props.hub.country_code) {
    return isoToEmoji(props.hub.country_code)
  }
  return '🌍'
})

const hasTransport = (type: string) => props.hub.transport_types?.some(t => t === type)
const distanceLabel = computed(() => {
  if (props.hub.distance) return props.hub.distance
  if (props.hub.distance_km != null) return `${Math.round(props.hub.distance_km)} km`
  return ''
})

const toRadians = (deg: number) => (deg * Math.PI) / 180
const toDegrees = (rad: number) => (rad * 180) / Math.PI

const bearing = computed(() => {
  const origin = props.origin
  const lat2 = props.hub.latitude
  const lon2 = props.hub.longitude
  if (!origin || lat2 == null || lon2 == null) return null
  const lat1 = origin.latitude
  const lon1 = origin.longitude
  if (lat1 == null || lon1 == null) return null

  const φ1 = toRadians(lat1)
  const φ2 = toRadians(lat2)
  const Δλ = toRadians(lon2 - lon1)

  const y = Math.sin(Δλ) * Math.cos(φ2)
  const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(Δλ)
  const θ = Math.atan2(y, x)
  const deg = (toDegrees(θ) + 360) % 360
  return deg
})
</script>
