const STORAGE_KEY = "hexawetter_settings";
const FAV_KEY = "hexawetter_favorites";

const el = (id) => document.getElementById(id);
let latestForecast = null;
let map = null;
let mapMarker = null;
let wmsLayers = [];
let layerControl = null;
let osmLayer = null;
let radarLayer = null;
let warningLayer = null;
let localRadarOverlay = null;
let radarTimes = [];
let radarFrameIndex = 0;
let radarPlayTimer = null;
let radarPlaying = false;
let renderedFrames = [];
let settings = loadSettings();
let searchTimer = null;

const WEATHER_ICONS = {
  0: "☀️", 1: "🌤️", 2: "⛅", 3: "☁️", 45: "🌫️", 48: "🌫️",
  51: "🌦️", 53: "🌦️", 55: "🌧️", 61: "🌧️", 63: "🌧️", 65: "🌧️",
  71: "🌨️", 73: "🌨️", 75: "❄️", 80: "🌦️", 81: "🌧️", 82: "⛈️",
  95: "⛈️", 96: "⛈️", 99: "⛈️",
};

function loadSettings() {
  try {
    return { theme: "dark", unitTemp: "celsius", unitWind: "kmh", radarMinutes: 120, ...JSON.parse(localStorage.getItem(STORAGE_KEY) || "{}") };
  } catch { return { theme: "dark", unitTemp: "celsius", unitWind: "kmh", radarMinutes: 120 }; }
}

function saveSettings() {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
}

function loadFavorites() {
  try { return JSON.parse(localStorage.getItem(FAV_KEY) || "[]"); } catch { return []; }
}

function saveFavorites(items) {
  localStorage.setItem(FAV_KEY, JSON.stringify(items));
}

function formatBytes(bytes) {
  if (!bytes) return "–";
  const units = ["B", "KB", "MB", "GB"];
  let value = bytes, unit = 0;
  while (value >= 1024 && unit < units.length - 1) { value /= 1024; unit++; }
  return `${value.toFixed(unit === 0 ? 0 : 1)} ${units[unit]}`;
}

function weatherText(code) {
  const map = {
    0: "Klar", 1: "Überwiegend klar", 2: "Teils bewölkt", 3: "Bewölkt",
    45: "Nebel", 48: "Reifnebel", 51: "Leichter Niesel", 53: "Niesel",
    55: "Starker Niesel", 61: "Leichter Regen", 63: "Regen", 65: "Starker Regen",
    71: "Leichter Schnee", 73: "Schnee", 75: "Starker Schnee", 80: "Regenschauer",
    81: "Starke Schauer", 82: "Heftige Schauer", 95: "Gewitter", 96: "Gewitter mit Hagel", 99: "Schweres Gewitter",
  };
  return `${WEATHER_ICONS[code] || ""} ${map[code] || `Code ${code}`}`.trim();
}

function convertTemp(c) {
  if (settings.unitTemp === "fahrenheit") return `${Math.round(c * 9 / 5 + 32)} °F`;
  return `${Math.round(c)} °C`;
}

function convertWind(kmh) {
  if (settings.unitWind === "ms") return `${(kmh / 3.6).toFixed(1)} m/s`;
  if (settings.unitWind === "kn") return `${(kmh * 0.539957).toFixed(1)} kn`;
  return `${Math.round(kmh)} km/h`;
}

async function api(path, options = {}) {
  const res = await fetch(path, options);
  if (!res.ok) {
    const text = await res.text();
    throw new Error(`${res.status}: ${text}`);
  }
  return res.json();
}

function getLocation() {
  return {
    place: el("place").value || "Standort",
    lat: Number(el("lat").value),
    lon: Number(el("lon").value),
  };
}

function setLocation(loc) {
  el("place").value = loc.place;
  el("lat").value = loc.lat;
  el("lon").value = loc.lon;
}

function formatDateTime(value) {
  return new Date(value).toLocaleString("de-DE", {
    weekday: "short", day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit",
  });
}

function metric(label, value, hint = "") {
  return `<div class="metric"><span>${label}</span><strong>${value}</strong>${hint ? `<small>${hint}</small>` : ""}</div>`;
}

function warnLevelClass(level) {
  if (level >= 50) return "warn-extreme";
  if (level >= 40) return "warn-severe";
  if (level >= 30) return "warn-moderate";
  if (level >= 20) return "warn-minor";
  return "warn-info";
}

