"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { Bell, BellOff } from "lucide-react";

// VAPID 공개키(base64url) → Uint8Array
function urlBase64ToUint8Array(base64String: string): Uint8Array {
  const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
  const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
  const raw = atob(base64);
  const arr = new Uint8Array(raw.length);
  for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);
  return arr;
}

// 사용자 의도 기억 — pushManager 가 SW 갱신/브라우저 quirks 로 일시적으로 sub 를 잃어도
// 권한이 granted 상태면 mount 시 자동 재구독해 'on' 상태를 유지.
const INTENT_KEY = "momo-push-intent";
const readIntent = (): "on" | "off" | null => {
  try { return (typeof localStorage !== "undefined" ? localStorage.getItem(INTENT_KEY) : null) as "on" | "off" | null; }
  catch { return null; }
};
const writeIntent = (v: "on" | "off" | null) => {
  try { if (v) localStorage.setItem(INTENT_KEY, v); else localStorage.removeItem(INTENT_KEY); }
  catch { /* ignore */ }
};

// 새 품목 판매 알림 켜기/끄기 스위치. (PWA 설치 + 알림 권한 필요)
export function PushOptIn() {
  const [on, setOn] = useState(false);
  const [busy, setBusy] = useState(false);
  const [denied, setDenied] = useState(false);
  const bootRef = useRef(false);

  const supported =
    typeof window !== "undefined" &&
    "serviceWorker" in navigator &&
    "PushManager" in window &&
    "Notification" in window;

  // 서버에 현재 구독 endpoint 저장 — 의도 'on' 일 때만 호출.
  const saveSubscriptionToServer = useCallback(async (sub: PushSubscription): Promise<boolean> => {
    const r = await fetch("/api/m/push/subscribe", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ subscription: sub.toJSON(), userAgent: navigator.userAgent }),
    });
    return r.ok;
  }, []);

  // 권한 granted 전제로 silent 하게 (재)구독. 권한이 default 이면 호출 측에서 먼저 요청.
  const subscribeSilently = useCallback(async (): Promise<PushSubscription | null> => {
    if (Notification.permission !== "granted") return null;
    const reg = await navigator.serviceWorker.ready;
    let sub = await reg.pushManager.getSubscription();
    if (!sub) {
      const res = await fetch("/api/m/push/vapid");
      if (!res.ok) return null;
      const { publicKey } = await res.json();
      if (!publicKey) return null;
      try {
        sub = await reg.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: urlBase64ToUint8Array(publicKey) as BufferSource,
        });
      } catch (e) {
        console.error("[push-optin] subscribe failed:", e);
        return null;
      }
    }
    if (sub) await saveSubscriptionToServer(sub).catch(() => {});
    return sub;
  }, [saveSubscriptionToServer]);

  // 마운트 시 상태 동기화
  useEffect(() => {
    if (!supported || bootRef.current) return;
    bootRef.current = true;
    (async () => {
      if (Notification.permission === "denied") {
        setDenied(true); setOn(false); writeIntent("off"); return;
      }
      const intent = readIntent();
      try {
        const reg = await navigator.serviceWorker.ready;
        const existing = await reg.pushManager.getSubscription();
        if (existing) {
          // 기존 구독 있으면 ON + 서버 동기화 (endpoint 가 바뀌었을 수도 있으니 다시 저장)
          await saveSubscriptionToServer(existing).catch(() => {});
          setOn(true); writeIntent("on"); return;
        }
        // 구독 없지만 사용자가 이전에 켜뒀고 권한 granted 이면 조용히 재구독
        if (intent === "on" && Notification.permission === "granted") {
          const sub = await subscribeSilently();
          setOn(!!sub);
          if (!sub) writeIntent("off");
          return;
        }
        setOn(false);
      } catch (e) {
        console.error("[push-optin] mount sync error:", e);
        setOn(false);
      }
    })();
  }, [supported, saveSubscriptionToServer, subscribeSilently]);

  // 켜기 — 권한이 default 면 요청, granted 면 바로 구독.
  const turnOn = useCallback(async (): Promise<boolean> => {
    const perm = Notification.permission === "granted"
      ? "granted"
      : await Notification.requestPermission();
    if (perm !== "granted") {
      setDenied(perm === "denied");
      writeIntent("off");
      return false;
    }
    setDenied(false);
    const sub = await subscribeSilently();
    if (sub) { writeIntent("on"); return true; }
    return false;
  }, [subscribeSilently]);

  const turnOff = useCallback(async (): Promise<void> => {
    writeIntent("off"); // 의도 먼저 기록 — 도중 실패해도 다음 mount 가 자동 재구독 안 함
    try {
      const reg = await navigator.serviceWorker.ready;
      const sub = await reg.pushManager.getSubscription();
      if (sub) {
        await fetch("/api/m/push/unsubscribe", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ endpoint: sub.endpoint }),
        }).catch(() => {});
        await sub.unsubscribe().catch(() => {});
      }
    } catch (e) {
      console.error("[push-optin] turnOff error:", e);
    }
  }, []);

  const toggle = async () => {
    if (busy) return;
    setBusy(true);
    try {
      if (on) { await turnOff(); setOn(false); }
      else { setOn(await turnOn()); }
    } finally {
      setBusy(false);
    }
  };

  if (!supported) return null;

  return (
    <div className="flex items-center gap-2">
      <span className="inline-flex items-center gap-1 text-xs font-semibold text-slate-600">
        {on ? <Bell size={14} className="text-emerald-700" /> : <BellOff size={14} className="text-slate-400" />}
        알림 {on ? "켜짐" : "꺼짐"}
      </span>
      <button
        type="button"
        role="switch"
        aria-checked={on}
        onClick={toggle}
        disabled={busy || denied}
        title={denied ? "기기/브라우저 설정에서 알림을 허용해주세요." : on ? "알림 끄기" : "알림 켜기"}
        className={`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors disabled:opacity-50 ${
          on ? "bg-emerald-600" : "bg-slate-300"
        }`}
      >
        <span
          className={`inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform ${
            on ? "translate-x-[22px]" : "translate-x-0.5"
          }`}
        />
      </button>
      {denied && <span className="text-[11px] text-rose-500">설정에서 허용 필요</span>}
    </div>
  );
}
