<script lang="ts">
  import { onMount, onDestroy } from 'svelte';
  import maplibregl from 'maplibre-gl';
  import 'maplibre-gl/dist/maplibre-gl.css';
  import { formatDistance, formatDate, sportIcon } from '../lib/format';

  export let base: string = '/';

  interface Segment {
    id: string;
    name: string;
    sport: string | null;
    distance_m: number;
    polyline: [number, number][];
    bbox: [number, number, number, number];
    created_by: string;
    created_at: string;
  }

  let mapEl: HTMLDivElement;
  let map: any;
  let segments: Segment[] = [];
  let loading = false;
  let selectedId: string | null = null;
  let fetchTimer: ReturnType<typeof setTimeout> | null = null;

  const TILE_STYLE = 'https://tiles.openfreemap.org/styles/positron';
  const SEG_GRADIENT = ['interpolate', ['linear'], ['line-progress'], 0, '#22c55e', 1, '#ef4444'];

  $: selectedSeg = segments.find(s => s.id === selectedId) ?? null;

  onMount(() => {
    map = new maplibregl.Map({
      container: mapEl,
      style: TILE_STYLE,
      center: [12, 45],
      zoom: 8,
      attributionControl: false,
    });
    map.addControl(new maplibregl.NavigationControl({ showCompass: false }), 'top-right');
    map.addControl(new maplibregl.AttributionControl({ compact: true }), 'bottom-right');

    map.on('load', () => {
      map.addSource('segments', {
        type: 'geojson',
        lineMetrics: true,
        data: { type: 'FeatureCollection', features: [] },
      });

      // Wider invisible hit area for easier clicking
      map.addLayer({ id: 'seg-hit', type: 'line', source: 'segments',
        paint: { 'line-color': 'transparent', 'line-width': 14 } });

      map.addLayer({ id: 'seg-line', type: 'line', source: 'segments',
        layout: { 'line-cap': 'round', 'line-join': 'round' },
        paint: {
          'line-gradient': SEG_GRADIENT,
          'line-width': ['case', ['==', ['get', 'id'], selectedId ?? ''], 5, 3],
        },
      });

      map.on('click', 'seg-hit', (e: any) => {
        const id = e.features?.[0]?.properties?.id;
        if (id) selectedId = selectedId === id ? null : id;
      });
      map.on('mouseenter', 'seg-hit', () => { map.getCanvas().style.cursor = 'pointer'; });
      map.on('mouseleave', 'seg-hit', () => { map.getCanvas().style.cursor = ''; });

      // Initial view: fit to all existing segments, fall back to default center
      fetch('/api/segments', { credentials: 'include' })
        .then(r => r.ok ? r.json() : [])
        .then((all: Segment[]) => {
          if (all.length > 0) {
            const lonMin = Math.min(...all.map(s => s.bbox[0]));
            const latMin = Math.min(...all.map(s => s.bbox[1]));
            const lonMax = Math.max(...all.map(s => s.bbox[2]));
            const latMax = Math.max(...all.map(s => s.bbox[3]));
            map.fitBounds([[lonMin, latMin], [lonMax, latMax]], { padding: 60, maxZoom: 14 });
            segments = all;
            updateMapSource();
          } else {
            fetchSegments();
          }
        })
        .catch(() => fetchSegments());
    });

    map.on('moveend', () => {
      if (fetchTimer) clearTimeout(fetchTimer);
      fetchTimer = setTimeout(fetchSegments, 300);
    });
  });

  onDestroy(() => {
    if (fetchTimer) clearTimeout(fetchTimer);
    map?.remove();
  });

  async function fetchSegments() {
    if (!map) return;
    const b = map.getBounds();
    const bbox = [b.getWest(), b.getSouth(), b.getEast(), b.getNorth()].map(v => v.toFixed(5)).join(',');
    loading = true;
    try {
      const r = await fetch(`/api/segments?bbox=${bbox}`, { credentials: 'include' });
      if (!r.ok) return;
      segments = await r.json();
      updateMapSource();
    } catch { /* ignore */ }
    loading = false;
  }

  function updateMapSource() {
    if (!map?.getSource('segments')) return;
    map.getSource('segments').setData({
      type: 'FeatureCollection',
      features: segments.map(s => ({
        type: 'Feature',
        geometry: {
          type: 'LineString',
          coordinates: s.polyline.map(([lat, lon]) => [lon, lat]),
        },
        properties: { id: s.id, name: s.name },
      })),
    });
    if (map.getLayer('seg-line')) {
      map.setPaintProperty('seg-line', 'line-width',
        ['case', ['==', ['get', 'id'], selectedId ?? ''], 5, 3]);
    }
  }

  $: if (map?.getLayer('seg-line') && selectedId !== undefined) {
    map.setPaintProperty('seg-line', 'line-width',
      ['case', ['==', ['get', 'id'], selectedId ?? ''], 5, 3]);
  }

  async function deleteSegment(id: string) {
    if (!confirm('Delete this segment? This cannot be undone.')) return;
    try {
      const r = await fetch(`/api/segments/${id}`, { method: 'DELETE', credentials: 'include' });
      if (r.ok) {
        segments = segments.filter(s => s.id !== id);
        if (selectedId === id) selectedId = null;
        updateMapSource();
      } else {
        const d = await r.json();
        alert(d.detail ?? 'Failed to delete');
      }
    } catch { alert('Could not reach server'); }
  }