async function loadHealth() {
  try {
    const data = await api("/api/health");
    el("health").textContent = `API: online · v${data.version} · ${new Date(data.time_utc).toLocaleTimeString("de-DE")}`;
    el("health").classList.remove("bad");
  } catch {
    el("health").textContent = "API: offline";
    el("health").classList.add("bad");
  }
}

async function loadSourceStatus() {
  try {
    const data = await api("/api/health/sources");
    renderSourceStatus(data.sources || []);
  } catch {
    el("sourceStatusSummary").textContent = "Quellenstatus nicht verfügbar";
  }
}

function applyDashboard(dash) {
  const loc = getLocation();
  if (dash.forecast?.data) {
    latestForecast = dash.forecast;
    const current = dash.forecast.data.current;
    el("currentTemp").textContent = convertTemp(current.temperature_2m);
    el("currentMeta").textContent = `${weatherText(current.weather_code)} · Wind ${convertWind(current.wind_speed_10m)} · ${loc.place}`;
    el("forecastSource").textContent = dash.forecast.cached ? `${dash.forecast.source} (Cache)` : dash.forecast.source;
    el("dailySource").textContent = dash.forecast.cached ? `${dash.forecast.source} (Cache)` : dash.forecast.source;
    el("currentDetails").innerHTML = [
      metric("Gefühlt", convertTemp(current.apparent_temperature)),
      metric("Luftfeuchte", `${current.relative_humidity_2m} %`),
      metric("Luftdruck", `${Math.round(current.pressure_msl)} hPa`),
      metric("Niederschlag", `${current.precipitation ?? 0} mm`),
      metric("Bewölkung", `${current.cloud_cover ?? 0} %`),
      metric("Böen", convertWind(current.wind_gusts_10m ?? 0)),
    ].join("");
    renderDaily(dash.forecast.data.daily);
    renderHourly(dash.forecast.data.hourly);
    renderHourStrip(dash.forecast.data.hourly);
  }

  if (dash.observations?.data) {
    const weather = dash.observations.data.weather;
    const source = dash.observations.data.sources?.[0];
    if (weather) {
      el("obsTemp").textContent = convertTemp(weather.temperature);
      el("obsMeta").textContent = `${source?.station_name || "DWD Station"} · ${weather.timestamp || ""}`;
    }
  }

  if (dash.radar) {
    el("radarCount").textContent = `${dash.radar.count} online`;
    el("radarMeta").textContent = `Produkt ${dash.radar.product?.toUpperCase() || "RV"} · DWD OpenData`;
  }

  if (dash.warnings) {
    applyWarningsData(dash.warnings);
  }
}

function applyWarningsData(data) {
  const localOnly = el("warningsLocalOnly")?.checked ?? true;
  const warnings = data.warnings || [];
  el("warnCount").textContent = String(data.count_local ?? warnings.length);
  el("warnMeta").textContent = localOnly
    ? `${warnings.length} Warnung(en) für deinen Standort`
    : `${data.count_total} Warnungen bundesweit (Top ${warnings.length})`;

  const warncellEl = el("warncellInfo");
  if (localOnly && data.warncells?.length) {
    warncellEl.classList.remove("hidden");
    warncellEl.innerHTML = `Zugeordnete Warngebiete: ${data.warncells.map((a) => `<strong>${a.name}</strong> (${a.warncell_id})`).join(" · ")}`;
  } else {
    warncellEl.classList.add("hidden");
    warncellEl.innerHTML = "";
  }

  el("warningsList").innerHTML = warnings.length ? warnings.map((w) => `
    <article class="warning-card ${warnLevelClass(w.level)}">
      <div class="warning-head">
        <strong>${w.headline || w.event}</strong>
        <span class="warn-badge">Level ${w.level} · ${w.level_label}</span>
      </div>
      <p class="muted">${w.region_name || ""} · ${w.state || ""}</p>
      <p>${(w.description || "").replace(/\n/g, "<br>")}</p>
      ${w.instruction ? `<p class="instruction">${w.instruction}</p>` : ""}
      <small class="muted">Gültig: ${w.start ? formatDateTime(w.start) : "–"} – ${w.end ? formatDateTime(w.end) : "–"}</small>
    </article>
  `).join("") : `<p class="muted">${localOnly ? "Keine aktiven Warnungen für deinen Standort." : "Keine Warnungen verfügbar."}</p>`;
}

