/**
 * 공유 알림 벨 — 모든 서비스 헤더에 자동 삽입
 *
 * 사용법: initAuth() 성공 후 동적 <script> 로드
 *   const s = document.createElement('script');
 *   s.src = '/shared/notification-bell.js?v=1';
 *   document.head.appendChild(s);
 *
 * 요구사항: SSOAuth (nav-header.js) 또는 getToken() 함수 존재
 */
(function () {
  'use strict';

  /* ========== Config ========== */
  var POLL_INTERVAL = 60000; // 60초
  var DROPDOWN_LIMIT = 5;
  var API_ORIGIN = (function () {
    var h = window.location.hostname;
    if (h.includes('technicalkorea.net')) return 'https://tkuser.technicalkorea.net';
    return window.location.protocol + '//' + h + ':30300';
  })();
  var API_BASE = API_ORIGIN + '/api/notifications';
  var PUSH_API_BASE = API_ORIGIN + '/api/push';

  /* ========== Token helper ========== */
  function _getToken() {
    if (window.SSOAuth && window.SSOAuth.getToken) return window.SSOAuth.getToken();
    if (typeof getToken === 'function') return getToken();
    // cookie fallback
    var m = document.cookie.match(/(?:^|; )sso_token=([^;]*)/);
    return m ? decodeURIComponent(m[1]) : null;
  }

  function _authFetch(url, opts) {
    opts = opts || {};
    opts.headers = opts.headers || {};
    var token = _getToken();
    if (token) opts.headers['Authorization'] = 'Bearer ' + token;
    return fetch(url, opts);
  }

  /* ========== State ========== */
  var pollTimer = null;
  var unreadCount = 0;
  var dropdownOpen = false;
  var pushSubscribed = false;
  var ntfySubscribed = false;

  /* ========== UI: Bell injection ========== */
  function injectBell() {
    var header = document.querySelector('header');
    if (!header) return;

    // 벨 컨테이너
    var wrapper = document.createElement('div');
    wrapper.id = 'notif-bell-wrapper';
    wrapper.style.cssText = 'position:relative;display:inline-flex;align-items:center;cursor:pointer;margin-left:12px;';

    wrapper.innerHTML =
      '<div id="notif-bell-btn" style="position:relative;padding:6px;" title="알림">' +
        '<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="color:#4B5563;">' +
          '<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>' +
          '<path d="M13.73 21a2 2 0 0 1-3.46 0"/>' +
        '</svg>' +
        '<span id="notif-badge" style="display:none;position:absolute;top:0;right:0;background:#EF4444;color:#fff;font-size:11px;font-weight:600;min-width:18px;height:18px;line-height:18px;text-align:center;border-radius:9px;padding:0 4px;">0</span>' +
      '</div>' +
      '<div id="notif-dropdown" style="display:none;position:fixed;width:340px;max-height:420px;background:#fff;border:1px solid #E5E7EB;border-radius:8px;box-shadow:0 10px 25px rgba(0,0,0,.15);z-index:9999;overflow:hidden;">' +
        '<div style="padding:12px 16px;border-bottom:1px solid #F3F4F6;display:flex;justify-content:space-between;align-items:center;">' +
          '<span style="font-weight:600;font-size:14px;color:#111827;">알림</span>' +
          '<div style="display:flex;gap:8px;align-items:center;">' +
            '<button id="notif-ntfy-toggle" style="font-size:12px;color:#6B7280;background:none;border:1px solid #D1D5DB;border-radius:4px;padding:2px 8px;cursor:pointer;" title="ntfy 앱 알림">ntfy</button>' +
            '<button id="notif-push-toggle" style="font-size:12px;color:#6B7280;background:none;border:1px solid #D1D5DB;border-radius:4px;padding:2px 8px;cursor:pointer;" title="Push 알림 설정">Push</button>' +
            '<button id="notif-read-all" style="font-size:12px;color:#3B82F6;background:none;border:none;cursor:pointer;">모두 읽음</button>' +
          '</div>' +
        '</div>' +
        '<div id="notif-list" style="max-height:300px;overflow-y:auto;"></div>' +
        '<a id="notif-view-all" href="' + _getAllNotificationsUrl() + '" style="display:block;text-align:center;padding:10px;font-size:13px;color:#3B82F6;text-decoration:none;border-top:1px solid #F3F4F6;">전체보기</a>' +
      '</div>';

    // 삽입 위치: header 내부, 우측 영역 찾기
    var rightArea = header.querySelector('.flex.items-center.gap-3') ||
                    header.querySelector('.flex.items-center.gap-4') ||
                    header.querySelector('.flex.items-center.space-x-4') ||
                    header.querySelector('[class*="items-center"]');

    if (rightArea) {
      // 로그아웃 버튼 앞에 삽입
      var logoutBtn = rightArea.querySelector('button[onclick*="Logout"], button[onclick*="logout"]');
      if (logoutBtn) {
        rightArea.insertBefore(wrapper, logoutBtn);
      } else {
        rightArea.insertBefore(wrapper, rightArea.firstChild);
      }
    } else {
      header.appendChild(wrapper);
    }

    // Event listeners
    document.getElementById('notif-bell-btn').addEventListener('click', toggleDropdown);
    document.getElementById('notif-read-all').addEventListener('click', markAllRead);
    document.getElementById('notif-push-toggle').addEventListener('click', handlePushToggle);
    document.getElementById('notif-ntfy-toggle').addEventListener('click', handleNtfyToggle);

    // 외부 클릭 시 닫기
    document.addEventListener('click', function (e) {
      if (dropdownOpen && !wrapper.contains(e.target)) {
        closeDropdown();
      }
    });
  }

  function _getAllNotificationsUrl() {
    var h = window.location.hostname;
    if (h.includes('technicalkorea.net')) return 'https://tkuser.technicalkorea.net/?tab=notificationRecipients';
    return window.location.protocol + '//' + h + ':30380/?tab=notificationRecipients';
  }

  /* ========== UI: Badge ========== */
  function updateBadge(count) {
    unreadCount = count;
    var badge = document.getElementById('notif-badge');
    if (!badge) return;
    if (count > 0) {
      badge.textContent = count > 99 ? '99+' : count;
      badge.style.display = 'block';
    } else {
      badge.style.display = 'none';
    }
  }

  /* ========== UI: Dropdown ========== */
  function toggleDropdown(e) {
    e && e.stopPropagation();
    if (dropdownOpen) { closeDropdown(); return; }
    openDropdown();
  }

  function onScrollWhileOpen() {
    closeDropdown();
  }

  function openDropdown() {
    dropdownOpen = true;
    var dd = document.getElementById('notif-dropdown');
    var btn = document.getElementById('notif-bell-btn');
    var rect = btn.getBoundingClientRect();

    // 드롭다운 너비: 뷰포트 좁으면 양쪽 8px 여백
    var ddWidth = Math.min(340, window.innerWidth - 16);
    dd.style.width = ddWidth + 'px';
    dd.style.top = (rect.bottom + 4) + 'px';

    // 우측 정렬 기본, 왼쪽 넘치면 보정
    var rightOffset = window.innerWidth - rect.right;
    if (rightOffset + ddWidth > window.innerWidth - 8) {
      dd.style.right = 'auto';
      dd.style.left = '8px';
    } else {
      dd.style.left = 'auto';
      dd.style.right = Math.max(8, rightOffset) + 'px';
    }

    dd.style.display = 'block';
    window.addEventListener('scroll', onScrollWhileOpen, { once: true });
    loadNotifications();
    updatePushToggleUI();
    updateNtfyToggleUI();
  }

  function closeDropdown() {
    dropdownOpen = false;
    document.getElementById('notif-dropdown').style.display = 'none';
  }

  function loadNotifications() {
    var list = document.getElementById('notif-list');
    if (!list) return;
    list.innerHTML = '<div style="padding:20px;text-align:center;color:#9CA3AF;font-size:13px;">로딩 중...</div>';

    _authFetch(API_BASE + '/unread')
      .then(function (r) {
        if (!r.ok) throw new Error(r.status);
        return r.json();
      })
      .then(function (data) {
        if (!data.success || !data.data || data.data.length === 0) {
          list.innerHTML = '<div style="padding:20px;text-align:center;color:#9CA3AF;font-size:13px;">새 알림이 없습니다</div>';
          return;
        }
        var items = data.data.slice(0, DROPDOWN_LIMIT);
        list.innerHTML = items.map(function (n) {
          var timeAgo = _timeAgo(n.created_at);
          var typeLabel = _typeLabel(n.type);
          return '<div class="notif-item" data-id="' + n.notification_id + '" data-url="' + _escAttr(n.link_url || '') + '" style="padding:10px 16px;border-bottom:1px solid #F9FAFB;cursor:pointer;transition:background .15s;" onmouseover="this.style.background=\'#F9FAFB\'" onmouseout="this.style.background=\'transparent\'">' +
            '<div style="display:flex;justify-content:space-between;align-items:flex-start;">' +
              '<div style="flex:1;min-width:0;">' +
                '<div style="display:flex;align-items:center;gap:6px;margin-bottom:2px;">' +
                  '<span style="font-size:10px;background:#EFF6FF;color:#3B82F6;padding:1px 6px;border-radius:3px;font-weight:500;">' + _escHtml(typeLabel) + '</span>' +
                  '<span style="font-size:11px;color:#9CA3AF;">' + _escHtml(timeAgo) + '</span>' +
                '</div>' +
                '<div style="font-size:13px;font-weight:500;color:#111827;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">' + _escHtml(n.title) + '</div>' +
                (n.message ? '<div style="font-size:12px;color:#6B7280;margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">' + _escHtml(n.message) + '</div>' : '') +
              '</div>' +
              '<div style="width:8px;height:8px;border-radius:50%;background:#3B82F6;flex-shrink:0;margin-top:6px;margin-left:8px;"></div>' +
            '</div>' +
          '</div>';
        }).join('');

        // 클릭 이벤트
        list.querySelectorAll('.notif-item').forEach(function (el) {
          el.addEventListener('click', function () {
            var id = el.getAttribute('data-id');
            var url = el.getAttribute('data-url');
            _authFetch(API_BASE + '/' + id + '/read', { method: 'POST' })
              .then(function () { fetchUnreadCount(); })
              .catch(function () {});
            if (url) {
              // 같은 서비스 내 URL이면 직접 이동, 아니면 새 탭
              if (url.startsWith('/')) window.location.href = url;
              else window.open(url, '_blank');
            }
            closeDropdown();
          });
        });
      })
      .catch(function () {
        list.innerHTML = '<div style="padding:20px;text-align:center;color:#EF4444;font-size:13px;">잠시 후 다시 시도해주세요</div>';
      });
  }

  function markAllRead(e) {
    e && e.stopPropagation();
    _authFetch(API_BASE + '/read-all', { method: 'POST' })
      .then(function () {
        updateBadge(0);
        var list = document.getElementById('notif-list');
        if (list) list.innerHTML = '<div style="padding:20px;text-align:center;color:#9CA3AF;font-size:13px;">새 알림이 없습니다</div>';
      })
      .catch(function () {});
  }

  /* ========== Polling ========== */
  function fetchUnreadCount() {
    _authFetch(API_BASE + '/unread/count')
      .then(function (r) { return r.json(); })
      .then(function (data) {
        if (data.success) updateBadge(data.data.count);
      })
      .catch(function () {});
  }

  function startPolling() {
    fetchUnreadCount();
    pollTimer = setInterval(fetchUnreadCount, POLL_INTERVAL);
  }

  function stopPolling() {
    if (pollTimer) { clearInterval(pollTimer); pollTimer = null; }
  }

  /* ========== Web Push ========== */
  function handlePushToggle(e) {
    e && e.stopPropagation();
    if (pushSubscribed) {
      unsubscribePush();
    } else {
      subscribePush();
    }
  }

  function subscribePush() {
    if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
      alert('이 브라우저는 Push 알림을 지원하지 않습니다.');
      return;
    }

    // VAPID 공개키 가져오기
    fetch(PUSH_API_BASE + '/vapid-public-key')
      .then(function (r) { return r.json(); })
      .then(function (data) {
        if (!data.success || !data.data.vapidPublicKey) {
          alert('Push 설정을 불러올 수 없습니다.');
          return;
        }
        var vapidKey = data.data.vapidPublicKey;

        return navigator.serviceWorker.getRegistration('/').then(function (reg) {
          if (!reg) {
            // push-sw.js 등록
            return navigator.serviceWorker.register('/push-sw.js', { scope: '/' });
          }
          return reg;
        }).then(function (reg) {
          return reg.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: _urlBase64ToUint8Array(vapidKey)
          });
        }).then(function (subscription) {
          // 서버에 구독 저장
          return _authFetch(PUSH_API_BASE + '/subscribe', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ subscription: subscription.toJSON() })
          });
        }).then(function (r) { return r.json(); })
        .then(function (result) {
          if (result.success) {
            pushSubscribed = true;
            stopPolling(); // Push 구독 성공 → 폴링 중단
            updatePushToggleUI();
          }
        });
      })
      .catch(function (err) {
        console.error('[notification-bell] Push subscribe error:', err);
        if (err.name === 'NotAllowedError') {
          alert('알림 권한이 거부되었습니다. 브라우저 설정에서 허용해주세요.');
        }
      });
  }

  function unsubscribePush() {
    navigator.serviceWorker.getRegistration('/').then(function (reg) {
      if (!reg) return;
      return reg.pushManager.getSubscription();
    }).then(function (sub) {
      if (!sub) return;
      var endpoint = sub.endpoint;
      return sub.unsubscribe().then(function () {
        return _authFetch(PUSH_API_BASE + '/unsubscribe', {
          method: 'DELETE',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ endpoint: endpoint })
        });
      });
    }).then(function () {
      pushSubscribed = false;
      startPolling(); // Push 해제 → 폴링 복구
      updatePushToggleUI();
    }).catch(function (err) {
      console.error('[notification-bell] Push unsubscribe error:', err);
    });
  }

  function checkPushStatus() {
    if (!('serviceWorker' in navigator) || !('PushManager' in window)) return;
    navigator.serviceWorker.getRegistration('/').then(function (reg) {
      if (!reg) return;
      return reg.pushManager.getSubscription();
    }).then(function (sub) {
      if (sub) {
        pushSubscribed = true;
        stopPolling(); // 이미 구독 상태면 폴링 불필요
        // Push로 뱃지만 갱신 (초기 1회)
        fetchUnreadCount();
      }
    }).catch(function () {});
  }

  function updatePushToggleUI() {
    var btn = document.getElementById('notif-push-toggle');
    if (!btn) return;
    if (ntfySubscribed) {
      // ntfy 활성화 시 Web Push 비활성화
      btn.textContent = 'Push';
      btn.style.borderColor = '#E5E7EB';
      btn.style.color = '#D1D5DB';
      btn.disabled = true;
      btn.title = 'ntfy 사용 중에는 Push를 사용할 수 없습니다';
    } else if (pushSubscribed) {
      btn.textContent = 'Push 해제';
      btn.style.borderColor = '#EF4444';
      btn.style.color = '#EF4444';
      btn.disabled = false;
      btn.title = 'Push 알림 해제';
    } else {
      btn.textContent = 'Push';
      btn.style.borderColor = '#D1D5DB';
      btn.style.color = '#6B7280';
      btn.disabled = false;
      btn.title = 'Push 알림 설정';
    }
  }

  /* ========== ntfy ========== */
  function handleNtfyToggle(e) {
    e && e.stopPropagation();
    if (ntfySubscribed) {
      unsubscribeNtfy();
    } else {
      subscribeNtfy();
    }
  }

  function subscribeNtfy() {
    _authFetch(PUSH_API_BASE + '/ntfy/subscribe', { method: 'POST' })
      .then(function (r) { return r.json(); })
      .then(function (data) {
        if (!data.success) {
          alert('ntfy 구독 등록 실패');
          return;
        }
        ntfySubscribed = true;
        updateNtfyToggleUI();
        updatePushToggleUI();
        showNtfySetupModal(data.data);
      })
      .catch(function (err) {
        console.error('[notification-bell] ntfy subscribe error:', err);
      });
  }

  function unsubscribeNtfy() {
    _authFetch(PUSH_API_BASE + '/ntfy/unsubscribe', { method: 'DELETE' })
      .then(function (r) { return r.json(); })
      .then(function () {
        ntfySubscribed = false;
        updateNtfyToggleUI();
        updatePushToggleUI();
        checkPushStatus();
      })
      .catch(function (err) {
        console.error('[notification-bell] ntfy unsubscribe error:', err);
      });
  }

  function checkNtfyStatus() {
    _authFetch(PUSH_API_BASE + '/ntfy/status')
      .then(function (r) { return r.json(); })
      .then(function (data) {
        if (data.success && data.data.subscribed) {
          ntfySubscribed = true;
          updateNtfyToggleUI();
          updatePushToggleUI();
        }
      })
      .catch(function () {});
  }

  function updateNtfyToggleUI() {
    var btn = document.getElementById('notif-ntfy-toggle');
    if (!btn) return;
    if (ntfySubscribed) {
      btn.textContent = 'ntfy 해제';
      btn.style.borderColor = '#EF4444';
      btn.style.color = '#EF4444';
    } else {
      btn.textContent = 'ntfy';
      btn.style.borderColor = '#D1D5DB';
      btn.style.color = '#6B7280';
    }
  }

  function showNtfySetupModal(info) {
    // 기존 모달 제거
    var existing = document.getElementById('ntfy-setup-modal');
    if (existing) existing.remove();

    var overlay = document.createElement('div');
    overlay.id = 'ntfy-setup-modal';
    overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);z-index:10000;display:flex;align-items:center;justify-content:center;';

    var modal = document.createElement('div');
    modal.style.cssText = 'background:#fff;border-radius:12px;padding:24px;max-width:380px;width:90%;box-shadow:0 20px 40px rgba(0,0,0,.2);';
    modal.innerHTML =
      '<h3 style="margin:0 0 16px;font-size:16px;color:#111827;">ntfy 앱 설정 안내</h3>' +
      '<div style="font-size:13px;color:#374151;line-height:1.6;">' +
        '<p style="margin:0 0 12px;"><strong>1.</strong> ntfy 앱 설치<br>' +
          '<span style="color:#6B7280;">Android: Play Store / iOS: App Store</span></p>' +
        '<p style="margin:0 0 12px;"><strong>2.</strong> 앱에서 서버 추가<br>' +
          '<code style="background:#F3F4F6;padding:2px 6px;border-radius:3px;font-size:12px;">' + _escHtml(info.serverUrl) + '</code></p>' +
        '<p style="margin:0 0 12px;"><strong>3.</strong> 계정 로그인<br>' +
          '아이디: <code style="background:#F3F4F6;padding:2px 6px;border-radius:3px;font-size:12px;">' + _escHtml(info.username) + '</code><br>' +
          '비밀번호: <code style="background:#F3F4F6;padding:2px 6px;border-radius:3px;font-size:12px;">' + _escHtml(info.password) + '</code></p>' +
        '<p style="margin:0;"><strong>4.</strong> 토픽 구독<br>' +
          '<code style="background:#F3F4F6;padding:2px 6px;border-radius:3px;font-size:12px;">' + _escHtml(info.topic) + '</code></p>' +
      '</div>' +
      '<button id="ntfy-modal-close" style="margin-top:16px;width:100%;padding:10px;background:#3B82F6;color:#fff;border:none;border-radius:6px;font-size:14px;cursor:pointer;">확인</button>';

    overlay.appendChild(modal);
    document.body.appendChild(overlay);

    document.getElementById('ntfy-modal-close').addEventListener('click', function () {
      overlay.remove();
    });
    overlay.addEventListener('click', function (e) {
      if (e.target === overlay) overlay.remove();
    });
  }

  /* ========== Push SW message handler ========== */
  function listenForPushMessages() {
    if (!('serviceWorker' in navigator)) return;
    navigator.serviceWorker.addEventListener('message', function (e) {
      if (e.data && e.data.type === 'NOTIFICATION_RECEIVED') {
        // Push 수신 시 뱃지 즉시 갱신
        fetchUnreadCount();
      }
    });
  }

  /* ========== Helpers ========== */
  function _timeAgo(dateStr) {
    if (!dateStr) return '';
    var now = Date.now();
    var then = new Date(dateStr).getTime();
    var diff = Math.floor((now - then) / 1000);
    if (diff < 60) return '방금 전';
    if (diff < 3600) return Math.floor(diff / 60) + '분 전';
    if (diff < 86400) return Math.floor(diff / 3600) + '시간 전';
    if (diff < 604800) return Math.floor(diff / 86400) + '일 전';
    return dateStr.substring(0, 10);
  }

  function _typeLabel(type) {
    var map = { system: '시스템', repair: '설비수리', safety: '안전', nonconformity: '부적합', partner_work: '협력업체', day_labor: '일용공' };
    return map[type] || type || '알림';
  }

  function _escHtml(s) {
    if (!s) return '';
    var d = document.createElement('div');
    d.textContent = s;
    return d.innerHTML;
  }

  function _escAttr(s) {
    if (!s) return '';
    return s.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  }

  function _urlBase64ToUint8Array(base64String) {
    var padding = '='.repeat((4 - base64String.length % 4) % 4);
    var base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
    var raw = atob(base64);
    var arr = new Uint8Array(raw.length);
    for (var i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);
    return arr;
  }

  /* ========== Init ========== */
  function init() {
    // 토큰 없으면 동작하지 않음
    if (!_getToken()) return;

    injectBell();
    startPolling();
    checkNtfyStatus();
    checkPushStatus();
    listenForPushMessages();
  }

  // DOM ready 또는 즉시 실행
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})();
