<template>
  <div class="fixed inset-0 flex flex-col">
    <!-- Loading state -->
    <div v-if="loading" class="absolute inset-0 z-50 flex items-center justify-center bg-base-100/80">
      <Card padding="lg">
        <Stack align="center" justify="center" gap="3">
          <Spinner />
          <Text tone="muted">{{ $t('catalogLanding.states.loading') }}</Text>
        </Stack>
      </Card>
    </div>

    <!-- Fullscreen Map -->
    <div class="absolute inset-0">
      <ClientOnly>
        <CatalogMap
          ref="mapRef"
          :map-id="mapId"
          :items="itemsWithCoords"
          :use-server-clustering="false"
          :point-color="pointColor"
          :hovered-item-id="hoveredId"
          :hovered-item="hoveredItem"
          @select-item="onMapSelect"
          @bounds-change="onBoundsChange"
        />
      </ClientOnly>
    </div>

    <!-- List button (LEFT, opens panel) - hide when panel is open -->
    <button
      v-if="!isPanelOpen"
      class="absolute top-[116px] left-4 z-20 hidden lg:flex items-center gap-2 bg-black/30 backdrop-blur-md rounded-lg px-3 py-1.5 border border-white/10 text-white text-sm hover:bg-black/40 transition-colors"
      @click="isPanelOpen = true"
    >
      <Icon name="lucide:menu" size="16" />
      <span>{{ $t('catalog.list') }}</span>
    </button>

    <!-- Left panel (slides from left when isPanelOpen is true) -->
    <Transition name="slide-left">
      <div
        v-if="isPanelOpen"
        class="absolute top-[116px] left-4 bottom-4 z-30 w-96 max-w-[calc(100vw-2rem)] hidden lg:block"
      >
        <div class="bg-black/50 backdrop-blur-md rounded-xl shadow-lg border border-white/10 h-full flex flex-col text-white overflow-hidden">
          <!-- Panel header -->
          <div class="p-4 border-b border-white/10 flex-shrink-0">
            <div class="flex items-center justify-between mb-3">
              <Text weight="semibold">{{ title }}</Text>
              <button
                class="btn btn-ghost btn-xs btn-circle text-white/70 hover:text-white"
                @click="isPanelOpen = false"
              >
                <Icon name="lucide:x" size="16" />
              </button>
            </div>

            <!-- Search bar -->
            <div v-if="showSearch" class="relative">
              <input
                :value="searchQuery"
                type="text"
                :placeholder="$t('common.search')"
                class="input input-sm w-full bg-white/10 border-white/20 text-white placeholder:text-white/50"
                @input="$emit('update:search-query', ($event.target as HTMLInputElement).value)"
              />
              <Icon name="lucide:search" size="16" class="absolute right-3 top-1/2 -translate-y-1/2 text-white/50" />
            </div>

            <!-- Header slot for extra actions -->
            <div v-if="$slots.header" class="mt-3">
              <slot name="header" />
            </div>
          </div>

          <!-- Items list -->
          <div class="flex-1 overflow-y-auto p-4 space-y-3">
            <template v-if="displayItems.length > 0">
              <div
                v-for="item in displayItems"
                :key="item.uuid"
                class="cursor-pointer"
                @mouseenter="$emit('update:hovered-id', item.uuid)"
                @mouseleave="$emit('update:hovered-id', undefined)"
                @click="$emit('select', item)"
              >
                <slot name="card" :item="item" />
              </div>
            </template>
            <template v-else>
              <slot name="empty" />
            </template>
          </div>

          <!-- Panel footer with count -->
          <div class="p-3 border-t border-white/10 flex-shrink-0">
            <Text size="sm" tone="muted">
              {{ $t('catalog.showing') }} {{ displayItems.length }} {{ $t('catalog.of') }} {{ totalCount }}
            </Text>
          </div>
        </div>
      </div>
    </Transition>

    <!-- Mobile bottom sheet -->
    <div class="lg:hidden absolute bottom-0 left-0 right-0 z-20">
      <!-- Mobile controls: List button -->
      <div class="flex justify-start px-4 mb-2">
        <button
          class="flex items-center gap-2 bg-black/30 backdrop-blur-md rounded-lg px-3 py-2 border border-white/10 text-white text-sm"
          @click="isPanelOpen = true"
        >
          <Icon name="lucide:menu" size="16" />
          <span>{{ $t('catalog.list') }}</span>
        </button>
      </div>

      <!-- Mobile panel (collapsible) -->
      <Transition name="slide-up">
        <div
          v-if="isPanelOpen"
          class="bg-black/50 backdrop-blur-md rounded-t-xl shadow-lg border border-white/10 transition-all duration-300 text-white h-[60vh]"
        >
          <!-- Drag handle / close -->
          <div
            class="flex justify-center py-2 cursor-pointer"
            @click="isPanelOpen = false"
          >
            <div class="w-10 h-1 bg-white/30 rounded-full" />
          </div>

          <div class="px-4 pb-4 overflow-y-auto h-[calc(60vh-2rem)]">
            <!-- Search bar -->
            <div v-if="showSearch" class="relative mb-3">
              <input
                :value="searchQuery"
                type="text"
                :placeholder="$t('common.search')"
                class="input input-sm w-full bg-white/10 border-white/20 text-white placeholder:text-white/50"
                @input="$emit('update:search-query', ($event.target as HTMLInputElement).value)"
              />
              <Icon name="lucide:search" size="16" class="absolute right-3 top-1/2 -translate-y-1/2 text-white/50" />
            </div>

            <!-- Header slot -->
            <div v-if="$slots.header" class="mb-3">
              <slot name="header" />
            </div>

            <!-- Items list -->
            <div class="space-y-3">
              <template v-if="displayItems.length > 0">
                <div
                  v-for="item in displayItems"
                  :key="item.uuid"
                  @click="$emit('select', item)"
                >
                  <slot name="card" :item="item" />
                </div>
              </template>
              <template v-else>
                <slot name="empty" />
              </template>
            </div>
          </div>
        </div>
      </Transition>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { MapBounds } from '~/components/catalog/CatalogMap.vue'

