/* =========================================================
  Weather App (single root page)
  - Landing designs: theme-1 / theme-2 / theme-3
  - Forecast UI: 1 / 2 / 3
  - Live OpenWeather: current + 3-hour forecast
  - Map widget: OpenStreetMap embed
========================================================= */

(() => {
  const $ = (sel) => document.querySelector(sel);
  const $$ = (sel) => Array.from(document.querySelectorAll(sel));

  // Storage key for API key
  const LS_KEY = "owm_api_key";

  // State
  const state = {
    view: "landing",  // landing | forecast
    theme: 1,         // 1..3
    ui: 1,            // 1..3
    city: "London",
    data: null
  };

  // Elements
  const viewLanding = $("#viewLanding");
  const viewForecast = $("#viewForecast");
  const badgeTheme = $("#badgeTheme");

  const btnKey = $("#btnKey");
  const keyModal = $("#keyModal");
  const btnCloseModal = $("#btnCloseModal");
  const apiKeyInput = $("#apiKeyInput");
  const btnSaveKey = $("#btnSaveKey");

  const msg = $("#msg");
  const cityTitle = $("#cityTitle");
  const uiRoot = $("#uiRoot");

  const searchForm = $("#searchForm");
  const cityInput = $("#cityInput");

  // -------------------- Helpers --------------------
  function setMsg(text, type = "") {
    if (!msg) return;
    msg.className = "msg " + type;
    msg.textContent = text || "";
  }

  function setBodyTheme(n) {
    document.body.classList.remove("theme-1", "theme-2", "theme-3");
    document.body.classList.add(`theme-${n}`);
    state.theme = n;
    if (badgeTheme) badgeTheme.textContent = `Landing ${n}`;
  }

  function setView(view) {
    state.view = view;

    // top nav chips
    $$(".chip[data-view]").forEach(b => b.classList.toggle("is-active", b.dataset.view === view));

    // views
    viewLanding.classList.toggle("is-active", view === "landing");
    viewForecast.classList.toggle("is-active", view === "forecast");

    if (view === "forecast") {
      // ensure we have something rendered
      render();
      // scroll to top of forecast section
      viewForecast.scrollIntoView({ behavior: "smooth", block: "start" });
    } else {
      viewLanding.scrollIntoView({ behavior: "smooth", block: "start" });
    }
  }

  function setUI(n) {
    state.ui = n;
    $$(".segBtn").forEach(b => b.classList.toggle("is-active", Number(b.dataset.ui) === n));
    render();
  }

  function getApiKey() {
    return localStorage.getItem(LS_KEY) || "";
  }

  function openModal() {
    apiKeyInput.value = getApiKey();
    keyModal.classList.add("is-open");
    keyModal.setAttribute("aria-hidden", "false");
    setTimeout(() => apiKeyInput.focus(), 0);
  }

  function closeModal() {
    keyModal.classList.remove("is-open");
    keyModal.setAttribute("aria-hidden", "true");
  }

  function saveKey() {
    const key = (apiKeyInput.value || "").trim();
    if (!key) {
      localStorage.removeItem(LS_KEY);
      closeModal();
      setMsg("API key cleared. Paste a valid key to use live data.", "bad");
      return;
    }
    localStorage.setItem(LS_KEY, key);
    closeModal();
    setMsg("API key saved. Loading weather…", "ok");
    loadCity(state.city).catch(() => {});
  }

  function iconUrl(code) {
    return `https://openweathermap.org/img/wn/${code}@2x.png`;
  }

  function fmtTime(dtTxt) {
    // "2026-01-04 03:00:00" -> "03:00"
    return (dtTxt || "").split(" ")[1]?.slice(0, 5) || "--:--";
  }

  function fmtDate(d) {
    return d.toLocaleDateString(undefined, { day:"2-digit", month:"long", year:"numeric" });
  }

  async function fetchJson(url) {
    const res = await fetch(url);
    if (!res.ok) {
      let extra = "";
      try { extra = (await res.json()).message || ""; } catch (e) {}
      throw new Error(extra || `Request failed: ${res.status}`);
    }
    return res.json();
  }

  function osmEmbed(lat, lon) {
    // Simple OSM embed with marker (no API key needed)
    // bbox is just a small window around point
    const d = 0.25; // degrees
    const left = (lon - d).toFixed(5);
    const right = (lon + d).toFixed(5);
    const top = (lat + d).toFixed(5);
    const bottom = (lat - d).toFixed(5);

    const src =
      `https://www.openstreetmap.org/export/embed.html?bbox=${left}%2C${bottom}%2C${right}%2C${top}` +
      `&layer=mapnik&marker=${lat.toFixed(5)}%2C${lon.toFixed(5)}`;

    return src;
  }

  // -------------------- Data loading --------------------
  async function loadCity(city) {
    const API_KEY = getApiKey();
    if (!API_KEY) {
      setMsg("No API key set. Click “API Key” and paste your OpenWeather key.", "bad");
      state.data = null;
      render(); // render placeholder UI
      return;
    }

    setMsg("Loading…", "ok");

    const wUrl =
      `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city)}` +
      `&appid=${API_KEY}&units=metric`;

    const fUrl =
      `https://api.openweathermap.org/data/2.5/forecast?q=${encodeURIComponent(city)}` +
      `&appid=${API_KEY}&units=metric`;

    const [w, f] = await Promise.all([fetchJson(wUrl), fetchJson(fUrl)]);

    const lat = w.coord?.lat ?? null;
    const lon = w.coord?.lon ?? null;

    state.city = city;
    state.data = {
      city: w.name || city,
      country: w.sys?.country || "",
      desc: w.weather?.[0]?.description || "—",
      main: w.weather?.[0]?.main || "—",
      icon: w.weather?.[0]?.icon || "",
      temp: Math.round(w.main?.temp ?? 0),
      feels: Math.round(w.main?.feels_like ?? 0),
      humidity: w.main?.humidity ?? "--",
      wind: (w.wind?.speed ?? "--"),
      pressure: w.main?.pressure ?? "--",
      clouds: w.clouds?.all ?? "--",
      precip: (w.rain?.["1h"] ?? 0),
      date: fmtDate(new Date()),
      lat,
      lon,
      forecast: (f.list || []).slice(0, 8).map(it => ({
        time: fmtTime(it.dt_txt),
        temp: Math.round(it.main?.temp ?? 0),
        main: it.weather?.[0]?.main || "",
        desc: it.weather?.[0]?.description || "",
        icon: it.weather?.[0]?.icon || ""
      }))
    };

    cityTitle.textContent = state.data.city;
    setMsg("");
    render();
  }

  // -------------------- Rendering --------------------
  function renderPlaceholder() {
    const needsKey = !getApiKey();
    return `
      <div class="ui ui2" style="padding:16px;">
        <div style="font-weight:950; font-size:18px;">No live data yet</div>
        <div style="margin-top:6px; color:rgba(234,242,255,.78); font-weight:800;">
          ${needsKey
            ? `Click <b>API Key</b> to paste your OpenWeather key.`
            : `Search a city to load weather.`}
        </div>
      </div>
    `;
  }

  function renderUI1(d) {
    const mapSrc = (d.lat != null && d.lon != null) ? osmEmbed(d.lat, d.lon) : "";
    const fc = (d.forecast || []).map(x => `
      <div class="fCard">
        <div class="t">${x.time}</div>
        <img src="${x.icon ? iconUrl(x.icon) : ""}" alt="" />
        <div class="v">${x.temp}°C</div>
        <div class="m">${x.main}</div>
      </div>
    `).join("");

    return `
      <section class="ui ui1">
        <div class="uiTop">
          <div>
            <div class="title">${d.city}${d.country ? ", " + d.country : ""}</div>
            <div class="sub">${d.date} • Current + forecast</div>
          </div>
          <button class="greenBtn" type="button" onclick="window.scrollTo({top:0,behavior:'smooth'})">
            <i class="fa-solid fa-arrow-up"></i> Top
          </button>
        </div>

        <div class="uiBody">
          <div class="card">
            <div class="nowRow">
              <div>
                <div class="temp">${d.temp}°C</div>
                <div class="desc">${d.desc}</div>
              </div>
              <img class="icon" src="${d.icon ? iconUrl(d.icon) : ""}" alt="icon" />
            </div>

            <div class="meta">
              <div><span>Feels</span><b>${d.feels}°C</b></div>
              <div><span>Humidity</span><b>${d.humidity}%</b></div>
              <div><span>Wind</span><b>${d.wind} m/s</b></div>
              <div><span>Pressure</span><b>${d.pressure} hPa</b></div>
            </div>
          </div>

          <div class="card mapCard">
            <b style="display:block; font-weight:950; margin-bottom:10px;">Map widget</b>
            ${mapSrc ? `<iframe loading="lazy" referrerpolicy="no-referrer-when-downgrade" src="${mapSrc}"></iframe>`
                     : `<div style="color:#64748b; font-weight:900;">Map unavailable</div>`}
          </div>

          <div class="card" style="grid-column:1/-1;">
            <div style="display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:10px;">
              <b style="font-weight:950;">Forecast</b>
              <span style="color:#64748b; font-weight:900; font-size:12px;">Next 8 × 3h</span>
            </div>
            <div class="forecastGrid">${fc}</div>
          </div>
        </div>
      </section>
    `;
  }

  function renderUI2(d) {
    const mapSrc = (d.lat != null && d.lon != null) ? osmEmbed(d.lat, d.lon) : "";
    const list = (d.forecast || []).map(x => `
      <div class="item">
        <div class="time">${x.time}</div>
        <div class="mid">
          <img src="${x.icon ? iconUrl(x.icon) : ""}" alt="" />
          <div>
            <div class="main">${x.main}</div>
            <div class="sub">${x.desc}</div>
          </div>
        </div>
        <div class="val">${x.temp}°C</div>
      </div>
    `).join("");

    return `
      <section class="ui ui2">
        <div class="uiBody">
          <div class="mapWrap">
            ${mapSrc ? `<iframe loading="lazy" referrerpolicy="no-referrer-when-downgrade" src="${mapSrc}"></iframe>` : ""}
            <div class="overlay"></div>

            <div class="widget">
              <div class="bigTemp">${d.temp}°C</div>

              <div class="descRow">
                <img src="${d.icon ? iconUrl(d.icon) : ""}" alt="" />
                <div>
                  <div class="d">${d.desc}</div>
                  <div class="s">${d.city}${d.country ? ", " + d.country : ""}</div>
                </div>
              </div>

              <div class="wGrid">
                <div><span>Feels like</span><b>${d.feels}°C</b></div>
                <div><span>Precip (1h)</span><b>${Number(d.precip).toFixed(2)} mm</b></div>
                <div><span>Wind</span><b>${d.wind} m/s</b></div>
                <div><span>Humidity</span><b>${d.humidity}%</b></div>
                <div><span>Clouds</span><b>${d.clouds}%</b></div>
                <div><span>Pressure</span><b>${d.pressure} hPa</b></div>
              </div>
            </div>
          </div>

          <aside class="panel">
            <div class="panelTop">
              <b>Forecast (3h)</b>
              <div class="date">${d.date}</div>
            </div>
            <div class="list">${list}</div>
          </aside>
        </div>
      </section>
    `;
  }

  function renderUI3(d) {
    const mapSrc = (d.lat != null && d.lon != null) ? osmEmbed(d.lat, d.lon) : "";
    const cards = (d.forecast || []).map(x => `
      <div class="fCard">
        <div class="t">${x.time}</div>
        <img src="${x.icon ? iconUrl(x.icon) : ""}" alt="" />
        <div class="v">${x.temp}°C</div>
        <div class="m">${x.main}</div>
      </div>
    `).join("");

    return `
      <section class="ui ui3">
        <div class="uiBody">
          <div class="topCard">
            <div class="topRow">
              <div>
                <div class="temp">${d.temp}°C</div>
                <div class="desc">${d.city}${d.country ? ", " + d.country : ""} • ${d.desc}</div>
              </div>
              <img src="${d.icon ? iconUrl(d.icon) : ""}" alt="" />
            </div>

            <div class="chips">
              <div class="chipCard"><i class="fa-solid fa-temperature-half"></i> Feels: ${d.feels}°C</div>
              <div class="chipCard"><i class="fa-solid fa-droplet"></i> Humidity: ${d.humidity}%</div>
              <div class="chipCard"><i class="fa-solid fa-wind"></i> Wind: ${d.wind} m/s</div>
              <div class="chipCard"><i class="fa-solid fa-gauge-high"></i> ${d.pressure} hPa</div>
            </div>
          </div>

          <div class="topCard">
            <div style="display:flex; justify-content:space-between; align-items:center; gap:10px; margin-bottom:10px;">
              <b style="font-weight:950;">Forecast</b>
              <span style="color:rgba(234,242,255,.75); font-weight:900; font-size:12px;">Next 8 × 3h</span>
            </div>
            <div class="grid">${cards}</div>
          </div>

          <div class="mapMini">
            ${mapSrc ? `<iframe loading="lazy" referrerpolicy="no-referrer-when-downgrade" src="${mapSrc}"></iframe>` : ""}
          </div>
        </div>
      </section>
    `;
  }

  function render() {
    if (state.view !== "forecast") return;

    if (!state.data) {
      uiRoot.innerHTML = renderPlaceholder();
      cityTitle.textContent = "—";
      return;
    }

    const d = state.data;
    cityTitle.textContent = d.city;

    if (state.ui === 1) uiRoot.innerHTML = renderUI1(d);
    else if (state.ui === 2) uiRoot.innerHTML = renderUI2(d);
    else uiRoot.innerHTML = renderUI3(d);
  }

  // -------------------- Events --------------------
  // View switch buttons
  $$(".chip[data-view]").forEach(btn => {
    btn.addEventListener("click", () => setView(btn.dataset.view));
  });

  // Landing theme buttons
  $$("button[data-theme]").forEach(btn => {
    btn.addEventListener("click", () => {
      const n = Number(btn.dataset.theme);
      setBodyTheme(n);
    });
  });

  // Landing -> Forecast buttons
  $$("button[data-go='forecast']").forEach(btn => {
    btn.addEventListener("click", () => {
      const ui = Number(btn.dataset.ui || "1");
      setView("forecast");
      setUI(ui);
    });
  });

  // Forecast UI switcher
  $$(".segBtn").forEach(btn => {
    btn.addEventListener("click", () => setUI(Number(btn.dataset.ui)));
  });

  // Search
  searchForm.addEventListener("submit", (e) => {
    e.preventDefault();
    const city = (cityInput.value || "").trim();
    if (!city) return setMsg("Type a city name first.", "bad");
    loadCity(city).catch(err => setMsg("Error: " + err.message, "bad"));
  });

  // Modal controls
  btnKey.addEventListener("click", openModal);
  btnCloseModal.addEventListener("click", closeModal);
  keyModal.addEventListener("click", (e) => {
    if (e.target === keyModal) closeModal();
  });
  btnSaveKey.addEventListener("click", saveKey);

  // ESC closes modal
  document.addEventListener("keydown", (e) => {
    if (e.key === "Escape") closeModal();
  });

  // -------------------- Boot --------------------
  setBodyTheme(1);
  setUI(1);

  // If they already have a key, preload data once they open forecast.
  // Also try a silent preload right away (won't show anything until forecast view).
  loadCity(state.city).catch(() => {});
})();
