(function () {
  if (window.MelonLitePwaInitialized) return;
  window.MelonLitePwaInitialized = true;

  const settings = Object.assign({
    enabled: true,
    showGuide: true,
    appName: '개인 음악실'
  }, window.APP_PWA_SETTINGS || {});

  if (!settings.enabled) return;

  const DISMISS_KEY = 'melon_lite_pwa_install_dismissed_at';
  const NEVER_KEY = 'melon_lite_pwa_install_never';
  const INSTALLED_KEY = 'melon_lite_pwa_installed';
  const LEGACY_CLOSED_KEY = 'melon_lite_pwa_banner_closed';
  const LAST_SHOWN_KEY = 'melon_lite_pwa_install_last_shown_at';
  const GUIDE_SEEN_KEY = 'melon_lite_pwa_install_guide_seen';
  const PLATFORM_KEY = 'melon_lite_pwa_install_platform';
  const OPEN_KEY = 'melon_lite_pwa_install_modal_open';
  const LAST_ONLINE_KEY = 'melon_lite_last_online_at';
  const ASSET_VERSION_KEY = 'melon_lite_asset_version';
  const SESSION_SHOWN_KEY = 'melon_lite_pwa_install_shown_session';
  const DISMISS_MS = 1000 * 60 * 60 * 24 * 30;
  const MIN_SHOW_INTERVAL_MS = 1000 * 60 * 60 * 24;

  let deferredPrompt = null;
  let refreshing = false;
  let pendingMode = null;
  let pendingTimer = null;

  const modal = document.getElementById('pwa-install-banner');
  const installBtn = document.getElementById('pwa-install-btn');
  const guideBtn = document.getElementById('pwa-guide-btn');
  const laterBtn = document.getElementById('pwa-install-later');
  const neverBtn = document.getElementById('pwa-install-never');
  const closeBtn = document.getElementById('pwa-install-close');
  const guideModal = document.getElementById('pwa-guide-modal');
  const guideClose = document.getElementById('pwa-guide-close');
  const guideBackdrop = document.getElementById('pwa-guide-backdrop');
  const guideBody = document.getElementById('pwa-guide-body');
  const copyTitle = modal ? modal.querySelector('.pwa-install-copy strong') : null;
  const copyText = modal ? modal.querySelector('#pwa-install-message') : null;
  const stepsPanel = document.getElementById('pwa-install-steps');

  const ua = navigator.userAgent || '';
  const isIOS = /iphone|ipad|ipod/i.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
  const isAndroid = /android/i.test(ua);
  const isSafari = /^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(ua);
  const isMobileLike = /android|iphone|ipad|ipod/i.test(ua) || (navigator.maxTouchPoints || 0) > 1 || window.matchMedia('(max-width: 767px)').matches;

  function isStandalone() {
    return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true;
  }

  function isAdminOrAuthPage() {
    const path = window.location.pathname;
    return /\/admin\//i.test(path)
      || /\/(login|setup_admin)\.php$/i.test(path)
      || /\/(backup|restore|import|export)(_|\.)/i.test(path);
  }

  function storageGet(key) {
    try { return localStorage.getItem(key); } catch (err) { return null; }
  }

  function storageSet(key, value) {
    try { localStorage.setItem(key, value); } catch (err) {}
  }

  function storageRemove(key) {
    try { localStorage.removeItem(key); } catch (err) {}
  }

  function sessionGet(key) {
    try { return sessionStorage.getItem(key); } catch (err) { return null; }
  }

  function sessionSet(key, value) {
    try { sessionStorage.setItem(key, value); } catch (err) {}
  }

  function sessionRemove(key) {
    try { sessionStorage.removeItem(key); } catch (err) {}
  }

  function rememberOnlineNow() {
    if (navigator.onLine) storageSet(LAST_ONLINE_KEY, String(Date.now()));
  }

  function savePlayerState() {
    if (window.AppPlayer && typeof window.AppPlayer.saveState === 'function') {
      try { window.AppPlayer.saveState(); } catch (err) {}
    }
  }

  function clearPwaCaches() {
    const clearWithCacheApi = ('caches' in window)
      ? caches.keys().then(function (keys) {
          return Promise.all(keys.filter(function (key) {
            return key.indexOf('melonlite-pwa-') === 0;
          }).map(function (key) {
            return caches.delete(key);
          }));
        }).catch(function () {})
      : Promise.resolve();

    const clearWithWorker = navigator.serviceWorker && navigator.serviceWorker.controller
      ? new Promise(function (resolve) {
          try {
            navigator.serviceWorker.controller.postMessage({ type: 'CLEAR_ALL_CACHES' });
          } catch (err) {}
          window.setTimeout(resolve, 150);
        })
      : Promise.resolve();

    return Promise.all([clearWithCacheApi, clearWithWorker]);
  }

  function handleAssetVersionChange(registration) {
    const currentVersion = String(window.APP_ASSET_VERSION || '');
    if (!currentVersion) return;
    const previousVersion = storageGet(ASSET_VERSION_KEY);
    if (previousVersion === currentVersion) return;
    storageSet(ASSET_VERSION_KEY, currentVersion);
    if (!previousVersion) return;

    savePlayerState();
    clearPwaCaches()
      .then(function () {
        if (registration && typeof registration.update === 'function') {
          return registration.update().catch(function () {});
        }
        return null;
      })
      .then(function () {
        if (!isAudioPlaying()) {
          window.location.reload();
          return;
        }
        showToast('앱 화면 파일이 갱신되었습니다. 재생을 멈춘 뒤 새로고침하면 최신 화면이 적용됩니다.', 'info');
      });
  }

  function isDismissed() {
    if (storageGet(NEVER_KEY) === '1' || storageGet(INSTALLED_KEY) === '1') return true;
    if (storageGet(LEGACY_CLOSED_KEY) === '1') {
      storageSet(DISMISS_KEY, String(Date.now()));
      storageRemove(LEGACY_CLOSED_KEY);
      return true;
    }
    const dismissedAt = Number(storageGet(DISMISS_KEY) || 0);
    return dismissedAt > 0 && Date.now() - dismissedAt < DISMISS_MS;
  }

  function wasShownRecently() {
    const lastShownAt = Number(storageGet(LAST_SHOWN_KEY) || 0);
    return lastShownAt > 0 && Date.now() - lastShownAt < MIN_SHOW_INTERVAL_MS;
  }

  function wasShownThisSession() {
    return sessionGet(SESSION_SHOWN_KEY) === '1';
  }

  function showToast(message, type) {
    if (window.MusicPlayer && typeof window.MusicPlayer.showToast === 'function') {
      window.MusicPlayer.showToast(message, type || 'info');
      return;
    }
    if (window.showToast && typeof window.showToast === 'function') {
      window.showToast(message, type || 'info');
      return;
    }
    let toast = document.getElementById('melon-lite-toast');
    if (!toast) {
      toast = document.createElement('div');
      toast.id = 'melon-lite-toast';
      toast.className = 'melon-lite-toast';
      toast.setAttribute('role', 'status');
      toast.setAttribute('aria-live', 'polite');
      document.body.appendChild(toast);
    }
    toast.textContent = message;
    toast.dataset.type = type || 'info';
    toast.classList.add('show');
    window.clearTimeout(toast.__hideTimer);
    toast.__hideTimer = window.setTimeout(function () { toast.classList.remove('show'); }, 4200);
  }

  function applyStandaloneClass() {
    const standalone = isStandalone();
    document.documentElement.classList.toggle('is-standalone', standalone);
    document.body.classList.toggle('is-standalone', standalone);
    if (standalone) storageSet(INSTALLED_KEY, '1');
    if (standalone) closeInstallModal(false);
  }

  function clearSteps() {
    if (!stepsPanel) return;
    stepsPanel.hidden = true;
    stepsPanel.innerHTML = '';
  }

  function renderSteps(mode) {
    if (!stepsPanel) return;
    stepsPanel.innerHTML = '';

    const title = document.createElement('strong');
    title.textContent = mode === 'ios' ? 'iPhone / iPad 설치 방법' : (mode === 'prompt' ? 'Android 설치 방법' : '브라우저 설치 방법');
    stepsPanel.appendChild(title);

    const list = document.createElement('ol');
    const steps = mode === 'ios'
      ? [
          isSafari ? 'Safari 하단 또는 상단의 공유 버튼을 누르세요.' : 'iPhone/iPad에서는 Safari로 이 페이지를 다시 열어 주세요.',
          '"홈 화면에 추가"를 선택하세요.',
          '추가 후 홈 화면의 개인 음악실 아이콘으로 실행할 수 있습니다.'
        ]
      : (mode === 'prompt'
          ? [
              '"앱 설치하기" 버튼을 누르세요.',
              '브라우저 설치 확인창에서 설치를 선택하세요.',
              '설치 후 홈 화면에서 앱처럼 바로 실행할 수 있습니다.'
            ]
          : [
              '브라우저 메뉴를 여세요.',
              '"앱 설치" 또는 "홈 화면에 추가"를 선택하세요.',
              '추가 후 개인 음악실을 앱처럼 실행할 수 있습니다.'
            ]);

    steps.forEach(function (step) {
      const item = document.createElement('li');
      item.textContent = step;
      list.appendChild(item);
    });
    stepsPanel.appendChild(list);
    stepsPanel.hidden = false;
    storageSet(GUIDE_SEEN_KEY, '1');
  }

  function configureInstallModal(mode) {
    if (!modal) return;
    modal.dataset.mode = mode;
    clearSteps();

    if (copyTitle) copyTitle.textContent = `${settings.appName || '개인 음악실'}을 홈 화면에 설치해보세요`;
    if (isIOS) {
      if (copyText) {
        copyText.textContent = isSafari
          ? '홈 화면에 추가하면 Safari를 열지 않고 앱처럼 음악을 들을 수 있습니다.'
          : 'iPhone과 iPad에서는 Safari에서 열어 홈 화면에 추가할 수 있습니다.';
      }
      if (installBtn) installBtn.hidden = true;
      if (guideBtn) {
        guideBtn.hidden = false;
        guideBtn.textContent = '설치 방법 보기';
      }
    } else if (mode === 'prompt') {
      if (copyText) copyText.textContent = '설치하면 홈 화면에서 바로 음악을 들을 수 있습니다.';
      if (installBtn) {
        installBtn.hidden = false;
        installBtn.textContent = '앱 설치하기';
      }
      if (guideBtn) {
        guideBtn.hidden = false;
        guideBtn.textContent = '설치 방법 보기';
      }
    } else {
      if (copyText) copyText.textContent = '브라우저 메뉴에서 홈 화면에 추가해 앱처럼 사용할 수 있습니다.';
      if (installBtn) installBtn.hidden = true;
      if (guideBtn) {
        guideBtn.hidden = false;
        guideBtn.textContent = '설치 방법 보기';
      }
    }
  }

  function isAudioPlaying() {
    const audio = document.getElementById('audio-player');
    return Boolean(audio && !audio.paused && !audio.ended);
  }

  function isUiBusy() {
    const sidebarOpen = document.getElementById('app-sidebar')?.classList.contains('open');
    const expanded = document.body.classList.contains('expand-player-open');
    const previewOpen = Boolean(document.getElementById('guest-preview-prompt')) || document.body.classList.contains('guest-preview-ended');
    const pwaOpen = Boolean(modal && !modal.hidden);
    const otherModalOpen = Boolean(document.querySelector('.modal-overlay[style*="display: flex"], .modal-overlay.show, .pwa-guide-modal:not([hidden])'));
    return sidebarOpen || expanded || previewOpen || pwaOpen || otherModalOpen || isAudioPlaying() || window.innerWidth < 340;
  }

  function closeInstallModal(saveOpenState) {
    if (!modal) return;
    modal.hidden = true;
    document.body.classList.remove('pwa-install-open');
    clearSteps();
    storageSet(OPEN_KEY, saveOpenState === false ? '0' : '0');
  }

  function scheduleInstallModal(mode, delay) {
    pendingMode = mode || pendingMode || (isIOS ? 'ios' : (deferredPrompt ? 'prompt' : 'manual'));
    window.clearTimeout(pendingTimer);
    pendingTimer = window.setTimeout(function () {
      showInstallModal(pendingMode);
    }, delay || 1600);
  }

  function showInstallModal(mode) {
    if (!settings.showGuide || !modal || isStandalone() || isAdminOrAuthPage() || isDismissed()) return;
    if (!isMobileLike && mode !== 'prompt') return;
    if (wasShownThisSession() && mode !== 'prompt') return;
    if (wasShownRecently() && mode !== 'prompt') return;
    if (isUiBusy()) {
      scheduleInstallModal(mode, 6000);
      return;
    }

    configureInstallModal(mode || (isIOS ? 'ios' : 'manual'));
    storageSet(LAST_SHOWN_KEY, String(Date.now()));
    storageSet(PLATFORM_KEY, isIOS ? 'ios' : (deferredPrompt ? 'install_prompt' : 'manual'));
    storageSet(OPEN_KEY, '1');
    sessionSet(SESSION_SHOWN_KEY, '1');
    modal.hidden = false;
    document.body.classList.add('pwa-install-open');
    window.setTimeout(function () {
      const primary = deferredPrompt && installBtn && !installBtn.hidden ? installBtn : guideBtn;
      if (primary && typeof primary.focus === 'function') primary.focus({ preventScroll: true });
    }, 80);
  }

  function hideInstallModal(kind) {
    if (kind === 'never') {
      storageSet(NEVER_KEY, '1');
      storageRemove(LEGACY_CLOSED_KEY);
    } else {
      storageSet(DISMISS_KEY, String(Date.now()));
      storageRemove(LEGACY_CLOSED_KEY);
    }
    closeInstallModal(false);
  }

  function closeGuideModal() {
    if (guideModal) {
      guideModal.hidden = true;
      guideModal.setAttribute('aria-hidden', 'true');
    }
    document.body.classList.remove('pwa-guide-open');
  }

  function openGuideModal() {
    if (stepsPanel) {
      renderSteps(modal?.dataset.mode || (isIOS ? 'ios' : (deferredPrompt ? 'prompt' : 'manual')));
      return;
    }
    if (!guideModal || !guideBody) return;
    guideBody.textContent = '';
    const wrapper = document.createElement('div');
    const list = document.createElement('ol');
    const steps = isIOS
      ? ['Safari의 공유 버튼을 누르세요.', '"홈 화면에 추가"를 선택하세요.', '추가 후 홈 화면의 개인 음악실 아이콘으로 실행할 수 있습니다.']
      : ['브라우저 메뉴를 여세요.', '"앱 설치" 또는 "홈 화면에 추가"를 선택하세요.', '추가 후 개인 음악실을 앱처럼 실행할 수 있습니다.'];
    steps.forEach(function (step) {
      const item = document.createElement('li');
      item.textContent = step;
      list.appendChild(item);
    });
    wrapper.appendChild(list);
    guideBody.appendChild(wrapper);
    storageSet(GUIDE_SEEN_KEY, '1');
    guideModal.hidden = false;
    guideModal.setAttribute('aria-hidden', 'false');
    document.body.classList.add('pwa-guide-open');
  }

  function registerServiceWorker() {
    if (!('serviceWorker' in navigator)) return;
    window.addEventListener('load', function () {
      const swVersion = window.APP_ASSET_VERSION ? ('?v=' + encodeURIComponent(window.APP_ASSET_VERSION)) : '';
      navigator.serviceWorker.register((window.APP_BASE_PATH || './') + 'service-worker.js' + swVersion, { updateViaCache: 'none' })
        .then(function (registration) {
          registration.update().catch(function () {});
          handleAssetVersionChange(registration);
          registration.addEventListener('updatefound', function () {
            const worker = registration.installing;
            if (!worker) return;
            worker.addEventListener('statechange', function () {
              if (worker.state === 'installed' && navigator.serviceWorker.controller) {
                try { worker.postMessage({ type: 'SKIP_WAITING' }); } catch (err) {}
                showToast('새 버전이 준비되었습니다. 새로고침하면 적용됩니다.', 'info');
              }
            });
          });
          if (registration.waiting && navigator.serviceWorker.controller) {
            try { registration.waiting.postMessage({ type: 'SKIP_WAITING' }); } catch (err) {}
          }
        })
        .catch(function (err) {
          console.warn('Service worker registration skipped:', err);
          storageSet('melon_lite_last_sw_error', JSON.stringify({ message: err.message || String(err), at: Date.now() }));
        });
    });

    navigator.serviceWorker.addEventListener('controllerchange', function () {
      if (refreshing) return;
      refreshing = true;
      savePlayerState();
      if (!isAudioPlaying()) {
        window.location.reload();
        return;
      }
      showToast('앱 파일이 업데이트되었습니다.', 'success');
    });
  }

  window.addEventListener('beforeinstallprompt', function (event) {
    event.preventDefault();
    deferredPrompt = event;
    scheduleInstallModal('prompt', 1000);
  });

  if (installBtn) {
    installBtn.addEventListener('click', function () {
      if (!deferredPrompt) {
        renderSteps(isIOS ? 'ios' : 'manual');
        return;
      }
      deferredPrompt.prompt();
      deferredPrompt.userChoice
        .then(function (choice) {
          storageSet('melon_lite_pwa_last_choice', JSON.stringify({ outcome: choice.outcome, at: Date.now() }));
          if (choice.outcome === 'accepted') {
            storageSet(INSTALLED_KEY, '1');
            closeInstallModal(false);
          } else {
            hideInstallModal('later');
          }
        })
        .catch(function (err) {
          console.warn('Install prompt failed:', err);
          renderSteps(isIOS ? 'ios' : 'manual');
          showToast('설치 안내를 표시하지 못했습니다. 브라우저 메뉴에서 홈 화면에 추가해 주세요.', 'error');
        })
        .finally(function () {
          deferredPrompt = null;
        });
    });
  }

  if (guideBtn) {
    guideBtn.addEventListener('click', function () {
      openGuideModal();
    });
  }

  if (guideClose) guideClose.addEventListener('click', closeGuideModal);
  if (guideBackdrop) guideBackdrop.addEventListener('click', closeGuideModal);

  if (modal) {
    modal.addEventListener('click', function (event) {
      if (event.target === modal) hideInstallModal('later');
    });
  }

  document.addEventListener('keydown', function (event) {
    if (event.key !== 'Escape') return;
    closeGuideModal();
    if (modal && !modal.hidden) hideInstallModal('later');
  });

  document.addEventListener('melonlite:page-ready', function () {
    closeGuideModal();
    if (modal && !modal.hidden && isUiBusy()) closeInstallModal(false);
    scheduleInstallModal(pendingMode, 2200);
  });

  document.addEventListener('melonlite:guest-preview-ended', function () {
    closeInstallModal(false);
  });

  if (laterBtn) {
    laterBtn.addEventListener('click', function () { hideInstallModal('later'); });
  }

  if (closeBtn) {
    closeBtn.addEventListener('click', function () { hideInstallModal('later'); });
  }

  if (neverBtn) {
    neverBtn.addEventListener('click', function () { hideInstallModal('never'); });
  }

  window.addEventListener('appinstalled', function () {
    storageSet(INSTALLED_KEY, '1');
    closeInstallModal(false);
    showToast('홈 화면에 앱이 추가되었습니다.', 'success');
  });

  window.addEventListener('online', function () {
    document.body.classList.remove('is-offline');
    rememberOnlineNow();
    showToast('네트워크가 다시 연결되었습니다.', 'success');
  });

  window.addEventListener('offline', function () {
    document.body.classList.add('is-offline');
    closeInstallModal(false);
    showToast('오프라인 상태입니다. 음악 재생과 저장 기능에는 서버 연결이 필요합니다.', 'warning');
  });

  window.addEventListener('pageshow', applyStandaloneClass);
  const standaloneQuery = window.matchMedia('(display-mode: standalone)');
  if (standaloneQuery.addEventListener) {
    standaloneQuery.addEventListener('change', applyStandaloneClass);
  } else if (standaloneQuery.addListener) {
    standaloneQuery.addListener(applyStandaloneClass);
  }

  window.addEventListener('load', function () {
    rememberOnlineNow();
    applyStandaloneClass();
    if (!navigator.onLine) document.body.classList.add('is-offline');
    if (isIOS) {
      scheduleInstallModal('ios', 1800);
    } else {
      scheduleInstallModal(deferredPrompt ? 'prompt' : (isAndroid ? 'manual' : 'manual'), 2200);
    }
  });

  window.resetMelonLitePwaInstallGuide = function () {
    storageRemove(DISMISS_KEY);
    storageRemove(NEVER_KEY);
    storageRemove(INSTALLED_KEY);
    storageRemove(LEGACY_CLOSED_KEY);
    storageRemove(LAST_SHOWN_KEY);
    storageRemove(GUIDE_SEEN_KEY);
    storageRemove(PLATFORM_KEY);
    storageRemove(OPEN_KEY);
    sessionRemove(SESSION_SHOWN_KEY);
    showInstallModal(isIOS ? 'ios' : (deferredPrompt ? 'prompt' : 'manual'));
    showToast('PWA 설치 안내를 다시 표시하도록 초기화했습니다.', 'success');
  };

  window.clearMelonLitePlayerStorage = function () {
    try {
      localStorage.removeItem('melon_lite_state');
      localStorage.removeItem('melon_lite_sidebar_groups');
      localStorage.removeItem('melon_lite_sidebar_scroll_top');
      localStorage.removeItem('melon_lite_sidebar_collapsed');
      localStorage.removeItem('melon_lite_theme');
      window.resetMelonLitePwaInstallGuide();
      alert('브라우저 플레이어 저장 정보, 테마, 사이드바 상태 및 PWA 안내 상태를 초기화했습니다.');
      window.location.reload();
    } catch (err) {
      alert('브라우저 저장 정보 초기화 중 오류가 발생했습니다.');
    }
  };

  registerServiceWorker();
})();