</script>

<div class="flex flex-col h-full">
  <!-- Header -->
  <div class="flex items-center justify-between px-4 py-3 border-b shrink-0"
       style="border-color: var(--border)">
    <h1 class="text-lg font-bold text-white">Segments</h1>
    <a href="{base}segments/new/"
       class="px-3 py-1.5 rounded-lg text-sm bg-blue-600 hover:bg-blue-500 text-white transition-colors">
      + New segment
    </a>
  </div>

  <!-- Map -->
  <div class="relative" style="height: 400px;">
    <div bind:this={mapEl} class="w-full h-full"></div>
    {#if loading}
      <div class="absolute top-2 left-2 bg-black/60 text-white text-xs px-2 py-1 rounded">Loading…</div>
    {/if}
  </div>

  <!-- Segment list -->
  <div class="flex-1 overflow-y-auto">
    {#if segments.length === 0 && !loading}
      <p class="text-zinc-500 text-sm text-center py-10">
        No segments in this area.<br/>
        <a href="{base}segments/new/" class="text-blue-400 hover:text-blue-300">Create the first one →</a>
      </p>
    {:else}
      <div class="divide-y" style="border-color: var(--border)">
        {#each segments as seg (seg.id)}
          <div
            class="px-4 py-3 cursor-pointer transition-colors"
            class:bg-zinc-800={selectedId === seg.id}
            style={selectedId !== seg.id ? 'background: transparent' : ''}
            on:click={() => selectedId = selectedId === seg.id ? null : seg.id}
            role="button"
            tabindex="0"
            on:keydown={e => e.key === 'Enter' && (selectedId = selectedId === seg.id ? null : seg.id)}
          >
            <div class="flex items-start justify-between gap-2">
              <div class="min-w-0">
                <div class="flex items-center gap-2">
                  {#if seg.sport}<span class="text-base">{sportIcon(seg.sport as any)}</span>{/if}
                  <span class="text-sm font-medium text-white truncate">{seg.name}</span>
                </div>
                <p class="text-xs text-zinc-500 mt-0.5">
                  {formatDistance(seg.distance_m)} · by {seg.created_by} · {formatDate(seg.created_at)}
                </p>
              </div>
              <button
                class="text-xs text-zinc-600 hover:text-red-400 transition-colors shrink-0"
                on:click|stopPropagation={() => deleteSegment(seg.id)}
                title="Delete segment"
              >✕</button>
            </div>

            {#if selectedId === seg.id}
              <div class="mt-2">
                <a href="{base}segments/{seg.id}/"
                   class="text-xs text-blue-400 hover:text-blue-300 transition-colors">
                  View efforts →
                </a>
              </div>
            {/if}
          </div>
        {/each}
      </div>
    {/if}
  </div>
</div>
