<script setup lang="ts">
import { computed, onBeforeUnmount, ref } from "vue";
import { useRouter } from "vue-router";

import type { MarketEntity } from "../api/market";
import MarketPreviewPanel from "./MarketPreviewPanel.vue";

const props = defineProps<{ entity: MarketEntity; label?: string }>();
const router = useRouter();
const anchor = ref<HTMLElement | null>(null);
const visible = ref(false);
const position = ref({ left: 0, top: 0 });
let timer: ReturnType<typeof setTimeout> | undefined;
const text = computed(() => props.label ?? props.entity.code);

function show(): void {
  if (matchMedia("(hover: none)").matches) return;
  if (timer) clearTimeout(timer);
  const rect = anchor.value?.getBoundingClientRect();
  if (!rect) return;
  const width = Math.min(480, window.innerWidth - 32);
  const height = 360;
  position.value = {
    left: Math.max(16, Math.min(rect.left, window.innerWidth - width - 16)),
    top: rect.bottom + height + 12 <= window.innerHeight
      ? rect.bottom + 8
      : Math.max(8, rect.top - height - 8),
  };
  visible.value = true;
}

function scheduleClose(): void {
  if (timer) clearTimeout(timer);
  timer = setTimeout(() => { visible.value = false; }, 180);
}

function openDetail(): void {
  visible.value = false;
  void router.push({
    name: "entity-detail",
    params: { entityType: props.entity.entity_type, identifier: props.entity.identifier },
    query: { code: props.entity.code, name: props.entity.name, sector: props.entity.sector ?? undefined },
  });
}

onBeforeUnmount(() => timer && clearTimeout(timer));
</script>

<template>
  <button ref="anchor" class="market-entity-link" type="button" @mouseenter="show" @mouseleave="scheduleClose" @focus="show" @blur="scheduleClose" @click="openDetail">{{ text }}</button>
  <Teleport to="body">
    <div v-if="visible" class="market-hover-popover" :style="{ left: `${position.left}px`, top: `${position.top}px` }" @mouseenter="show" @mouseleave="scheduleClose">
      <MarketPreviewPanel :entity="entity" />
    </div>
  </Teleport>
</template>
