<template>
  <div class="outremer-accordion">
    <div
      v-for="dom in DOM_TOM"
      :key="dom.name"
      class="outremer-item"
    >
      <button
        class="outremer-header"
        @click="toggle(dom.name)"
        :aria-expanded="openDom === dom.name"
      >
        <span class="outremer-title">{{ dom.name }}</span>
        <span class="outremer-meta">
          <span class="outremer-count-badge" :style="orgCounts[dom.name] === 0 ? 'opacity:0.4' : ''">
            {{ orgCounts[dom.name] ?? 0 }} fiche{{ (orgCounts[dom.name] ?? 0) > 1 ? 's' : '' }}
          </span>
          <svg
            width="14" height="14" viewBox="0 0 24 24" fill="none"
            stroke="currentColor" stroke-width="2.5" stroke-linecap="round"
            aria-hidden="true"
            class="outremer-chevron"
            :class="{ 'outremer-chevron--open': openDom === dom.name }"
          >
            <polyline points="6 9 12 15 18 9"/>
          </svg>
        </span>
      </button>

      <div
        v-show="openDom === dom.name"
        class="outremer-map-container"
      >
        <div :ref="el => { if (el) mapRefs[dom.name] = el as HTMLElement }" class="outremer-map" />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { Map as LeafletMap, TileLayer } from 'leaflet'

interface Org {
  Id: number
  nom: string
  latitude?: number | null
  longitude?: number | null
  territoire?: string
  echelle?: string
  tags_fonction?: string
  localisation_ville?: string
  prioritaire?: boolean
}

const DOM_TOM = [
  { name: 'Guadeloupe',  center: [16.25, -61.58] as [number, number], zoom: 9  },
  { name: 'Martinique',  center: [14.65, -61.02] as [number, number], zoom: 9  },
  { name: 'Guyane',      center: [4.0,  -53.0]   as [number, number], zoom: 6  },
  { name: 'La Réunion',  center: [-21.11, 55.53]  as [number, number], zoom: 9  },
  { name: 'Mayotte',     center: [-12.83, 45.16]  as [number, number], zoom: 10 },
]

const props = defineProps<{
  orgs: Org[]
  selectedId?: number | null
}>()

const emit = defineEmits<{
  'select-org': [id: number]
}>()

const mapRefs: Record<string, HTMLElement> = {}
const mapInstances: Record<string, LeafletMap> = {}
const tileLayers: Record<string, TileLayer> = {}

const openDom = ref<string | null>(null)

const orgCounts = computed<Record<string, number>>(() => {
  const counts: Record<string, number> = {}
  DOM_TOM.forEach(d => { counts[d.name] = 0 })
  props.orgs.forEach(o => {
    if (o.territoire && counts[o.territoire] !== undefined) {
      counts[o.territoire]++
    }
  })
  return counts
})

function toggle(name: string) {
  openDom.value = openDom.value === name ? null : name
  nextTick(() => {
    if (openDom.value === name && !mapInstances[name]) {
      initSingleMap(name)
    } else if (openDom.value === name) {
      mapInstances[name]?.invalidateSize()
    }
  })
}

function createPinIcon(L: any, isPrioritaire: boolean, isSelected = false) {
  const bg = isPrioritaire ? '#f5b342' : 'rgba(26, 34, 56, 0.6)'
  const border = isPrioritaire ? '#1a2238' : '#ffffff'
  const size = isSelected ? 16 : 12
  return L.divIcon({
    className: '',
    html: `<div style="width:${size}px;height:${size}px;border-radius:50%;background:${bg};border:2px solid ${border};"></div>`,
    iconSize: [size, size],
    iconAnchor: [size / 2, size / 2],
    popupAnchor: [0, -(size / 2 + 4)],
  })
}

function getTileUrl(dark: boolean) {
  return dark
    ? 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png'
    : 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png'
}

