<script setup lang="ts">
import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
import { useFavoritesStore } from '~/stores/favorites'
import { useHistoryStore } from '~/stores/history'
import type { SearchHit } from '~/types'

interface Study {
  id?: number
  title?: string
  date?: string
  place?: string
  link?: string
}

interface EntrelineaDoc {
  id?: string
  image?: string
  link?: string
  locale?: string
  origin?: string
  filter?: string
  page?: number | string
  text?: string
  html?: string
  draft?: boolean
  studies?: Study[]
  [key: string]: unknown
}

const props = defineProps<{
  document: EntrelineaDoc
  collection?: string
  highlightedText?: string | null
  noTrackVisit?: boolean
}>()

const emits = defineEmits<{ close: [] }>()

const showStudies = ref(false)

// Volver al detalle cuando cambia el documento
watch(() => props.document?.id, () => { showStudies.value = false })

const { unlocked } = useDevMode()

const imageUrl = computed<string | null>(() =>
  getEntrelineaImageUrl(props.document?.image, 'detail')
)

const origin = computed(() => (props.document?.origin as string) || '')

const title = computed(() =>
  origin.value || (props.document?.id as string) || 'Entrelínea'
)

function formatEntrelineaText(html: string): string {
  return html;
  if (!html) return ''

  const sPrefix  = "font-family:'Times New Roman',serif;font-style:italic;color:#c00000"
  const sBracket = "font-family:'Times New Roman',serif;font-style:italic;color:#c00000"
  const sInner   = "font-family:'Times New Roman',serif;font-style:italic;color:#c00000;text-decoration:underline"

  const wrapLine = (content: string, isFirst: boolean): string =>
    (isFirst ? `<span style="${sPrefix}">[WSS] </span>` : '') +
    `<span style="${sBracket}">«</span>` +
    `<span style="${sInner}">${content}</span>` +
    `<span style="${sBracket}">»</span>`

  if (/<p[\s>]/i.test(html)) {
    const lines = html
      .split(/<p(?:[^>]*)>/i)
      .map(part => part.replace(/<\/p>/gi, '').trim())
      .filter(Boolean)
    if (lines.length) return lines.map((l, i) => wrapLine(l, i === 0)).join('<br>')
    return html
  }

  if (/<br/i.test(html)) {
    const parts = html.split(/<br\s*\/?>/i).map(p => p.trim()).filter(Boolean)
    if (parts.length) return parts.map((l, i) => wrapLine(l, i === 0)).join('<br>')
  }

  return wrapLine(html.trim(), true)
}

const bodyHtml = computed<string>(() =>
  formatEntrelineaText(props.document?.html || props.document?.text || '')
)

/* -------------------------------------------------------------------------- */
/*  Favoritos / Historial                                                      */
/* -------------------------------------------------------------------------- */

const favorites = useFavoritesStore()
const history = useHistoryStore()
const toast = useToast()

function toSearchHit(doc: EntrelineaDoc): SearchHit {
  const id = doc.id || ''
  return { _id: id, id, title: doc.text?.slice(0, 100) || 'Entrelínea', body: doc.text, ...doc }
}

watch(
  () => [props.collection, props.document?.id] as const,
  ([collection, id]) => {
    if (!collection || !id) return
    if (!props.noTrackVisit) history.visit(collection, toSearchHit(props.document))
  },
  { immediate: true }
)

const isFav = computed(() => {
  if (!props.collection || !props.document?.id) return false
  return favorites.isFavorite(props.collection, props.document.id)
})

function onToggleFavorite() {
  if (!props.collection || !props.document?.id) return
  const wasFav = isFav.value
  favorites.toggle(props.collection, toSearchHit(props.document))
  console.log("text slice", props.document.text?.slice(0, 100))
  toast.add({
    title: 'Entrelínea',
    description: props.document.text?.slice(0, 100) || props.document.id,
    icon: wasFav ? 'i-lucide-bookmark-x' : 'i-lucide-bookmark-check',
    color: wasFav ? 'neutral' : 'primary',
    duration: 1800
  })
}