function renderSourceStatus(sources) {
  const bad = sources.filter((s) => s.status === "error").length;
  el("sourceStatusSummary").textContent = bad ? `${bad} Quelle(n) mit Problemen` : "Alle Quellen erreichbar";
  el("sourceStatusGrid").innerHTML = sources.map((s) => `
    <div class="source-status ${s.status}">
      <strong>${s.name}</strong>
      <span>${s.status}${s.latency_ms ? ` · ${s.latency_ms} ms` : ""}</span>
      ${s.error ? `<small>${s.error}</small>` : ""}
    </div>
  `).join("");
}

async function loadForecast() {
  const loc = getLocation();
  const data = await api(`/api/forecast?lat=${loc.lat}&lon=${loc.lon}`);
  latestForecast = data;
  const current = data.data.current;
  el("currentTemp").textContent = convertTemp(current.temperature_2m);
  el("currentMeta").textContent = `${weatherText(current.weather_code)} · Wind ${convertWind(current.wind_speed_10m)} · ${loc.place}`;
  el("forecastSource").textContent = data.cached ? `${data.source} (Cache)` : data.source;
  el("dailySource").textContent = data.cached ? `${data.source} (Cache)` : data.source;
  el("currentDetails").innerHTML = [
    metric("Gefühlt", convertTemp(current.apparent_temperature)),
    metric("Luftfeuchte", `${current.relative_humidity_2m} %`),
    metric("Luftdruck", `${Math.round(current.pressure_msl)} hPa`),
    metric("Niederschlag", `${current.precipitation ?? 0} mm`),
    metric("Bewölkung", `${current.cloud_cover ?? 0} %`),
    metric("Böen", convertWind(current.wind_gusts_10m ?? 0)),
  ].join("");
  renderDaily(data.data.daily);
  renderHourly(data.data.hourly);
  renderHourStrip(data.data.hourly);
}

function renderDaily(daily) {
  el("dailyForecast").innerHTML = daily.time.map((date, idx) => {
    const d = new Date(date + "T12:00:00");
    const day = d.toLocaleDateString("de-DE", { weekday: "short", day: "2-digit", month: "2-digit" });
    const sunrise = daily.sunrise?.[idx] ? new Date(daily.sunrise[idx]).toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" }) : "–";
    const sunset = daily.sunset?.[idx] ? new Date(daily.sunset[idx]).toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" }) : "–";
    return `<div class="day">
      <strong>${day}</strong>
      <span class="muted">${weatherText(daily.weather_code[idx])}</span>
      <p class="temp">${convertTemp(daily.temperature_2m_max[idx])} / ${convertTemp(daily.temperature_2m_min[idx])}</p>
      <span class="muted">Regen: ${daily.precipitation_sum[idx]} mm · ${daily.precipitation_probability_max[idx] ?? 0}%</span>
      <span class="muted block">Wind: ${convertWind(daily.wind_speed_10m_max[idx] ?? 0)} · Böen ${convertWind(daily.wind_gusts_10m_max[idx] ?? 0)}</span>
      <span class="muted block">Sonne: ${sunrise} – ${sunset}</span>
    </div>`;
  }).join("");
}

function renderHourly(hourly) {
  el("hourlyTable").innerHTML = hourly.time.slice(0, 48).map((time, idx) => `
    <tr>
      <td>${formatDateTime(time)}</td>
      <td>${weatherText(hourly.weather_code[idx])}</td>
      <td>${convertTemp(hourly.temperature_2m[idx])}</td>
      <td>${hourly.precipitation_probability[idx] ?? 0}% · ${hourly.precipitation[idx] ?? 0} mm</td>
      <td>${hourly.cloud_cover[idx] ?? 0}%</td>
      <td>${convertWind(hourly.wind_speed_10m[idx] ?? 0)}</td>
      <td>${convertWind(hourly.wind_gusts_10m[idx] ?? 0)}</td>
    </tr>
  `).join("");
}

