import React, { useState, useEffect, useCallback, useRef } from 'react'
import { createRoot } from 'react-dom/client'
import ConversationList from '../../components/messaging/ConversationList'
import ConversationThread from '../../components/messaging/ConversationThread'
import NewConversationModal from '../../components/messaging/NewConversationModal'

// ── helpers ──────────────────────────────────────────────────────────────────

function getCsrf() {
  return document.querySelector('meta[name="csrf-token"]')?.content ?? ''
}

async function apiFetch(url, options = {}) {
  const isFormData = options.body instanceof FormData
  const headers = {
    'X-CSRF-TOKEN': getCsrf(),
    Accept: 'application/json',
    ...options.headers,
  }

  if (!isFormData) {
    headers['Content-Type'] = 'application/json'
  }

  const res = await fetch(url, {
    headers,
    ...options,
  })
  if (!res.ok) {
    const err = await res.json().catch(() => ({}))
    throw new Error(err.message ?? `HTTP ${res.status}`)
  }
  return res.json()
}

// ── MessagesPage ─────────────────────────────────────────────────────────────

function MessagesPage({ userId, username, activeConversationId: initialId }) {
  const [conversations, setConversations] = useState([])
  const [loadingConvs, setLoadingConvs] = useState(true)
  const [activeId, setActiveId] = useState(initialId ?? null)
  const [showNewModal, setShowNewModal] = useState(false)
  const [searchQuery, setSearchQuery] = useState('')
  const [searchResults, setSearchResults] = useState([])
  const [searching, setSearching] = useState(false)
  const pollRef = useRef(null)

  // ── Load conversations list ────────────────────────────────────────────────
  const loadConversations = useCallback(async () => {
    try {
      const data = await apiFetch('/api/messages/conversations')
      setConversations(data.data ?? [])
    } catch (e) {
      console.error('Failed to load conversations', e)
    } finally {
      setLoadingConvs(false)
    }
  }, [])

  useEffect(() => {
    loadConversations()

    // Phase 1 polling: refresh conversation list every 15 seconds
    pollRef.current = setInterval(loadConversations, 15_000)
    return () => clearInterval(pollRef.current)
  }, [loadConversations])

  const handleSelectConversation = useCallback((id) => {
    setActiveId(id)
    history.replaceState(null, '', `/messages/${id}`)
  }, [])

  const handleConversationCreated = useCallback((conv) => {
    setShowNewModal(false)
    loadConversations()
    setActiveId(conv.id)
    history.replaceState(null, '', `/messages/${conv.id}`)
  }, [loadConversations])

  const handleMarkRead = useCallback((conversationId) => {
    setConversations(prev =>
      prev.map(c => c.id === conversationId ? { ...c, unread_count: 0 } : c)
    )
  }, [])

  useEffect(() => {
    let cancelled = false

    const run = async () => {
      const q = searchQuery.trim()
      if (q.length < 2) {
        setSearchResults([])
        setSearching(false)
        return
      }

      setSearching(true)
      try {
        const data = await apiFetch(`/api/messages/search?q=${encodeURIComponent(q)}`)
        if (!cancelled) {
          setSearchResults(data.data ?? [])
        }
      } catch (_) {
        if (!cancelled) {
          setSearchResults([])
        }
      } finally {
        if (!cancelled) {
          setSearching(false)
        }
      }
    }

    const timer = setTimeout(run, 250)
    return () => {
      cancelled = true
      clearTimeout(timer)
    }
  }, [searchQuery])

  const openSearchResult = useCallback((item) => {
    if (!item?.conversation_id) return
    setActiveId(item.conversation_id)
    history.replaceState(null, '', `/messages/${item.conversation_id}?focus=${item.id}`)
  }, [])

  const activeConversation = conversations.find(c => c.id === activeId) ?? null

  return (
    <div className="mx-auto max-w-screen-xl px-4 sm:px-6 lg:px-8 py-6">
      <div className="flex h-[calc(100vh-10rem)] overflow-hidden rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 shadow-sm">

        {/* ── Left panel: conversation list ─────────────────────────────── */}
        <aside className={`w-full sm:w-80 flex-shrink-0 border-r border-gray-200 dark:border-gray-700 flex flex-col ${activeId ? 'hidden sm:flex' : 'flex'}`}>
          <div className="flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700">
            <h1 className="text-lg font-semibold text-gray-900 dark:text-gray-100">Messages</h1>
            <button
              onClick={() => setShowNewModal(true)}
              className="rounded-full p-1.5 text-gray-500 hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
              title="New message"
            >
              <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                <path fillRule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clipRule="evenodd" />
              </svg>
            </button>
          </div>

          <div className="px-3 py-2 border-b border-gray-100 dark:border-gray-800">
            <input
              type="search"
              value={searchQuery}
              onChange={e => setSearchQuery(e.target.value)}
              placeholder="Search all messages…"
              className="w-full rounded-lg bg-gray-100 dark:bg-gray-800 px-3 py-1.5 text-sm text-gray-900 dark:text-gray-100 placeholder-gray-400 outline-none focus:ring-2 focus:ring-blue-500"
            />
            {searching && <p className="mt-1 text-[11px] text-gray-400">Searching…</p>}
          </div>

          {searchQuery.trim().length >= 2 && (
            <div className="border-b border-gray-100 dark:border-gray-800 max-h-44 overflow-y-auto">
              {searchResults.length === 0 && !searching && (
                <p className="px-3 py-2 text-xs text-gray-400">No results.</p>
              )}
              {searchResults.map(item => (
                <button
                  key={`search-${item.id}`}
                  onClick={() => openSearchResult(item)}
                  className="w-full text-left px-3 py-2 hover:bg-gray-50 dark:hover:bg-gray-800/60 border-b border-gray-100 dark:border-gray-800"
                >
                  <p className="text-xs text-gray-500">@{item.sender?.username ?? 'unknown'} · {new Date(item.created_at).toLocaleString()}</p>
                  <p className="text-sm text-gray-800 dark:text-gray-200 truncate">{item.body || '(attachment)'}</p>
                </button>
              ))}
            </div>
          )}

          <ConversationList
            conversations={conversations}
            loading={loadingConvs}
            activeId={activeId}
            currentUserId={userId}
            onSelect={handleSelectConversation}
          />
        </aside>

        {/* ── Right panel: thread ───────────────────────────────────────── */}
        <main className={`flex-1 flex flex-col min-w-0 ${activeId ? 'flex' : 'hidden sm:flex'}`}>
          {activeId ? (
            <ConversationThread
              key={activeId}
              conversationId={activeId}
              conversation={activeConversation}
              currentUserId={userId}
              currentUsername={username}
              apiFetch={apiFetch}
              onBack={() => { setActiveId(null); history.replaceState(null, '', '/messages') }}
              onMarkRead={handleMarkRead}
              onConversationUpdated={loadConversations}
            />
          ) : (
            <div className="flex flex-1 items-center justify-center text-gray-400 dark:text-gray-600">
              <div className="text-center">
                <svg xmlns="http://www.w3.org/2000/svg" className="mx-auto h-12 w-12 mb-3 opacity-40" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
                </svg>
                <p className="text-sm">Select a conversation or start a new one</p>
              </div>
            </div>
          )}
        </main>
      </div>

      {showNewModal && (
        <NewConversationModal
          currentUserId={userId}
          apiFetch={apiFetch}
          onCreated={handleConversationCreated}
          onClose={() => setShowNewModal(false)}
        />
      )}
    </div>
  )
}

// ── Mount ────────────────────────────────────────────────────────────────────

const el = document.getElementById('messages-root')
if (el) {
  function parse(key, fallback = null) {
    try { return JSON.parse(el.dataset[key] ?? 'null') ?? fallback } catch { return fallback }
  }
  createRoot(el).render(
    <MessagesPage
      userId={parse('userId')}
      username={parse('username', '')}
      activeConversationId={parse('activeConversationId')}
    />
  )
}

export default MessagesPage