/* -------------------------------------------------------------------------- */
/*  Desktop hover zoom (lente + panel magnificado)                             */
/* -------------------------------------------------------------------------- */

const zoomBoxRef = ref<HTMLElement | null>(null)
const zoomImgRef = ref<HTMLImageElement | null>(null)
const zoomActive = ref(false)

const cursorX = ref(0)
const cursorY = ref(0)
const imgW = ref(0)
const imgH = ref(0)
const imgOffsetX = ref(0)
const imgOffsetY = ref(0)
const boxRight = ref(0)
const boxLeft = ref(0)
const boxTop = ref(0)

const ZOOM_LEVEL = 2.5
const PANEL_W = 400
const PANEL_H = 400
const LENS_W = PANEL_W / ZOOM_LEVEL
const LENS_H = PANEL_H / ZOOM_LEVEL

function refreshImageRect() {
  if (!zoomImgRef.value || !zoomBoxRef.value) return
  const ir = zoomImgRef.value.getBoundingClientRect()
  const br = zoomBoxRef.value.getBoundingClientRect()
  imgW.value = ir.width
  imgH.value = ir.height
  imgOffsetX.value = ir.left - br.left
  imgOffsetY.value = ir.top - br.top
  boxRight.value = br.right
  boxLeft.value = br.left
  boxTop.value = br.top
}

function onZoomEnter() {
  refreshImageRect()
  zoomActive.value = true
}

function onZoomLeave() {
  zoomActive.value = false
}

function onZoomMove(e: MouseEvent) {
  if (!zoomImgRef.value || !imgW.value) return
  const r = zoomImgRef.value.getBoundingClientRect()
  let x = e.clientX - r.left
  let y = e.clientY - r.top
  x = Math.max(LENS_W / 2, Math.min(imgW.value - LENS_W / 2, x))
  y = Math.max(LENS_H / 2, Math.min(imgH.value - LENS_H / 2, y))
  cursorX.value = x
  cursorY.value = y
}

const lensStyle = computed(() => ({
  left:   `${imgOffsetX.value + cursorX.value - LENS_W / 2}px`,
  top:    `${imgOffsetY.value + cursorY.value - LENS_H / 2}px`,
  width:  `${LENS_W}px`,
  height: `${LENS_H}px`,
}))

const zoomPanelStyle = computed(() => {
  if (!imgW.value) return {}
  const bgX = -(cursorX.value * ZOOM_LEVEL - PANEL_W / 2)
  const bgY = -(cursorY.value * ZOOM_LEVEL - PANEL_H / 2)
  const vw = typeof window !== 'undefined' ? window.innerWidth : 1600
  const left = (boxRight.value + 16 + PANEL_W <= vw)
    ? boxRight.value + 16
    : Math.max(8, boxLeft.value - 16 - PANEL_W)
  return {
    left:               `${left}px`,
    top:                `${boxTop.value}px`,
    width:              `${PANEL_W}px`,
    height:             `${PANEL_H}px`,
    backgroundImage:    `url("${imageUrl.value}")`,
    backgroundSize:     `${imgW.value * ZOOM_LEVEL}px ${imgH.value * ZOOM_LEVEL}px`,
    backgroundPosition: `${bgX}px ${bgY}px`,
    backgroundRepeat:   'no-repeat',
  }
})

watch(imageUrl, () => { setTimeout(refreshImageRect, 50) })

onMounted(() => {
  window.addEventListener('resize', refreshImageRect)
  window.addEventListener('scroll', refreshImageRect, { passive: true })
})

onUnmounted(() => {
  window.removeEventListener('resize', refreshImageRect)
  window.removeEventListener('scroll', refreshImageRect)
})

/* -------------------------------------------------------------------------- */
/*  Mobile lightbox con pinch-to-zoom                                          */
/* -------------------------------------------------------------------------- */

const lightboxOpen = ref(false)
const lightboxScale = ref(1)
const lbTranslateX = ref(0)
const lbTranslateY = ref(0)

let lbInitialDist = 0
let lbInitialScale = 1
let lbLastTouchX = 0
let lbLastTouchY = 0
let lbLastMidX = 0
let lbLastMidY = 0