function renderHourStrip(hourly) {
  el("hourStrip").innerHTML = hourly.time.slice(0, 12).map((time, idx) => {
    const label = new Date(time).toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" });
    const rain = hourly.precipitation_probability[idx] ?? 0;
    return `<div class="hour-card">
      <strong>${label}</strong>
      <span>${convertTemp(hourly.temperature_2m[idx])}</span>
      <small>${weatherText(hourly.weather_code[idx])}</small>
      <div class="bar"><i style="width:${Math.min(rain, 100)}%"></i></div>
      <small>Regen ${rain}% · Wind ${convertWind(hourly.wind_speed_10m[idx] ?? 0)}</small>
    </div>`;
  }).join("");
}

async function loadObservations() {
  const loc = getLocation();
  try {
    const data = await api(`/api/observations?lat=${loc.lat}&lon=${loc.lon}`);
    const weather = data.data.weather;
    const source = data.data.sources?.[0];
    if (!weather) throw new Error("Keine Beobachtung gefunden");
    el("obsTemp").textContent = convertTemp(weather.temperature);
    el("obsMeta").textContent = `${source?.station_name || "DWD Station"} · ${weather.timestamp || ""}`;
  } catch (err) {
    el("obsTemp").textContent = "–";
    el("obsMeta").textContent = `Keine DWD-Beobachtung: ${err.message}`;
  }
}

async function loadWarnings() {
  const loc = getLocation();
  const localOnly = el("warningsLocalOnly")?.checked ?? true;
  try {
    const data = await api(`/api/warnings?lat=${loc.lat}&lon=${loc.lon}&local_only=${localOnly}`);
    const warnings = data.warnings || [];
    el("warnCount").textContent = String(data.count_local ?? warnings.length);
    el("warnMeta").textContent = localOnly
      ? `${warnings.length} Warnung(en) für deinen Standort`
      : `${data.count_total} Warnungen bundesweit (Top ${warnings.length})`;

    const warncellEl = el("warncellInfo");
    if (localOnly && data.warncells?.length) {
      warncellEl.classList.remove("hidden");
      warncellEl.innerHTML = `Zugeordnete Warngebiete: ${data.warncells.map((a) => `<strong>${a.name}</strong> (${a.warncell_id})`).join(" · ")}`;
    } else {
      warncellEl.classList.add("hidden");
      warncellEl.innerHTML = "";
    }

    el("warningsList").innerHTML = warnings.length ? warnings.map((w) => `
      <article class="warning-card ${warnLevelClass(w.level)}">
        <div class="warning-head">
          <strong>${w.headline || w.event}</strong>
          <span class="warn-badge">Level ${w.level} · ${w.level_label}</span>
        </div>
        <p class="muted">${w.region_name || ""} · ${w.state || ""}</p>
        <p>${(w.description || "").replace(/\n/g, "<br>")}</p>
        ${w.instruction ? `<p class="instruction">${w.instruction}</p>` : ""}
        <small class="muted">Gültig: ${w.start ? formatDateTime(w.start) : "–"} – ${w.end ? formatDateTime(w.end) : "–"}</small>
      </article>
    `).join("") : `<p class="muted">${localOnly ? "Keine aktiven Warnungen für deinen Standort." : "Keine Warnungen verfügbar."}</p>`;
  } catch (err) {
    el("warnCount").textContent = "–";
    el("warnMeta").textContent = err.message;
    el("warningsList").innerHTML = `<p class="muted">Warnungen nicht verfügbar: ${err.message}</p>`;
    el("warncellInfo")?.classList.add("hidden");
  }
}

async function loadRadarFiles() {
  const latest = await api("/api/radar/latest?limit=12");
  el("radarCount").textContent = `${latest.count} online`;
  el("radarMeta").textContent = `Produkt ${latest.product.toUpperCase()} · DWD OpenData`;
  const local = await api("/api/radar/files");
  el("radarFiles").innerHTML = local.files.length ? local.files.slice().reverse().map((file) => `
    <tr><td>${file.name}</td><td>${formatBytes(file.size_bytes)}</td>
    <td>${new Date(file.modified_utc).toLocaleString("de-DE")}</td>
    <td><a href="${file.download_url}">Download</a></td></tr>
  `).join("") : `<tr><td colspan="4" class="muted">Noch keine lokalen Radar-Dateien.</td></tr>`;
  try {
    const rendered = await api("/api/radar/rendered?limit=12");
    renderedFrames = rendered.frames || [];
    el("renderedCount").textContent = `${rendered.count} Frame(s)`;
    el("renderedFrames").innerHTML = renderedFrames.length ? renderedFrames.map((f) => `
      <figure class="rendered-frame">
        <img src="${f.image_url}" alt="Radar ${f.filename}" loading="lazy" />
        <figcaption>${f.filename}</figcaption>
      </figure>
    `).join("") : `<p class="muted">Noch keine gerenderten Frames. Renderer-Worker abwarten.</p>`;
  } catch {
    el("renderedCount").textContent = "–";
    el("renderedFrames").innerHTML = `<p class="muted">Renderer nicht verfügbar.</p>`;
  }
}

