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

const PushSubscriptionsSection = () => {
  const { user } = useSession();
  const [subs, setSubs] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [flash, setFlash] = React.useState('');

  const reload = React.useCallback(async () => {
    try {
      const { subscriptions } = await api.pushList();
      setSubs(subscriptions || []);
    } catch { setSubs([]); }
    setLoading(false);
  }, []);

  React.useEffect(() => { reload(); }, [reload]);

  const notifySupported =
    typeof window !== 'undefined' &&
    'serviceWorker' in navigator &&
    'PushManager' in window;

  const isIOSSafari = /iPad|iPhone|iPod/.test(navigator.userAgent || '') && !window.MSStream;
  const isStandalone =
    window.matchMedia?.('(display-mode: standalone)').matches ||
    window.navigator.standalone === true;

  const subscribe = async () => {
    if (busy) return;
    setError(''); setBusy(true);
    try {
      if (!('serviceWorker' in navigator)) {
        setError('Ваш браузер не поддерживает Service Worker — push-уведомления невозможны.'); setBusy(false); return;
      }
      if (!('PushManager' in window)) {
        setError('Ваш браузер не поддерживает PushManager.'); setBusy(false); return;
      }
      if (!('Notification' in window)) {
        setError('Ваш браузер не поддерживает Notification API.'); setBusy(false); return;
      }
      if (isIOSSafari && !isStandalone) {
        setError('На iPhone/iPad push-уведомления работают только после установки приложения на главный экран (кнопка «Установить приложение»).');
        setBusy(false); return;
      }
      if (Notification.permission === 'denied') {
        setError('Уведомления запрещены в настройках браузера для этого сайта. Откройте их вручную и попробуйте снова.');
        setBusy(false); return;
      }

      const permission = Notification.permission === 'granted'
        ? 'granted'
        : await Notification.requestPermission();
      if (permission !== 'granted') {
        setError('Нужно разрешить уведомления в диалоге браузера.'); setBusy(false); return;
      }

      const regPromise = navigator.serviceWorker.ready;
      const timeout = new Promise((_, rej) => setTimeout(() => rej(new Error('Service Worker не активировался за 10 секунд')), 10000));
      const reg = await Promise.race([regPromise, timeout]);

      const { publicKey } = await api.pushVapidKey();
      if (!publicKey || typeof publicKey !== 'string' || publicKey.length < 40) {
        setError('Push-сервер вернул некорректный VAPID-ключ. Сообщите администратору.'); setBusy(false); return;
      }

      const existing = await reg.pushManager.getSubscription();
      if (existing) {
        try { await existing.unsubscribe(); }
        catch (e) { console.warn('[push] unsubscribe existing failed, continuing:', e); }
      }

      let sub;
      try {
        sub = await reg.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: urlBase64ToUint8Array(publicKey),
        });
      } catch (e) {
        console.error('[push] pushManager.subscribe failed:', e);
        if (e?.name === 'NotAllowedError') {
          setError('Браузер отклонил подписку. Проверьте, что разрешены уведомления для этого сайта.');
        } else if (e?.name === 'AbortError') {
          setError('Подписка отменена. Обычно это значит, что push-сервер браузера временно недоступен — попробуйте позже.');
        } else {
          setError('Не удалось создать подписку: ' + (e?.message || String(e)));
        }
        setBusy(false); return;
      }

      const json = sub.toJSON();
      if (!json.endpoint || !json.keys?.p256dh || !json.keys?.auth) {
        setError('Браузер вернул неполную подписку — ключи отсутствуют.'); setBusy(false); return;
      }

      try {
        await api.pushSubscribe(json.endpoint, {
          p256dh: json.keys.p256dh, auth: json.keys.auth,
        }, navigator.userAgent);
      } catch (e) {
        console.error('[push] api.pushSubscribe failed:', e);
        setError('Сервер отклонил подписку: ' + (e?.message || e?.status));
        setBusy(false); return;
      }

      await reload();
      setFlash('Устройство подписано');
      setTimeout(()=> setFlash(''), 2200);
    } catch (e) {
      console.error('[push] subscribe flow error:', e);
      setError('Не удалось подписаться: ' + (e?.message || String(e)));
    }
    setBusy(false);
  };

  const unsubscribe = async (id) => {
    if (!confirm('Отписать это устройство от уведомлений?')) return;
    setError('');
    try {
      await api.pushUnsubscribe(id);
      await reload();
    } catch (e) { setError('Ошибка: ' + (e?.message || String(e))); }
  };

  const testPush = async () => {
    setError(''); setBusy(true);
    try {
      const res = await api.pushTest();
      setFlash(`Отправлено: ${res.sent}, не дошло: ${res.failed}`);
      setTimeout(()=> setFlash(''), 3200);
    } catch (e) { setError('Ошибка: ' + (e?.message || String(e))); }
    setBusy(false);
  };

  const friendlyName = (ua) => {
    if (!ua) return 'Устройство';
    if (/iPhone|iPad/.test(ua)) return 'iPhone/iPad (Safari)';
    if (/Android/.test(ua)) return 'Android';
    if (/Mac OS/.test(ua)) return 'Mac (Chrome/Safari)';
    if (/Windows/.test(ua)) return 'Windows (Chrome/Edge)';
    return 'Устройство';
  };

  return (
    <Card>
      <SectionTitle
        eyebrow="УВЕДОМЛЕНИЯ"
        title={`Push-уведомления · ${subs.length}`}
        action={subs.length > 0 ? <Button variant="ghost" size="sm" onClick={testPush} disabled={busy}>Тест</Button> : null}
      />
      {error && <div style={{ padding: 10, borderRadius: 10, background:'#FBE1DA', color:'#9A3218', fontSize: 13, marginBottom: 14 }}>{error}</div>}
      {flash && <div style={{ padding: 10, borderRadius: 10, background:'var(--good-1)', color:'#4A6E33', fontSize: 13, marginBottom: 14 }}>{flash}</div>}

      <div style={{ display:'flex', alignItems:'center', gap: 14, padding: '12px 0', borderBottom: subs.length > 0 ? '1px solid var(--border)' : 'none' }}>
        <div style={{ width: 44, height: 44, borderRadius: 14, background:'var(--surface-2)', border:'1px solid var(--border)', display:'grid', placeItems:'center', color:'var(--accent)' }}>
          <IconSparkle size={22}/>
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 600, fontSize: 15 }}>Подписаться на этом устройстве</div>
          <div style={{ fontSize: 13, color:'var(--fg-muted)', marginTop: 2 }}>
            Уведомления о новых оценках и комментариях. Можно подписывать несколько устройств одновременно.
          </div>
        </div>
        <Button variant="primary" size="sm" onClick={subscribe} disabled={busy || !notifySupported} leading={<IconPlus size={14}/>}>
          {notifySupported ? 'Подписаться' : 'Недоступно'}
        </Button>
      </div>

      {!loading && subs.length > 0 && (
        <div style={{ display:'flex', flexDirection:'column', gap: 2, paddingTop: 4 }}>
          {subs.map((s, i) => (
            <div key={s.id} style={{ display:'flex', alignItems:'center', gap: 10, padding:'10px 0', borderBottom: i < subs.length-1 ? '1px solid var(--border)' : 'none' }}>
              <div style={{ flex:1 }}>
                <div style={{ fontSize: 14, fontWeight: 500 }}>{friendlyName(s.ua)}</div>
                <div className="mono" style={{ fontSize: 11, color:'var(--fg-subtle)', marginTop: 2 }}>
                  …{s.endpointPreview} · {new Date(s.createdAt * 1000).toLocaleDateString('ru-RU')}
                </div>
              </div>
              <Button variant="ghost" size="sm" onClick={()=> unsubscribe(s.id)}>Отписать</Button>
            </div>
          ))}
        </div>
      )}
    </Card>
  );
};

Object.assign(window, { PushSubscriptionsSection });