const LB_MIN_SCALE = 1
const LB_MAX_SCALE = 5

function openLightbox() {
  lightboxScale.value = LB_MIN_SCALE
  lbTranslateX.value = 0
  lbTranslateY.value = 0
  lightboxOpen.value = true
}

function closeLightbox() {
  lightboxOpen.value = false
}

function getTouchDist(t1: Touch, t2: Touch): number {
  return Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)
}

function onLightboxTouchStart(e: TouchEvent) {
  if (e.touches.length === 1) {
    lbLastTouchX = e.touches[0].clientX
    lbLastTouchY = e.touches[0].clientY
  } else if (e.touches.length === 2) {
    lbInitialDist = getTouchDist(e.touches[0], e.touches[1])
    lbInitialScale = lightboxScale.value
    lbLastMidX = (e.touches[0].clientX + e.touches[1].clientX) / 2
    lbLastMidY = (e.touches[0].clientY + e.touches[1].clientY) / 2
  }
}

function onLightboxTouchMove(e: TouchEvent) {
  if (e.touches.length === 1 && lightboxScale.value > 1) {
    const dx = e.touches[0].clientX - lbLastTouchX
    const dy = e.touches[0].clientY - lbLastTouchY
    lbTranslateX.value += dx
    lbTranslateY.value += dy
    lbLastTouchX = e.touches[0].clientX
    lbLastTouchY = e.touches[0].clientY
  } else if (e.touches.length === 2) {
    const dist = getTouchDist(e.touches[0], e.touches[1])
    lightboxScale.value = Math.max(LB_MIN_SCALE, Math.min(LB_MAX_SCALE, lbInitialScale * (dist / lbInitialDist)))
    const midX = (e.touches[0].clientX + e.touches[1].clientX) / 2
    const midY = (e.touches[0].clientY + e.touches[1].clientY) / 2
    lbTranslateX.value += midX - lbLastMidX
    lbTranslateY.value += midY - lbLastMidY
    lbLastMidX = midX
    lbLastMidY = midY
    if (lightboxScale.value <= LB_MIN_SCALE) {
      lbTranslateX.value = 0
      lbTranslateY.value = 0
    }
  }
}

function onLightboxTouchEnd() {
  if (lightboxScale.value <= LB_MIN_SCALE) {
    lightboxScale.value = LB_MIN_SCALE
    lbTranslateX.value = 0
    lbTranslateY.value = 0
  }
}

const lightboxImgStyle = computed(() => ({
  transform: `translate(${lbTranslateX.value}px, ${lbTranslateY.value}px) scale(${lightboxScale.value})`,
  transformOrigin: 'center center',
}))
</script>