async function initSingleMap(domName: string) {
  const dom = DOM_TOM.find(d => d.name === domName)
  if (!dom) return
  const Lmod = await import('leaflet')
  const L: any = (Lmod as any).default || Lmod
  await import('leaflet/dist/leaflet.css')
  const isDark = typeof document !== 'undefined' && document.documentElement.classList.contains('dark')
  const el = mapRefs[domName]
  if (!el) return
  const map = L.map(el, {
    center: dom.center, zoom: dom.zoom,
    zoomControl: false, attributionControl: false,
    dragging: true, scrollWheelZoom: true, doubleClickZoom: true,
    touchZoom: true, keyboard: false,
  })
  const tileLayer = L.tileLayer(getTileUrl(isDark), {
    attribution: '© OpenStreetMap contributors © CARTO', maxZoom: 19,
  })
  tileLayer.addTo(map)
  tileLayers[domName] = tileLayer as unknown as TileLayer
  mapInstances[domName] = map as unknown as LeafletMap
  renderPins(L, domName)
}

function updateTheme(dark: boolean) {
  const url = getTileUrl(dark)
  Object.values(tileLayers).forEach(tl => {
    (tl as any).setUrl(url)
  })
}

function renderPins(L: any, domName: string) {
  const map = mapInstances[domName] as any
  if (!map) return

  if (map._navMarkers) {
    map._navMarkers.forEach((m: any) => m.remove())
  }
  map._navMarkers = []

  const domOrgs = props.orgs.filter(o => o.territoire === domName && o.latitude != null && o.longitude != null)
  domOrgs.forEach(org => {
    const icon = createPinIcon(L, !!org.prioritaire, org.Id === props.selectedId)
    const marker = L.marker([org.latitude!, org.longitude!], { icon })

    const fonctions = org.tags_fonction
      ? org.tags_fonction.split(',').map((f: string) => f.trim()).filter(Boolean).slice(0, 2).join(', ')
      : ''

    marker.bindPopup(`
      <div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;min-width:160px;padding:4px 0;">
        <div style="font-weight:700;color:#1a2238;margin-bottom:2px;">${org.nom}</div>
        ${org.echelle ? `<div style="font-size:11px;color:rgba(26,34,56,0.55);">${org.echelle}${org.localisation_ville ? ' · ' + org.localisation_ville : ''}</div>` : ''}
        ${fonctions ? `<div style="font-size:11px;color:rgba(26,34,56,0.55);margin-top:2px;">${fonctions}</div>` : ''}
        <a href="/fiche/${org.Id}" style="display:inline-block;margin-top:8px;font-size:12px;color:#1a2238;text-decoration:underline;">Voir la fiche →</a>
      </div>
    `, { maxWidth: 200 })

    marker.on('click', () => emit('select-org', org.Id))
    marker.addTo(map)
    map._navMarkers.push(marker)
  })
}

watch(() => props.orgs, () => {
  DOM_TOM.forEach(dom => {
    if (mapInstances[dom.name]) {
      import('leaflet').then(L => renderPins(L, dom.name))
    }
  })
}, { deep: false })

watch(() => props.selectedId, () => {
  DOM_TOM.forEach(dom => {
    if (mapInstances[dom.name]) {
      import('leaflet').then(L => renderPins(L, dom.name))
    }
  })
})

let themeObserver: MutationObserver | null = null

onMounted(() => {
  themeObserver = new MutationObserver(() => {
    const dark = document.documentElement.classList.contains('dark')
    updateTheme(dark)
  })
  themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })
})

onUnmounted(() => {
  themeObserver?.disconnect()
  Object.values(mapInstances).forEach(m => (m as any).remove())
})
</script>

<style scoped>
.outremer-accordion {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.outremer-item {
  border-bottom: 1px solid var(--nav-bg-alt);
}

.outremer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 12px 16px;
  background: var(--nav-surface);
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background 0.15s;
}

.outremer-header:hover {
  background: var(--nav-bg-alt);
}

.outremer-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--nav-text);
}

.outremer-meta {
  display: flex;
  align-items: center;
  gap: 8px;
}

.outremer-count-badge {
  font-size: 0.75rem;
  color: var(--nav-text-muted);
}

.outremer-chevron {
  color: var(--nav-text-muted);
  transition: transform 0.2s ease;
  flex-shrink: 0;
}

.outremer-chevron--open {
  transform: rotate(180deg);
}

.outremer-map-container {
  height: 220px;
  border-top: 1px solid var(--nav-bg-alt);
}

.outremer-map {
  width: 100%;
  height: 100%;
}
</style>
