import { createContext, useContext, useEffect, useRef, useState, useCallback } from 'react'
import useAuthStore from '../store/authStore'
import client from '../api/client'

const NotificationContext = createContext(null)

export function useNotifications() {
  return useContext(NotificationContext)
}

// ─── Persistent banner (one message at a time, stacked) ───────────────────────

function NotificationBanner({ message, onAck }) {
  const tableIds = (() => { try { return JSON.parse(message.table_ids || '[]') } catch { return [] } })()

  return (
    <div style={{
      display: 'flex', alignItems: 'flex-start', gap: 12,
      background: '#1e1b4b', border: '1px solid #6366f1',
      borderRadius: 14, padding: '12px 14px',
      boxShadow: '0 8px 24px rgba(0,0,0,0.4)',
      animation: 'slideIn 0.25s ease',
    }}>
      <span style={{ fontSize: 22, flexShrink: 0 }}>📢</span>
      <div style={{ flex: 1, minWidth: 0 }}>
        {message.sender_name && (
          <div style={{ fontSize: 11, fontWeight: 700, color: '#a5b4fc', marginBottom: 2, textTransform: 'uppercase', letterSpacing: 0.5 }}>
            {message.sender_name}
          </div>
        )}
        <div style={{ fontSize: 15, fontWeight: 600, color: '#e2e8f0', lineHeight: 1.4 }}>
          {message.body}
        </div>
        {tableIds.length > 0 && (
          <div style={{ fontSize: 12, color: '#94a3b8', marginTop: 4 }}>
            Τραπέζι{tableIds.length > 1 ? 'α' : ''}: {tableIds.join(', ')}
          </div>
        )}
      </div>
      <button
        onClick={() => onAck(message.id)}
        style={{
          flexShrink: 0, height: 32, padding: '0 12px',
          borderRadius: 8, border: 'none',
          background: '#4f46e5', color: 'white',
          fontSize: 12, fontWeight: 700, cursor: 'pointer',
        }}
      >OK ✓</button>
    </div>
  )
}

export function NotificationProvider({ children }) {
  const { token, user } = useAuthStore()
  const [pendingMessages, setPendingMessages] = useState([])
  const [recentMessages, setRecentMessages] = useState([])

  const fetchUnread = useCallback(async () => {
    if (!token || !user) return
    try {
      const res = await client.get('/api/messages/unread')
      setPendingMessages(res.data)
    } catch { /* offline or unauthenticated — swallow */ }
  }, [token, user?.id])

  const fetchRecent = useCallback(async () => {
    if (!token || !user) return
    try {
      const res = await client.get('/api/messages/recent?limit=10')
      setRecentMessages(res.data)
    } catch { }
  }, [token, user?.id])

  // Initial load + 5s fallback poll (SSE is primary, poll is safety net)
  useEffect(() => {
    if (!token || !user) return
    fetchUnread()
    fetchRecent()
    const id = setInterval(fetchUnread, 5000)
    return () => clearInterval(id)
  }, [token, user?.id])

  // SSE message_sent events → add to pending without polling
  useEffect(() => {
    function onSSEEvent(e) {
      const { type, data } = e.detail
      if (type !== 'message_sent') return
      if (!user) return

      // Check if this message targets us (empty = broadcast)
      const targets = data.target_waiter_ids || []
      if (targets.length > 0 && !targets.includes(user.id)) return

      const msg = {
        id: data.id,
        sender_id: data.sender_id,
        sender_name: data.sender_name,
        body: data.body,
        table_ids: data.table_ids,
        created_at: data.created_at,
        acked_by: [],
      }

      setPendingMessages(prev => {
        if (prev.find(m => m.id === msg.id)) return prev
        return [msg, ...prev]
      })
      setRecentMessages(prev => {
        if (prev.find(m => m.id === msg.id)) return prev
        return [msg, ...prev].slice(0, 10)
      })
    }

    window.addEventListener('sse-event', onSSEEvent)
    return () => window.removeEventListener('sse-event', onSSEEvent)
  }, [user?.id])

  // Fallback: re-fetch unread when SSE reconnects (catches any messages missed during gap)
  useEffect(() => {
    function onSSEConnect() {
      fetchUnread()
      fetchRecent()
    }
    // SSEProvider fires this via setOnline — we listen to the connection store indirectly
    // through the backend-coming-back-online signal that SSEProvider dispatches
    window.addEventListener('sse-reconnected', onSSEConnect)
    return () => window.removeEventListener('sse-reconnected', onSSEConnect)
  }, [fetchUnread, fetchRecent])

  async function ackMessage(messageId) {
    try {
      await client.post(`/api/messages/${messageId}/ack`)
      setPendingMessages(prev => prev.filter(m => m.id !== messageId))
      fetchRecent()
    } catch { }
  }

  const unreadCount = pendingMessages.length

  return (
    <NotificationContext.Provider value={{ pendingMessages, recentMessages, unreadCount, ackMessage, fetchRecent, fetchUnread }}>
      {children}

      {/* Floating banner stack (max 3 visible) */}
      {pendingMessages.length > 0 && (
        <div style={{
          position: 'fixed', top: 64, left: 0, right: 0, zIndex: 9999,
          padding: '0 12px',
          display: 'flex', flexDirection: 'column', gap: 8,
          pointerEvents: 'none',
        }}>
          <style>{`@keyframes slideIn { from { transform: translateY(-16px); opacity: 0 } to { transform: translateY(0); opacity: 1 } }`}</style>
          {pendingMessages.slice(0, 3).map(msg => (
            <div key={msg.id} style={{ pointerEvents: 'all' }}>
              <NotificationBanner message={msg} onAck={ackMessage} />
            </div>
          ))}
          {pendingMessages.length > 3 && (
            <div style={{
              textAlign: 'center', fontSize: 12, color: '#94a3b8',
              pointerEvents: 'all',
            }}>
              +{pendingMessages.length - 3} ακόμα μηνύματα
            </div>
          )}
        </div>
      )}
    </NotificationContext.Provider>
  )
}