async function syncRadar() {
  const button = el("syncRadarBtn");
  button.disabled = true;
  button.textContent = "Sync läuft…";
  try {
    await api("/api/radar/sync?limit=6", { method: "POST" });
    await loadRadarFiles();
  } finally {
    button.disabled = false;
    button.textContent = "Radar jetzt syncen";
  }
}

async function loadSources() {
  try {
    const data = await api("/api/sources");
    el("sourceList").innerHTML = Object.entries(data).map(([key, value]) => `
      <div class="source-item"><span>${key}</span><code>${String(value)}</code></div>
    `).join("");
  } catch (err) {
    el("sourceList").innerHTML = `<p class="muted">${err.message}</p>`;
  }
}

function setRadarTime(index) {
  if (!radarTimes.length) return;
  radarFrameIndex = Math.max(0, Math.min(index, radarTimes.length - 1));
  const time = radarTimes[radarFrameIndex];
  el("radarSlider").value = radarFrameIndex;
  el("radarTimeLabel").textContent = formatDateTime(time);
  el("radarFrameInfo").textContent = `Frame ${radarFrameIndex + 1} / ${radarTimes.length}`;

  if (el("useLocalRadar").checked && renderedFrames.length) {
    showLocalRadarFrame(radarFrameIndex);
  } else if (radarLayer) {
    radarLayer.setParams({ TIME: time, _cache: Date.now() });
  }
}

function showLocalRadarFrame(index) {
  if (!map) return;
  const frame = renderedFrames[Math.min(index, renderedFrames.length - 1)];
  if (!frame?.bounds) return;
  const b = frame.bounds;
  const bounds = [[b.south, b.west], [b.north, b.east]];
  if (localRadarOverlay) map.removeLayer(localRadarOverlay);
  localRadarOverlay = L.imageOverlay(frame.image_url + `?t=${Date.now()}`, bounds, { opacity: 0.75 });
  localRadarOverlay.addTo(map);
}

async function loadRadarTimes() {
  const layer = radarLayer?.wmsParams?.layers || "dwd:Niederschlagsradar";
  const minutes = settings.radarMinutes || 120;
  try {
    const data = await api(`/api/radar/wms/times?layer=${encodeURIComponent(layer)}&minutes=${minutes}`);
    radarTimes = data.times || [];
    el("radarSlider").max = Math.max(0, radarTimes.length - 1);
    if (radarTimes.length) setRadarTime(radarTimes.length - 1);
    else el("radarTimeLabel").textContent = "Keine Zeitschritte";
  } catch (err) {
    el("radarTimeLabel").textContent = `Zeitleiste: ${err.message}`;
  }
}

function toggleRadarPlay() {
  if (radarPlaying) {
    clearInterval(radarPlayTimer);
    radarPlayTimer = null;
    radarPlaying = false;
    el("radarPlayBtn").textContent = "▶";
    return;
  }
  if (radarTimes.length < 2) return;
  radarPlaying = true;
  el("radarPlayBtn").textContent = "⏸";
  radarPlayTimer = setInterval(() => {
    const next = radarFrameIndex + 1;
    if (next >= radarTimes.length) setRadarTime(0);
    else setRadarTime(next);
  }, 800);
}