<template>
  <UDashboardPanel id="entrelinea-detail">
    <UDashboardNavbar
      :toggle="false"
      :ui="{
        root: 'h-auto min-h-(--ui-header-height) py-2 items-start sm:items-center',
        left: 'flex-1 min-w-0 py-1',
        title: 'flex items-center gap-1.5 font-semibold text-highlighted min-w-0 whitespace-normal'
      }"
    >
      <template #leading>
        <!-- En sub-pantalla de estudios: volver al detalle -->
        <UButton
          v-if="showStudies"
          icon="i-lucide-arrow-left"
          color="neutral"
          variant="ghost"
          class="-ms-1.5"
          @click="showStudies = false"
        />
        <!-- En detalle: cerrar el panel -->
        <UButton
          v-else
          icon="i-lucide-arrow-left"
          color="neutral"
          variant="ghost"
          class="-ms-1.5"
          @click="emits('close')"
        />
      </template>

      <template #right>
        <template v-if="!showStudies">
          <UTooltip v-if="collection" :text="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'">
            <UButton
              :icon="isFav ? 'i-lucide-bookmark-check' : 'i-lucide-bookmark-plus'"
              :color="isFav ? 'primary' : 'neutral'"
              variant="ghost"
              :aria-label="isFav ? 'Quitar de mi lista' : 'Guardar en mi lista'"
              @click="onToggleFavorite"
            />
          </UTooltip>
        </template>
      </template>
    </UDashboardNavbar>

    <div
      v-if="!showStudies"
      class="flex items-start justify-between gap-3 px-4 sm:px-6 py-2.5 border-b border-default bg-elevated/40 min-w-0 w-full"
    >
      <div class="flex flex-wrap items-center gap-2 min-w-0 flex-1">
        <UBadge
          v-if="document.locale"
          :label="String(document.locale).toUpperCase()"
          color="neutral"
          variant="subtle"
          size="xs"
          class="shrink-0"
        />
        <UBadge
          v-if="document.filter"
          :label="String(document.filter)"
          color="neutral"
          variant="subtle"
          size="xs"
          class="shrink-0 uppercase"
        />
        <span
          v-if="origin"
          class="inline-flex items-start rounded-md bg-primary/10 text-primary text-xs font-medium px-2 py-0.5 min-w-0 max-w-full whitespace-normal leading-snug [overflow-wrap:anywhere]"
          :title="origin"
        >
          {{ origin }}
        </span>
      </div>
    </div>

    <!-- ------------------------------------------------------------------ -->
    <!--  VISTA PRINCIPAL: imagen + texto + accesos                          -->
    <!-- ------------------------------------------------------------------ -->
    <div v-if="!showStudies" class="flex-1 overflow-y-auto">
      <div class="p-4 sm:p-6 pb-10 flex flex-col gap-6">

        <!-- Imagen: mobile toca para abrir lightbox, desktop zoom al hover -->
        <template v-if="imageUrl && (!document.draft || unlocked)">
          <!-- Mobile: imagen con indicador de zoom táctil -->
          <div
            class="lg:hidden h-52 rounded-xl overflow-hidden border border-default shadow-sm bg-elevated relative cursor-pointer flex items-center justify-center"
            @click="openLightbox"
          >
            <img :src="imageUrl" :alt="title" loading="lazy" class="w-full h-full object-contain select-none">
            <div class="absolute bottom-2 right-2 bg-black/50 rounded-full p-1.5 pointer-events-none">
              <UIcon name="i-lucide-zoom-in" class="size-4 text-white" />
            </div>
          </div>

          <!-- Desktop: hover zoom con lente -->
          <div
            ref="zoomBoxRef"
            class="hidden lg:flex h-52 rounded-xl bg-elevated border border-default shadow-sm p-4 items-center justify-center relative cursor-zoom-in select-none"
            @mouseenter="onZoomEnter"
            @mouseleave="onZoomLeave"
            @mousemove="onZoomMove"
          >
            <img
              ref="zoomImgRef"
              :src="imageUrl"
              :alt="title"
              loading="lazy"
              class="max-h-full max-w-full object-contain drop-shadow-sm select-none"
              draggable="false"
              @load="refreshImageRect"
            />
            <!-- Lente: marca el área magnificada -->
            <div
              v-show="zoomActive"
              class="absolute pointer-events-none border-2 border-white shadow-lg rounded"
              style="background-color: rgba(255,255,255,0.35);"
              :style="lensStyle"
            />
          </div>
        </template>

        <!-- Sin imagen / Borrador -->
        <div
          v-else
          class="rounded-xl border border-dashed border-default p-8 text-center text-xs text-dimmed"
        >
          <UIcon name="i-lucide-image-off" class="size-6 mb-1 mx-auto" />
          <p>Imagen no disponible</p>
        </div>

        <!-- Texto -->
        <div v-if="bodyHtml" class="rounded-xl border border-default bg-white dark:bg-neutral-900 shadow-sm p-4 sm:p-6">
          <article
            class="prose prose-sm max-w-none dark:prose-invert leading-relaxed"
            v-html="bodyHtml"
          />
        </div>
        <p v-else class="text-sm text-muted">
          No hay entrelínea para esta coincidencia.
        </p>

        <!-- Link al sitio -->
        <a
          v-if="document.link"
          :href="document.link"
          target="_blank"
          rel="noopener noreferrer"
          class="flex items-center gap-3 rounded-xl border border-primary/30 bg-primary/5 hover:bg-primary/10 transition-colors px-4 py-3 group"
        >
          <UIcon name="i-lucide-external-link" class="size-5 text-primary shrink-0" />
          <div class="min-w-0 flex-1">
            <p class="text-sm font-medium text-primary">Ver en el sitio</p>
            <p class="text-xs text-muted truncate">{{ document.link }}</p>
          </div>
          <UIcon name="i-lucide-chevron-right" class="size-4 text-primary/60 shrink-0 group-hover:translate-x-0.5 transition-transform" />
        </a>
      </div>
    </div>

    <!-- ------------------------------------------------------------------ -->
    <!--  SUB-PANTALLA: lista de estudios relacionados                       -->
    <!-- ------------------------------------------------------------------ -->
    <div v-else class="flex-1 overflow-y-auto divide-y divide-default">
      <a
        v-for="study in document.studies"
        :key="study.id"
        :href="study.link"
        target="_blank"
        rel="noopener noreferrer"
        :title="study.title"
        class="flex items-center gap-3 px-4 sm:px-6 py-3.5 hover:bg-primary/5 transition-colors group"
      >
        <div class="flex flex-col justify-center shrink-0 w-14 text-center">
          <template v-if="study.date">
            <span class="text-base font-bold text-highlighted tabular-nums leading-none">
              {{ new Date(study.date + 'T00:00:00').getUTCDate() }}
            </span>
            <span class="text-[10px] uppercase tracking-wide text-muted leading-tight mt-0.5">
              {{ new Date(study.date + 'T00:00:00').toLocaleDateString('es', { month: 'short', timeZone: 'UTC' }) }}
              {{ new Date(study.date + 'T00:00:00').getUTCFullYear() }}
            </span>
          </template>
          <UIcon v-else name="i-lucide-calendar-x" class="size-4 text-dimmed mx-auto" />
        </div>

        <div class="w-px self-stretch bg-default shrink-0" />

        <div class="flex-1 min-w-0">
          <p class="text-sm font-medium text-highlighted leading-snug group-hover:text-primary transition-colors line-clamp-2">
            {{ study.title }}
          </p>
          <p v-if="study.place" class="text-xs text-muted truncate mt-0.5">
            {{ study.place }}
          </p>
        </div>

        <UIcon name="i-lucide-arrow-up-right" class="size-4 text-muted shrink-0 group-hover:text-primary transition-colors" />
      </a>
    </div>

    <!-- Panel de zoom desktop: Teleport a body para escapar del stacking context -->
    <Teleport to="body">
      <div
        v-show="zoomActive"
        class="hidden lg:block fixed pointer-events-none bg-white border border-gray-200 shadow-2xl rounded-lg overflow-hidden"
        style="z-index: 9999;"
        :style="zoomPanelStyle"
      />
    </Teleport>

    <!-- Popup móvil: imagen con pinch-to-zoom -->
    <UModal
      v-model:open="lightboxOpen"
      :ui="{
        overlay: 'bg-black/90',
        content: 'bg-black text-white max-w-[95vw] sm:max-w-lg',
        header: 'py-2 px-3 border-b-0',
        body: 'p-0',
      }"
    >
      <template #header>
        <div class="w-full flex justify-end">
          <UButton
            icon="i-lucide-x"
            size="sm"
            color="neutral"
            variant="ghost"
            class="text-white hover:bg-white/20"
            @click="closeLightbox"
          />
        </div>
      </template>
      <template #body>
        <div
          class="touch-none flex items-center justify-center overflow-hidden"
          style="height: 70dvh"
          @touchstart.passive="onLightboxTouchStart"
          @touchmove.passive="onLightboxTouchMove"
          @touchend.passive="onLightboxTouchEnd"
        >
          <img
            v-if="imageUrl"
            :src="imageUrl"
            :alt="title"
            class="w-full h-full object-contain select-none"
            :style="lightboxImgStyle"
            draggable="false"
          />
        </div>
      </template>
    </UModal>

  </UDashboardPanel>
</template>
