(() => {
  "use strict";

  const MAX_ITEMS = 50;
  const MAX_NAME_LENGTH = 80;
  const MAX_URL_LENGTH = 1000;
  const LOCAL_VOLUME_KEY = "sekagent-radio-volume-v1";
  const LOCAL_COLLAPSED_KEY = "sekagent-radio-collapsed-v1";
  const LOCAL_REPEAT_KEY = "sekagent-radio-repeat-v1";
  const HISTORY_LIMIT = 50;
  const YOUTUBE_API_TIMEOUT_MS = 15000;
  const YOUTUBE_EMBED_ORIGIN = "https://www.youtube-nocookie.com";
  const YOUTUBE_MESSAGE_ORIGINS = new Set([
    YOUTUBE_EMBED_ORIGIN,
    "https://www.youtube.com",
  ]);

  const elements = {
    root: document.querySelector("#radioPlayer"),
    collapse: document.querySelector("#radioPlayerCollapse"),
    expand: document.querySelector("#radioPlayerExpand"),
    close: document.querySelector("#radioPlayerClose"),
    playPause: document.querySelector("#radioPlayPause"),
    previous: document.querySelector("#radioPrevious"),
    next: document.querySelector("#radioNext"),
    repeat: document.querySelector("#radioRepeat"),
    title: document.querySelector("#radioPlayerTitle"),
    status: document.querySelector("#radioPlayerStatus"),
    popoverTitle: document.querySelector("#radioPopoverTitle"),
    popoverStatus: document.querySelector("#radioPopoverStatus"),
    error: document.querySelector("#radioPlayerError"),
    volume: document.querySelector("#radioVolume"),
    volumeValue: document.querySelector("#radioVolumeValue"),
    openSettings: document.querySelector("#radioOpenSettings"),
    audio: document.querySelector("#radioNativeAudio"),
    youtubeHost: document.querySelector("#radioYoutubeHost"),
    playlistDialog: document.querySelector("#radioPlaylistDialog"),
    playlistForm: document.querySelector("#radioPlaylistForm"),
    playlistClose: document.querySelector("#closeRadioPlaylist"),
    playlistCancel: document.querySelector("#cancelRadioPlaylist"),
    settingsLinks: document.querySelector("#radioLinksSetting"),
    settingsVisible: document.querySelector("#radioDockVisibleSetting"),
    settingsShuffle: document.querySelector("#radioShuffleSetting"),
    settingsSummary: document.querySelector("#radioSettingsSummary"),
    settingsError: document.querySelector("#radioSettingsError"),
  };

  let settings = normalizeSettings(null);
  let queue = [];
  let queueCursor = 0;
  let currentItem = null;
  let currentSource = "";
  let isPlaying = false;
  let youtubeFrame = null;
  let youtubeReady = false;
  let youtubeHandshakeTimer = null;
  let youtubeReadyTimer = null;
  let sourceChangeToken = 0;
  let dockCollapsed = false;
  let currentTrackTitle = "";
  let trackNotificationPending = false;
  let repeatOne = false;
  let playbackHistory = [];

  function clampVolume(value) {
    const number = Number(value);
    if (!Number.isFinite(number)) return 0.35;
    return Math.min(1, Math.max(0, number));
  }

  function getSavedLocalCollapsed() {
    try {
      return localStorage.getItem(LOCAL_COLLAPSED_KEY) === "true";
    } catch {
      return false;
    }
  }

  function saveLocalCollapsed(collapsed) {
    try {
      localStorage.setItem(LOCAL_COLLAPSED_KEY, String(collapsed));
    } catch {
    }
  }

  function setDockCollapsed(collapsed, { save = true } = {}) {
    dockCollapsed = Boolean(collapsed);
    elements.root?.classList.toggle("radio-dock--collapsed", dockCollapsed);
    elements.root?.setAttribute("aria-expanded", String(!dockCollapsed));
    if (elements.expand) elements.expand.hidden = !dockCollapsed;
    if (elements.collapse) elements.collapse.hidden = dockCollapsed;
    if (save) saveLocalCollapsed(dockCollapsed);
  }

  function getSavedLocalRepeat() {
    try {
      return localStorage.getItem(LOCAL_REPEAT_KEY) === "true";
    } catch {
      return false;
    }
  }

  function saveLocalRepeat(value) {
    try {
      localStorage.setItem(LOCAL_REPEAT_KEY, String(Boolean(value)));
    } catch {
    }
  }

  function setRepeatOne(value, { save = true } = {}) {
    repeatOne = Boolean(value);
    if (elements.repeat) {
      const label = repeatOne ? "Wyłącz powtarzanie tego utworu" : "Powtarzaj ten utwór w kółko";
      elements.repeat.classList.toggle("radio-player-control--active", repeatOne);
      elements.repeat.setAttribute("aria-pressed", String(repeatOne));
      elements.repeat.setAttribute("aria-label", label);
      elements.repeat.title = label;
    }
    if (save) saveLocalRepeat(repeatOne);
  }

  function normalizeHttpUrl(value) {
    const raw = String(value ?? "").trim().slice(0, MAX_URL_LENGTH);
    if (!raw || /\s/.test(raw)) return "";
    const candidate = /^[a-z][a-z\d+.-]*:\/\//i.test(raw) ? raw : `https://${raw}`;
    try {
      const parsed = new URL(candidate);
      const isHttp = parsed.protocol === "http:" || parsed.protocol === "https:";
      return isHttp && parsed.hostname && !parsed.hostname.includes("%") ? parsed.href : "";
    } catch {
      return "";
    }
  }

  function extractYoutubeVideoId(value) {
    const url = normalizeHttpUrl(value);
    if (!url) return "";
    try {
      const parsed = new URL(url);
      const host = parsed.hostname.toLowerCase().replace(/^www\./, "");
      let videoId = "";
      if (host === "youtu.be") {
        videoId = parsed.pathname.split("/").filter(Boolean)[0] || "";
      } else if (
        host === "youtube.com"
        || host === "m.youtube.com"
        || host === "music.youtube.com"
        || host === "youtube-nocookie.com"
      ) {
        if (parsed.pathname === "/watch") {
          videoId = parsed.searchParams.get("v") || "";
        } else {
          const pathParts = parsed.pathname.split("/").filter(Boolean);
          if (["embed", "shorts", "live"].includes(pathParts[0])) videoId = pathParts[1] || "";
        }
      }
      return /^[a-zA-Z0-9_-]{11}$/.test(videoId) ? videoId : "";
    } catch {
      return "";
    }
  }

  function deriveItemName(url, index = 0) {
    const youtubeId = extractYoutubeVideoId(url);
    if (youtubeId) return `YouTube ${index + 1}`;
    try {
      const parsed = new URL(url);
      return parsed.hostname.replace(/^www\./, "") || `Radio ${index + 1}`;
    } catch {
      return `Radio ${index + 1}`;
    }
  }

  function normalizeItem(value, index = 0) {
    const source = typeof value === "string" ? { url: value } : value;
    if (!source || typeof source !== "object" || Array.isArray(source)) return null;
    const url = normalizeHttpUrl(source.url);
    if (!url) return null;
    const name = String(source.name ?? "")
      .replace(/\s+/g, " ")
      .trim()
      .slice(0, MAX_NAME_LENGTH) || deriveItemName(url, index);
    return {
      name,
      url,
      type: extractYoutubeVideoId(url) ? "youtube" : "stream",
    };
  }

  function normalizeItems(items) {
    if (!Array.isArray(items)) return [];
    const normalized = [];
    const seenUrls = new Set();
    for (const value of items) {
      const item = normalizeItem(value, normalized.length);
      if (!item || seenUrls.has(item.url)) continue;
      seenUrls.add(item.url);
      normalized.push(item);
      if (normalized.length >= MAX_ITEMS) break;
    }
    return normalized;
  }

  function normalizeSettings(value) {
    return {
      visible: value?.visible !== false,
      shuffle: value?.shuffle !== false,
      volume: clampVolume(value?.volume),
      items: normalizeItems(value?.items),
    };
  }

  function parseItemsText(value) {
    const lines = String(value ?? "").split(/\r?\n/);
    const items = [];
    const seenUrls = new Set();

    for (let index = 0; index < lines.length; index += 1) {
      const line = lines[index].trim();
      if (!line) continue;
      if (items.length >= MAX_ITEMS) {
        throw new Error(`Możesz zapisać maksymalnie ${MAX_ITEMS} linków.`);
      }

      let name = "";
      let rawUrl = line;
      const separatorIndex = line.lastIndexOf("|");
      if (separatorIndex > -1) {
        const possibleUrl = line.slice(separatorIndex + 1).trim();
        if (normalizeHttpUrl(possibleUrl)) {
          name = line.slice(0, separatorIndex).replace(/\s+/g, " ").trim();
          rawUrl = possibleUrl;
        }
      }

      const url = normalizeHttpUrl(rawUrl);
      if (!url) {
        throw new Error(`Wiersz ${index + 1} nie zawiera prawidłowego linku http:// lub https://.`);
      }
      if (seenUrls.has(url)) continue;
      seenUrls.add(url);
      items.push(normalizeItem({ name, url }, items.length));
    }

    return items;
  }

  function formatItems(items) {
    return normalizeItems(items)
      .map((item) => `${item.name} | ${item.url}`)
      .join("\n");
  }

  function getSavedLocalVolume() {
    try {
      const saved = localStorage.getItem(LOCAL_VOLUME_KEY);
      return saved === null ? null : clampVolume(saved);
    } catch {
      return null;
    }
  }

  function saveLocalVolume(volume) {
    try {
      localStorage.setItem(LOCAL_VOLUME_KEY, String(clampVolume(volume)));
    } catch {
    }
  }

  function getVolume() {
    return clampVolume(elements.volume ? Number(elements.volume.value) / 100 : settings.volume);
  }

  function showSettingsError(message = "") {
    if (!elements.settingsError) return;
    elements.settingsError.textContent = message;
    elements.settingsError.hidden = !message;
  }

  function updateSettingsSummary() {
    if (!elements.settingsLinks || !elements.settingsSummary) return;
    try {
      const items = parseItemsText(elements.settingsLinks.value);
      elements.settingsSummary.textContent = items.length === 0
        ? "Lista jest pusta — dodaj co najmniej jeden link, aby uruchomić odtwarzacz."
        : `Gotowe linki: ${items.length}/${MAX_ITEMS}.`;
      showSettingsError("");
    } catch (error) {
      elements.settingsSummary.textContent = "Popraw listę przed zapisaniem.";
      showSettingsError(error?.message || "Lista zawiera nieprawidłowy link.");
    }
  }

  
  
  function syncSettingsForm(value) {
    const normalized = normalizeSettings(value);
    if (elements.settingsVisible) elements.settingsVisible.checked = normalized.visible;
  }

  function readSettingsForm() {
    return normalizeSettings({
      ...settings,
      visible: elements.settingsVisible?.checked !== false,
      volume: getVolume(),
    });
  }

  function syncPlaylistForm() {
    if (elements.settingsLinks) elements.settingsLinks.value = formatItems(settings.items);
    if (elements.settingsShuffle) elements.settingsShuffle.checked = settings.shuffle;
    updateSettingsSummary();
  }

  function openPlaylistDialog() {
    if (!elements.playlistDialog) return;
    syncPlaylistForm();
    if (!elements.playlistDialog.open) elements.playlistDialog.showModal();
    elements.settingsLinks?.focus();
  }

  function closePlaylistDialog() {
    if (elements.playlistDialog?.open) elements.playlistDialog.close();
  }

  function submitPlaylistDialog(event) {
    event?.preventDefault();
    let items;
    try {
      items = parseItemsText(elements.settingsLinks?.value);
    } catch (error) {
      showSettingsError(error?.message || "Lista zawiera nieprawidłowy link.");
      elements.settingsLinks?.focus();
      return;
    }
    const nextRadio = normalizeSettings({
      ...settings,
      shuffle: elements.settingsShuffle?.checked !== false,
      volume: getVolume(),
      items,
    });
    configure(nextRadio);
    closePlaylistDialog();
    globalThis.dispatchEvent(new CustomEvent("sekagent-radio-settings-change", {
      detail: { radio: nextRadio },
    }));
  }

  function setError(message = "") {
    if (!elements.error) return;
    elements.error.textContent = message;
    elements.error.hidden = !message;
  }

  function sanitizeTrackTitle(value) {
    return String(value ?? "").replace(/\s+/g, " ").trim().slice(0, 160);
  }

  function getManualYoutubeTitle(item) {
    if (!item || item.type !== "youtube") return "";
    const name = sanitizeTrackTitle(item.name);
    return name && !/^YouTube \d+$/i.test(name) ? name : "";
  }

  function getCurrentTrackTitle({ allowYoutubeDefault = false } = {}) {
    if (!currentItem) return "";
    if (currentItem.type === "youtube") {
      return getManualYoutubeTitle(currentItem)
        || currentTrackTitle
        || (allowYoutubeDefault ? sanitizeTrackTitle(currentItem.name) : "");
    }
    return currentTrackTitle || sanitizeTrackTitle(currentItem.name);
  }

  function maybeAnnounceTrack() {
    if (!trackNotificationPending) return;
    const title = getCurrentTrackTitle();
    if (!title) return;
    trackNotificationPending = false;
    globalThis.showToast?.(`Teraz gra: ${title}`, "music");
  }

  function updatePlayerDisplay(statusText = "") {
    const hasItems = settings.items.length > 0;
    const trackLabel = getCurrentTrackTitle({ allowYoutubeDefault: true });
    const title = trackLabel || "Radio i muzyka";
    const status = statusText || (hasItems ? "Gotowe do odtwarzania" : "Kliknij „Lista utworów” i wklej linki");

    if (elements.title) {
      elements.title.textContent = trackLabel || "Radio";
      elements.title.title = trackLabel;
    }
    if (elements.status) elements.status.textContent = status;
    if (elements.popoverTitle) {
      elements.popoverTitle.textContent = title;
      elements.popoverTitle.title = trackLabel;
    }
    if (elements.popoverStatus) elements.popoverStatus.textContent = status;
    if (elements.root) elements.root.dataset.state = isPlaying ? "playing" : (currentItem ? "paused" : "idle");
    if (elements.playPause) {
      elements.playPause.disabled = !hasItems;
      elements.playPause.setAttribute("aria-label", isPlaying ? "Wstrzymaj odtwarzanie" : "Rozpocznij odtwarzanie");
      elements.playPause.setAttribute("aria-pressed", String(isPlaying));
      elements.playPause.querySelector("[data-radio-play-icon]")?.toggleAttribute("hidden", isPlaying);
      elements.playPause.querySelector("[data-radio-pause-icon]")?.toggleAttribute("hidden", !isPlaying);
    }
    if (elements.next) elements.next.disabled = !hasItems;
    if (elements.previous) elements.previous.disabled = !hasItems;
    if (elements.repeat) elements.repeat.disabled = !hasItems;
  }

  function setPlaying(playing, statusText = "") {
    isPlaying = Boolean(playing);
    updatePlayerDisplay(statusText || (isPlaying ? "Odtwarzanie" : "Wstrzymano"));
  }

  function shuffleArray(values) {
    const copy = [...values];
    for (let index = copy.length - 1; index > 0; index -= 1) {
      const swapIndex = Math.floor(Math.random() * (index + 1));
      [copy[index], copy[swapIndex]] = [copy[swapIndex], copy[index]];
    }
    return copy;
  }

  function resetQueue() {
    const indexes = settings.items.map((_, index) => index);
    queue = settings.shuffle ? shuffleArray(indexes) : indexes;
    if (queue.length > 1 && currentItem && settings.items[queue[0]]?.url === currentItem.url) {
      [queue[0], queue[1]] = [queue[1], queue[0]];
    }
    queueCursor = 0;
  }

  function takeNextItem() {
    if (settings.items.length === 0) return null;
    if (queueCursor >= queue.length) resetQueue();
    const item = settings.items[queue[queueCursor]];
    queueCursor += 1;
    return item || null;
  }

  function stopCurrentSource({ clear = false } = {}) {
    sourceChangeToken += 1;
    if (clear) currentSource = "";
    if (elements.audio) {
      elements.audio.pause();
      if (clear) {
        elements.audio.removeAttribute("src");
        elements.audio.load();
      }
    }
    if (youtubeFrame) {
      postYoutubeCommand(clear ? "stopVideo" : "pauseVideo");
      if (clear) destroyYoutubeFrame();
    }
    isPlaying = false;
  }

  function playNativeStream(item) {
    if (!elements.audio) return;
    currentSource = "stream";
    elements.audio.src = item.url;
    elements.audio.volume = getVolume();
    elements.audio.load();
    updatePlayerDisplay("Łączenie ze stacją…");
    const playResult = elements.audio.play();
    if (playResult && typeof playResult.catch === "function") {
      playResult.catch(() => {
        setPlaying(false, "Nie udało się rozpocząć");
        setError("Ten adres nie udostępnia bezpośredniego dźwięku. Wklej adres strumienia MP3/AAC, a nie zwykłą stronę radia.");
      });
    }
  }

  function clearYoutubeTimers() {
    if (youtubeHandshakeTimer !== null) clearInterval(youtubeHandshakeTimer);
    if (youtubeReadyTimer !== null) clearTimeout(youtubeReadyTimer);
    youtubeHandshakeTimer = null;
    youtubeReadyTimer = null;
  }

  function destroyYoutubeFrame() {
    clearYoutubeTimers();
    youtubeReady = false;
    if (youtubeFrame) youtubeFrame.remove();
    youtubeFrame = null;
    if (elements.youtubeHost) elements.youtubeHost.replaceChildren();
  }

  function postYoutubeMessage(message) {
    if (!youtubeFrame?.contentWindow) return;
    youtubeFrame.contentWindow.postMessage(JSON.stringify({
      id: youtubeFrame.id,
      channel: "sekagent-radio",
      ...message,
    }), YOUTUBE_EMBED_ORIGIN);
  }

  function postYoutubeCommand(func, args = []) {
    postYoutubeMessage({ event: "command", func, args });
  }

  function subscribeYoutubeEvents() {
    postYoutubeMessage({ event: "listening" });
    for (const eventName of ["onReady", "onStateChange", "onError"]) {
      postYoutubeCommand("addEventListener", [eventName]);
    }
  }

  function handleYoutubeStateChange(state) {
    if (currentSource !== "youtube") return;
    if (state === 1) {
      setError("");
      setPlaying(true, "Odtwarzanie z YouTube");
      maybeAnnounceTrack();
    } else if (state === 2) {
      setPlaying(false, "Wstrzymano");
    } else if (state === 3) {
      updatePlayerDisplay("Ładowanie z YouTube…");
    } else if (state === 0) {
      if (repeatOne && currentItem && youtubeReady) {
        postYoutubeCommand("seekTo", [0, true]);
        postYoutubeCommand("playVideo");
        updatePlayerDisplay("Powtarzanie utworu…");
        return;
      }
      void playNext();
    }
  }

  function handleYoutubeError() {
    setPlaying(false, "Nie udało się odtworzyć");
    setError("Ten film jest niedostępny albo jego autor zablokował odtwarzanie poza YouTube. Wybierz następny link.");
  }

  function handleYoutubeInfo(info) {
    if (currentSource !== "youtube" || !currentItem || !info || typeof info !== "object") return;
    const videoData = info.videoData;
    if (!videoData || typeof videoData !== "object") return;

    const currentVideoId = extractYoutubeVideoId(currentItem.url);
    const reportedVideoId = String(videoData.video_id || videoData.videoId || "").trim();
    if (reportedVideoId && reportedVideoId !== currentVideoId) return;

    const youtubeTitle = sanitizeTrackTitle(videoData.title);
    if (!youtubeTitle || youtubeTitle === currentTrackTitle) return;
    currentTrackTitle = youtubeTitle;
    updatePlayerDisplay(elements.status?.textContent || "");
    if (isPlaying) maybeAnnounceTrack();
  }

  function handleYoutubeMessage(event) {
    if (
      !youtubeFrame
      || event.source !== youtubeFrame.contentWindow
      || !YOUTUBE_MESSAGE_ORIGINS.has(event.origin)
    ) return;
    let message = event.data;
    if (typeof message === "string") {
      try {
        message = JSON.parse(message);
      } catch {
        return;
      }
    }
    if (!message || typeof message !== "object") return;
    if (message.event === "infoDelivery" || message.event === "initialDelivery") {
      handleYoutubeInfo(message.info);
    }
    if (message.event === "onReady") {
      clearYoutubeTimers();
      youtubeReady = true;
      postYoutubeCommand("setVolume", [Math.round(getVolume() * 100)]);
      postYoutubeCommand("playVideo");
      return;
    }
    if (message.event === "onStateChange") {
      handleYoutubeStateChange(Number(message.info));
      return;
    }
    if (message.event === "onError") handleYoutubeError();
  }

  function playYoutube(item) {
    const videoId = extractYoutubeVideoId(item.url);
    if (!videoId || !elements.youtubeHost) {
      handleYoutubeError();
      return;
    }

    currentSource = "youtube";
    updatePlayerDisplay("Łączenie z YouTube…");
    const token = sourceChangeToken;
    const frame = document.createElement("iframe");
    frame.id = `sekagent-youtube-${Date.now().toString(36)}`;
    frame.title = "Odtwarzacz YouTube";
    frame.width = "200";
    frame.height = "200";
    frame.referrerPolicy = "strict-origin-when-cross-origin";
    frame.sandbox = "allow-scripts allow-same-origin allow-presentation";
    frame.allow = "autoplay; encrypted-media";
    frame.src = `${YOUTUBE_EMBED_ORIGIN}/embed/${encodeURIComponent(videoId)}`
      + `?autoplay=1&controls=0&disablekb=1&enablejsapi=1&fs=0&playsinline=1&rel=0`
      + `&origin=${encodeURIComponent(globalThis.location?.origin || "")}`;
    frame.addEventListener("load", subscribeYoutubeEvents, { once: true });
    elements.youtubeHost.replaceChildren(frame);
    youtubeFrame = frame;
    youtubeHandshakeTimer = setInterval(subscribeYoutubeEvents, 300);
    youtubeReadyTimer = setTimeout(() => {
      if (token !== sourceChangeToken || youtubeReady) return;
      setPlaying(false, "Brak połączenia z YouTube");
      setError("YouTube nie odpowiedział na czas.");
      destroyYoutubeFrame();
    }, YOUTUBE_API_TIMEOUT_MS);
  }

  function rememberPlayedItem(item) {
    if (playbackHistory[playbackHistory.length - 1]?.url === item.url) return;
    playbackHistory.push(item);
    if (playbackHistory.length > HISTORY_LIMIT) playbackHistory.shift();
  }

  function startItem(item, { recordHistory = true } = {}) {
    if (!item) return;
    stopCurrentSource({ clear: true });
    currentItem = item;
    if (recordHistory) rememberPlayedItem(item);
    currentTrackTitle = "";
    
    
    trackNotificationPending = true;
    setError("");
    updatePlayerDisplay("Przygotowanie…");
    if (item.type === "youtube") {
      void playYoutube(item);
    } else {
      playNativeStream(item);
    }
  }

  async function playNext() {
    const item = takeNextItem();
    if (!item) {
      setPlaying(false, "Kliknij „Lista utworów” i wklej linki");
      setError("Lista odtwarzania jest pusta.");
      return;
    }
    startItem(item);
  }

  function playPrevious() {
    if (currentItem && playbackHistory.length > 1) {
      playbackHistory.pop();
      startItem(playbackHistory[playbackHistory.length - 1], { recordHistory: false });
      return;
    }
    if (currentItem) {
      
      startItem(currentItem, { recordHistory: false });
      return;
    }
    void playNext();
  }

  function resumeCurrent() {
    setError("");
    if (!currentItem) {
      void playNext();
      return;
    }
    if (currentSource === "youtube" && youtubeFrame && youtubeReady) {
      postYoutubeCommand("playVideo");
      updatePlayerDisplay("Wznawianie…");
      return;
    }
    if (currentSource === "stream" && elements.audio) {
      const playResult = elements.audio.play();
      updatePlayerDisplay("Łączenie…");
      playResult?.catch?.(() => {
        setPlaying(false, "Nie udało się wznowić");
        setError("Nie udało się wznowić tego źródła dźwięku.");
      });
      return;
    }
    startItem(currentItem);
  }

  function togglePlayback() {
    if (isPlaying) {
      if (currentSource === "youtube" && youtubeFrame && youtubeReady) {
        postYoutubeCommand("pauseVideo");
      } else {
        elements.audio?.pause();
      }
      setPlaying(false, "Wstrzymano");
      return;
    }
    resumeCurrent();
  }

  function applyVolume(rawValue, { save = true } = {}) {
    const volume = clampVolume(rawValue);
    settings.volume = volume;
    if (elements.volume) elements.volume.value = String(Math.round(volume * 100));
    if (elements.volumeValue) elements.volumeValue.textContent = `${Math.round(volume * 100)}%`;
    if (elements.audio) elements.audio.volume = volume;
    if (youtubeFrame && youtubeReady) postYoutubeCommand("setVolume", [Math.round(volume * 100)]);
    if (save) saveLocalVolume(volume);
  }

  function hideDock() {
    stopCurrentSource({ clear: true });
    currentItem = null;
    currentTrackTitle = "";
    trackNotificationPending = false;
    playbackHistory = [];
    settings.visible = false;
    resetQueue();
    setError("");
    if (elements.root) elements.root.hidden = true;
    if (elements.settingsVisible) elements.settingsVisible.checked = false;
    updatePlayerDisplay();
    globalThis.dispatchEvent(new CustomEvent("sekagent-radio-settings-change", {
      detail: { radio: { ...settings } },
    }));
  }

  function configure(value) {
    const nextSettings = normalizeSettings(value);
    const localVolume = getSavedLocalVolume();
    if (localVolume !== null) nextSettings.volume = localVolume;
    const nextCurrentItem = currentItem
      ? nextSettings.items.find((item) => item.url === currentItem.url)
      : null;
    const currentStillExists = Boolean(nextCurrentItem);
    settings = nextSettings;
    if (nextCurrentItem) currentItem = nextCurrentItem;
    applyVolume(settings.volume, { save: false });
    setDockCollapsed(getSavedLocalCollapsed(), { save: false });
    setRepeatOne(getSavedLocalRepeat(), { save: false });
    resetQueue();
    playbackHistory = playbackHistory.filter((entry) => settings.items.some((item) => item.url === entry.url));
    if (elements.root) elements.root.hidden = !settings.visible;
    if (elements.settingsVisible) elements.settingsVisible.checked = settings.visible;

    if (!settings.visible && (currentItem || isPlaying)) {
      stopCurrentSource({ clear: true });
      currentItem = null;
      currentTrackTitle = "";
      trackNotificationPending = false;
      setError("");
    } else if (!currentStillExists && currentItem) {
      stopCurrentSource({ clear: true });
      currentItem = null;
      currentTrackTitle = "";
      trackNotificationPending = false;
      setError("");
    }
    updatePlayerDisplay();
  }

  function initializeEvents() {
    globalThis.addEventListener("message", handleYoutubeMessage);
    elements.collapse?.addEventListener("click", () => setDockCollapsed(true));
    elements.expand?.addEventListener("click", () => setDockCollapsed(false));
    elements.close?.addEventListener("click", hideDock);
    elements.playPause?.addEventListener("click", togglePlayback);
    elements.previous?.addEventListener("click", playPrevious);
    elements.next?.addEventListener("click", () => void playNext());
    elements.repeat?.addEventListener("click", () => setRepeatOne(!repeatOne));
    elements.volume?.addEventListener("input", () => {
      applyVolume(Number(elements.volume.value) / 100);
    });
    elements.openSettings?.addEventListener("click", openPlaylistDialog);
    elements.playlistForm?.addEventListener("submit", submitPlaylistDialog);
    elements.playlistClose?.addEventListener("click", closePlaylistDialog);
    elements.playlistCancel?.addEventListener("click", closePlaylistDialog);
    elements.settingsLinks?.addEventListener("input", updateSettingsSummary);
    elements.audio?.addEventListener("playing", () => {
      if (currentSource !== "stream") return;
      setError("");
      setPlaying(true, "Odtwarzanie radia");
      maybeAnnounceTrack();
    });
    elements.audio?.addEventListener("waiting", () => {
      if (currentSource === "stream") updatePlayerDisplay("Buforowanie radia…");
    });
    elements.audio?.addEventListener("pause", () => {
      if (currentSource === "stream" && isPlaying) setPlaying(false, "Wstrzymano");
    });
    elements.audio?.addEventListener("ended", () => {
      if (currentSource !== "stream") return;
      if (repeatOne && currentItem) {
        try {
          elements.audio.currentTime = 0;
        } catch {
        }
        updatePlayerDisplay("Powtarzanie utworu…");
        const playResult = elements.audio.play();
        playResult?.catch?.(() => void playNext());
        return;
      }
      void playNext();
    });
    elements.audio?.addEventListener("error", () => {
      if (currentSource !== "stream" || !elements.audio?.src) return;
      setPlaying(false, "Nie udało się odtworzyć");
      setError("Ten adres nie zwrócił obsługiwanego dźwięku. Użyj bezpośredniego strumienia MP3/AAC.");
    });
  }

  initializeEvents();
  configure(settings);

  globalThis.SekagentRadio = Object.freeze({
    configure,
    extractYoutubeVideoId,
    formatItems,
    getVolume,
    normalizeSettings,
    parseItemsText,
    readSettingsForm,
    syncSettingsForm,
  });
})();