async function initMap() {
  if (map || typeof L === "undefined") return;
  const loc = getLocation();
  map = L.map("map", { zoomControl: true }).setView([loc.lat, loc.lon], 8);
  osmLayer = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
    maxZoom: 19,
    attribution: "&copy; OpenStreetMap-Mitwirkende",
  }).addTo(map);
  mapMarker = L.marker([loc.lat, loc.lon]).addTo(map).bindPopup(loc.place);

  try {
    const config = await api("/api/radar/wms");
    const overlays = {};
    wmsLayers = config.layers.map((layer) => {
      const wms = L.tileLayer.wms(config.service_url, {
        layers: layer.layer,
        format: "image/png",
        transparent: true,
        version: "1.1.1",
        opacity: layer.opacity ?? 0.7,
        attribution: config.attribution,
      });
      overlays[layer.title] = wms;
      if (layer.id === "niederschlagsradar") radarLayer = wms;
      if (layer.id === "warnungen_gemeinden") warningLayer = wms;
      if (layer.enabled) wms.addTo(map);
      return { ...layer, instance: wms };
    });
    layerControl = L.control.layers({ "OpenStreetMap": osmLayer }, overlays, { collapsed: false }).addTo(map);
    el("mapMeta").textContent = "DWD Radar + Warnungen aktiv";
    await loadRadarTimes();
  } catch (err) {
    el("mapMeta").textContent = `Karte: ${err.message}`;
  }
}

function updateMapLocation() {
  if (!map || !mapMarker) return;
  const loc = getLocation();
  map.setView([loc.lat, loc.lon], Math.max(map.getZoom(), 8));
  mapMarker.setLatLng([loc.lat, loc.lon]).bindPopup(loc.place);
}

function reloadRadarLayers() {
  wmsLayers.forEach((layer) => {
    if (map?.hasLayer(layer.instance)) layer.instance.setParams({ _cache: Date.now() });
  });
  loadRadarTimes();
}

function toggleWarningsOnMap() {
  if (!warningLayer || !map) return;
  if (el("showWarningsOnMap").checked) warningLayer.addTo(map);
  else map.removeLayer(warningLayer);
}

async function searchPlaces(query) {
  if (query.length < 2) {
    el("searchResults").classList.add("hidden");
    return;
  }
  try {
    const data = await api(`/api/geocode/search?q=${encodeURIComponent(query)}`);
    const results = data.results || [];
    el("searchResults").innerHTML = results.length ? results.map((r, i) => `
      <li role="option" data-index="${i}">
        <strong>${r.place}</strong>
        <span>${r.label}</span>
      </li>
    `).join("") : `<li class="muted">Keine Treffer</li>`;
    el("searchResults").classList.remove("hidden");
    el("searchResults").querySelectorAll("li[data-index]").forEach((item) => {
      item.addEventListener("click", () => {
        const r = results[Number(item.dataset.index)];
        setLocation({ place: r.place, lat: r.lat, lon: r.lon });
        el("searchResults").classList.add("hidden");
        loadAll();
      });
    });
  } catch {
    el("searchResults").innerHTML = `<li class="muted">Suche fehlgeschlagen</li>`;
    el("searchResults").classList.remove("hidden");
  }
}

function renderFavorites() {
  const favs = loadFavorites();
  const panel = el("favoritesPanel");
  if (!favs.length) { panel.classList.add("hidden"); return; }
  panel.classList.remove("hidden");
  el("favoritesList").innerHTML = favs.map((f, i) => `
    <button class="chip" data-index="${i}">${f.place}</button>
  `).join("");
  el("favoritesList").querySelectorAll(".chip").forEach((btn) => {
    btn.addEventListener("click", () => {
      const f = favs[Number(btn.dataset.index)];
      setLocation(f);
      loadAll();
    });
  });
}

function addFavorite() {
  const loc = getLocation();
  const favs = loadFavorites().filter((f) => f.place !== loc.place || f.lat !== loc.lat);
  favs.unshift(loc);
  saveFavorites(favs.slice(0, 8));
  renderFavorites();
}

function useGeolocation() {
  if (!navigator.geolocation) return;
  navigator.geolocation.getCurrentPosition(async (pos) => {
    const lat = pos.coords.latitude;
    const lon = pos.coords.longitude;
    try {
      const data = await api(`/api/geocode/reverse?lat=${lat}&lon=${lon}`);
      setLocation({ place: data.result?.place || "GPS-Standort", lat, lon });
    } catch {
      setLocation({ place: "GPS-Standort", lat, lon });
    }
    loadAll();
  });
}

function applyTheme() {
  document.documentElement.dataset.theme = settings.theme;
  el("themeToggle").textContent = settings.theme === "dark" ? "🌙" : "☀️";
}

