(function ($) {
  "use strict";

  const state = {
    spTimer: null,
    spEnabled: true,
    activeId: null
  };

  function showToast(msg) {
    const $toast = $("#appToast");
    if (!$toast.length) return;
    $("#toastMsg").text(msg);
    const t = bootstrap.Toast.getOrCreateInstance($toast[0], { delay: 2600 });
    t.show();
  }

  function smoothScrollTo(hash) {
    const $target = $(hash);
    if (!$target.length) return;
    $("html, body").stop(true).animate(
      { scrollTop: $target.offset().top - 90 },
      450
    );
  }

  function openProjectModal(projectId) {
    const p = (window.PROJECTS || []).find(x => x.id === projectId);
    if (!p) return;

    $("#pmTitle").text(p.title + " • " + p.year);
    $("#pmSummary").text(p.summary);

    const $tech = $("#pmTech").empty();
    (p.tech || []).forEach(t => $("<span/>").addClass("tag").text(t).appendTo($tech));

    const $links = $("#pmLinks").empty();
    if (p.links && p.links.length) {
      p.links.forEach(l => {
        $("<a/>", {
          class: "btn btn-light btn-sm",
          href: l.url,
          target: "_blank",
          rel: "noreferrer"
        }).text(l.label).appendTo($links);
      });
    } else {
      $("<span/>", { class: "text-white/50 text-sm" }).text("No public links yet.").appendTo($links);
    }

    const $gallery = $("#pmGallery").empty();
    const imgs = Array.isArray(p.images) ? p.images : [];
    if (imgs.length) {
      imgs.forEach((url, idx) => {
        $("<a/>", {
          class: "pm-thumb",
          href: url,
          target: "_blank",
          rel: "noreferrer"
        }).append(
          $("<img/>", { src: url, alt: `${p.title} screenshot ${idx + 1}` })
        ).appendTo($gallery);
      });
    } else {
      $("<div/>", { class: "text-white/50 small" }).text("No screenshots yet.").appendTo($gallery);
    }

    const $modal = $("#projectModal");
    if ($modal.length) {
      const modal = bootstrap.Modal.getOrCreateInstance($modal[0]);
      modal.show();
    }
  }

  function applyProjectFilter(tag) {
    tag = (tag || "all").toString().toLowerCase();
    $(".chip").removeClass("active");
    $(`.chip[data-filter="${tag}"]`).addClass("active");

    $(".project-card").each(function () {
      const $c = $(this);
      const t = ($c.data("project-tag") || "").toString().toLowerCase();
      const show = (tag === "all") || (t === tag);
      if (show) $c.stop(true).fadeIn(140);
      else $c.stop(true).fadeOut(140);
    });
  }

  function animateBarsInView() {
    const winTop = $(window).scrollTop();
    const winBottom = winTop + $(window).height();

    $(".bar").each(function () {
      const $bar = $(this);
      if ($bar.data("done")) return;

      const top = $bar.offset().top;
      if (top < winBottom - 80) {
        const level = parseInt($bar.data("level"), 10) || 0;
        $bar.find(".bar-fill").css("width", Math.max(0, Math.min(level, 100)) + "%");
        $bar.data("done", true);
      }
    });
  }

  // Scrollspy (active navlink)
  function setActiveNav(id) {
    if (!id || state.activeId === id) return;
    state.activeId = id;

    $(".navlink").removeClass("is-active");
    $(`.navlink[href="#${id}"]`).addClass("is-active");
  }

  function initScrollSpy() {
    const ids = ["about", "projects", "stack", "gaming", "contact"];
    const $sections = ids
      .map(id => $("#" + id))
      .filter($el => $el.length);

    if (!$sections.length) return;

    const updateActive = () => {
      const y = $(window).scrollTop() + 120;
      let bestId = null;

      $sections.forEach($el => {
        const top = $el.offset().top;
        const bottom = top + $el.outerHeight();
        if (y >= top && y < bottom) bestId = $el.attr("id");
      });

      if (!bestId) {
        $sections.forEach($el => {
          if (y >= $el.offset().top - 40) bestId = $el.attr("id");
        });
      }

      if (bestId) setActiveNav(bestId);
    };

    updateActive();
    $(window).on("scroll resize", updateActive);
  }

  // Spotify
  function renderSpotify(payload) {
    const $card = $("#spotifyCard");

    if (!payload || !payload.ok) {
      $("#spStatus").text("Spotify not configured");
      $(".pulse-bars").hide();
      $card.removeClass("is-playing");
      return;
    }

    const mode = payload.mode; // playing | recent | offline
    const t = payload.track || {};

    $("#spTitle").text(t.title || "—");
    $("#spArtist").text(t.artist || "—");
    $("#spLink").attr("href", t.url || "#");

    if (t.art) $("#spArt").attr("src", t.art).show();
    else $("#spArt").removeAttr("src").hide();

    if (mode === "playing") {
      $("#spStatus").text("Now Playing");
      $(".pulse-bars").show();
      $card.addClass("is-playing");
    } else if (mode === "recent") {
      $("#spStatus").text("Last Played");
      $(".pulse-bars").hide();
      $card.removeClass("is-playing");
    } else {
      $("#spStatus").text("Offline");
      $(".pulse-bars").hide();
      $card.removeClass("is-playing");
    }
  }

  function fetchSpotify() {
    if (!state.spEnabled) return;

    $.ajax({
      url: "/api/spotify.php",
      method: "GET",
      dataType: "json",
      cache: false,
      timeout: 8000
    })
      .done(renderSpotify)
      .fail(function () {
        $("#spStatus").text("Spotify unavailable");
        $(".pulse-bars").hide();
      });
  }

  // Spotify Widget
var SpotifyWidget = (function ($) {
  var cfg = { endpoint: '/api/spotify.php' };

  var $widget, $song, $artist, $status, $link, $visualizer;
  var $artEl; // could be <img> or <div>

  function init() {
    $widget = $('#spotify-widget');
    $song = $('#spotify-song');
    $artist = $('#spotify-artist');
    $status = $('#spotify-status-text');
    $link = $('#spotify-link');
    $visualizer = $('.eq-visualizer');
    $artEl = $('#spotify-art');

    // Replace the low-contrast logo with a badge (same idea as your JS)
    var $logoImg = $('.spotify-logo-icon');
    if ($logoImg.length) {
      var $badge = $('<span/>', {
        'class': 'spotify-badge',
        'role': 'img',
        'aria-label': 'Spotify',
        'text': 'Spotify'
      });
      $logoImg.replaceWith($badge);
    }

    update();
    setInterval(update, 15000);
  }

  function update() {
    $.ajax({
      url: cfg.endpoint,
      method: 'GET',
      dataType: 'json',
      cache: false
    })
    .done(function (data) {
      if (!data || data.ok !== true) {
        hide();
        return;
      }
      if (data.mode === 'offline') {
        hide();
        return;
      }
      render(data);
    })
    .fail(function (xhr) {
      console.warn('Spotify widget API failed:', xhr.status, xhr.responseText);
      hide();
    });
  }

  function hide() {
    $widget.addClass('hidden');
  }

  function render(data) {
    var t = (data.track || {});
    $widget.removeClass('hidden');

    $song.text(t.title || 'Not Playing');
    $artist.text(t.artist || 'Spotify');
    $link.attr('href', t.url || '#');

    // album art
    if (t.art) {
      if ($artEl.prop('tagName') === 'IMG') {
        $artEl.attr('src', t.art);
        $artEl.attr('alt', (t.title || 'Track') + ' album art');
      } else {
        $artEl.css({
          backgroundImage: "url('" + t.art + "')",
          backgroundSize: 'cover',
          backgroundPosition: 'center'
        });
        $artEl.find('i[data-feather]').remove();
      }
    }

    if (data.mode === 'playing') {
      $status.text('Now Playing');
      $visualizer.css('display', 'flex');
    } else {
      $status.text('Last Played');
      $visualizer.css('display', 'none');
    }

    // marquee if long
    if ((t.title || '').length > 25) {
      $song.css('animation', 'marquee 10s linear infinite');
    } else {
      $song.css('animation', 'none');
    }
  }

  return { init: init };
})(jQuery);


    // Contact form (AJAX)
  function bindContactForm() {
    const contactEndpoint = (window.CONTACT_ENDPOINT || "/api/contact.php");
    $("#contactForm").on("submit", function (e) {
      e.preventDefault();

      const $form = $(this);
      const $btn = $form.find("button[type=submit]");
      $btn.prop("disabled", true);
      const payload = $form.serialize();

      $.ajax({
        url: contactEndpoint,
        method: "POST",
        dataType: "json",
        data: payload,
        timeout: 12000
      })
        .done(handleRes)
        .fail(function () {
          showToast("Network error while sending.");
        })
        .always(function () {
          $btn.prop("disabled", false);
        });

      function handleRes(res) {
        if (res && res.ok) {
          showToast("Message sent.");
          $form[0].reset();
        } else {
          showToast((res && res.error) ? res.error : "Could not send.");
        }
      }
    });
  }

  // Init
  $(function () {
    // Smooth scroll
    $(document).on("click", "a[data-scroll], a[href^='#']", function (e) {
      const href = $(this).attr("href");
      if (!href || href === "#") return;
      if (href.startsWith("#")) {
        e.preventDefault();
        smoothScrollTo(href);

        // update nav immediately on click
        setActiveNav(href.replace("#", ""));

        // close offcanvas if open
        const $off = $("#mobileNav");
        if ($off.length) bootstrap.Offcanvas.getOrCreateInstance($off[0]).hide();
      }
    });

    // Project card click
    $(".project-card").on("click", function () {
      openProjectModal($(this).data("project-id"));
    });

    // Filter chips
    $(".chip").on("click", function () {
      applyProjectFilter($(this).data("filter"));
    });

    // Bars
    animateBarsInView();
    $(window).on("scroll", animateBarsInView);

    // Scrollspy active nav animation
    initScrollSpy();

    // Contact
    bindContactForm();

    // Spotify polling
    fetchSpotify();
    state.spTimer = setInterval(fetchSpotify, 20000);
  });

})(jQuery);