interface MapItem {
  uuid?: string | null
  latitude?: number | null
  longitude?: number | null
  name?: string | null
  [key: string]: unknown
}

const props = withDefaults(defineProps<{
  items: MapItem[]
  loading?: boolean
  mapId?: string
  pointColor?: string
  hoveredId?: string
  selectedId?: string
  totalCount?: number
  title?: string
  showSearch?: boolean
  searchQuery?: string
}>(), {
  loading: false,
  mapId: 'client-area-map',
  pointColor: '#6366f1',
  totalCount: 0,
  title: '',
  showSearch: true,
  searchQuery: ''
})

const emit = defineEmits<{
  'select': [item: MapItem]
  'bounds-change': [bounds: MapBounds]
  'update:hovered-id': [uuid: string | undefined]
  'update:search-query': [value: string]
}>()

// Panel state
const isPanelOpen = ref(true)

// Map ref
const mapRef = ref<{ flyTo: (lat: number, lng: number, zoom?: number) => void } | null>(null)

// Filter items with search query
const displayItems = computed(() => {
  if (!props.searchQuery) return props.items
  const query = props.searchQuery.toLowerCase()
  return props.items.filter(item => {
    const name = (item.name as string || '').toLowerCase()
    return name.includes(query)
  })
})

// Filter items with valid coordinates for map
const itemsWithCoords = computed(() =>
  props.items.filter(item =>
    item.latitude != null &&
    item.longitude != null &&
    !isNaN(Number(item.latitude)) &&
    !isNaN(Number(item.longitude))
  ).map(item => ({
    uuid: item.uuid,
    name: item.name || '',
    latitude: Number(item.latitude),
    longitude: Number(item.longitude)
  }))
)

// Hovered item with coordinates for map highlight
const hoveredItem = computed(() => {
  if (!props.hoveredId) return null
  const item = props.items.find(i => i.uuid === props.hoveredId)
  if (!item?.latitude || !item?.longitude) return null
  return { latitude: Number(item.latitude), longitude: Number(item.longitude) }
})

const onBoundsChange = (bounds: MapBounds) => {
  emit('bounds-change', bounds)
}

const onMapSelect = (uuid: string) => {
  const item = props.items.find(i => i.uuid === uuid)
  if (item) {
    emit('select', item)
  }
}

// Expose flyTo for external use
const flyTo = (lat: number, lng: number, zoom = 8) => {
  mapRef.value?.flyTo(lat, lng, zoom)
}

defineExpose({ flyTo })
</script>

<style scoped>
/* Drawer slide animation (desktop - left) */
.slide-left-enter-active,
.slide-left-leave-active {
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.slide-left-enter-from,
.slide-left-leave-to {
  transform: translateX(-100%);
  opacity: 0;
}

/* Drawer slide animation (mobile - up) */
.slide-up-enter-active,
.slide-up-leave-active {
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.slide-up-enter-from,
.slide-up-leave-to {
  transform: translateY(100%);
  opacity: 0;
}
</style>