function applySettingsToUI() {
  el("unitTemp").value = settings.unitTemp;
  el("unitWind").value = settings.unitWind;
  el("radarMinutes").value = String(settings.radarMinutes);
  applyTheme();
}

async function loadDefaultLocation() {
  const stored = settings.defaultLocation;
  if (stored) { setLocation(stored); return; }
  try {
    const data = await api("/api/location/default");
    setLocation(data);
  } catch { /* fallback values in HTML */ }
}

function activateView(name) {
  document.querySelectorAll(".tab").forEach((tab) => tab.classList.toggle("active", tab.dataset.view === name));
  document.querySelectorAll(".view").forEach((view) => view.classList.toggle("active", view.dataset.view === name));
  if (name === "radar") initMap().then(() => setTimeout(() => map?.invalidateSize(), 150));
  if (name === "warnings") loadWarnings();
}

async function loadAll() {
  await loadHealth();
  await Promise.allSettled([loadForecast(), loadObservations(), loadRadarFiles(), loadSources(), loadWarnings()]);
  updateMapLocation();
  if (map) loadRadarTimes();
}

async function init() {
  applySettingsToUI();
  await loadDefaultLocation();
  renderFavorites();
  await loadAll();
  setInterval(loadHealth, 30000);
}

document.querySelectorAll(".tab").forEach((tab) => tab.addEventListener("click", () => activateView(tab.dataset.view)));
el("loadBtn").addEventListener("click", loadAll);
el("syncRadarBtn").addEventListener("click", syncRadar);
el("centerMapBtn").addEventListener("click", updateMapLocation);
el("reloadRadarLayersBtn").addEventListener("click", reloadRadarLayers);
el("favBtn").addEventListener("click", addFavorite);
el("geoBtn").addEventListener("click", useGeolocation);
el("warningsLocalOnly")?.addEventListener("change", loadWarnings);
el("showWarningsOnMap")?.addEventListener("change", toggleWarningsOnMap);
el("useLocalRadar")?.addEventListener("change", () => setRadarTime(radarFrameIndex));

el("radarPlayBtn").addEventListener("click", toggleRadarPlay);
el("radarPrevBtn").addEventListener("click", () => setRadarTime(radarFrameIndex - 1));
el("radarNextBtn").addEventListener("click", () => setRadarTime(radarFrameIndex + 1));
el("radarFirstBtn").addEventListener("click", () => setRadarTime(0));
el("radarLastBtn").addEventListener("click", () => setRadarTime(radarTimes.length - 1));
el("radarSlider").addEventListener("input", (e) => setRadarTime(Number(e.target.value)));

el("placeSearch").addEventListener("input", (e) => {
  clearTimeout(searchTimer);
  searchTimer = setTimeout(() => searchPlaces(e.target.value.trim()), 300);
});
document.addEventListener("click", (e) => {
  if (!e.target.closest(".search-wrap")) el("searchResults").classList.add("hidden");
});

el("themeToggle").addEventListener("click", () => {
  settings.theme = settings.theme === "dark" ? "light" : "dark";
  saveSettings();
  applyTheme();
});

["unitTemp", "unitWind", "radarMinutes"].forEach((id) => {
  el(id).addEventListener("change", (e) => {
    const key = id === "radarMinutes" ? "radarMinutes" : id.replace("unit", "unit").replace("Temp", "Temp").replace("Wind", "Wind");
    if (id === "unitTemp") settings.unitTemp = e.target.value;
    if (id === "unitWind") settings.unitWind = e.target.value;
    if (id === "radarMinutes") settings.radarMinutes = Number(e.target.value);
    saveSettings();
    if (latestForecast) { renderDaily(latestForecast.data.daily); renderHourly(latestForecast.data.hourly); renderHourStrip(latestForecast.data.hourly); loadForecast(); }
    if (id === "radarMinutes" && map) loadRadarTimes();
  });
});

el("saveDefaultLocationBtn").addEventListener("click", () => {
  settings.defaultLocation = getLocation();
  saveSettings();
  el("saveDefaultLocationBtn").textContent = "Gespeichert ✓";
  setTimeout(() => { el("saveDefaultLocationBtn").textContent = "Aktuellen Ort als Standard speichern"; }, 2000);
});

init();
