import { useEffect, useRef, useState, useCallback } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import client from '../api/client'
import useAuthStore from '../store/authStore'
import useChatStore from '../store/chatStore'

// ─── Helpers ──────────────────────────────────────────────────────────────────

function formatTime(dateStr) {
  if (!dateStr) return ''
  return new Date(dateStr).toLocaleTimeString('el-GR', { hour: '2-digit', minute: '2-digit' })
}

function formatDateLabel(dateStr) {
  const date = new Date(dateStr)
  const now = new Date()
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
  const yesterday = new Date(today)
  yesterday.setDate(yesterday.getDate() - 1)
  const d = new Date(date.getFullYear(), date.getMonth(), date.getDate())

  if (d.getTime() === today.getTime()) return 'Σήμερα'
  if (d.getTime() === yesterday.getTime()) return 'Χθες'
  return date.toLocaleDateString('el-GR', { weekday: 'long', day: 'numeric', month: 'long' })
}

function sameDay(a, b) {
  const da = new Date(a), db = new Date(b)
  return da.getFullYear() === db.getFullYear() &&
    da.getMonth() === db.getMonth() &&
    da.getDate() === db.getDate()
}

// ─── Message bubble ───────────────────────────────────────────────────────────

function MessageBubble({ msg, isOwn, showSender, isGroup }) {
  if (msg.is_deleted) {
    return (
      <div style={{
        alignSelf: isOwn ? 'flex-end' : 'flex-start',
        maxWidth: '75%',
        padding: '8px 14px',
        borderRadius: isOwn ? '18px 18px 4px 18px' : '18px 18px 18px 4px',
        background: 'var(--bg3)',
      }}>
        <span style={{ fontSize: 13, color: 'var(--muted)', fontStyle: 'italic' }}>
          Το μήνυμα διαγράφηκε
        </span>
      </div>
    )
  }

  return (
    <div style={{
      alignSelf: isOwn ? 'flex-end' : 'flex-start',
      maxWidth: '75%',
      display: 'flex', flexDirection: 'column',
      alignItems: isOwn ? 'flex-end' : 'flex-start',
      gap: 3,
    }}>
      {isGroup && showSender && !isOwn && (
        <span style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', paddingLeft: 4 }}>
          {msg.sender_name}
        </span>
      )}
      <div style={{
        padding: '10px 14px',
        borderRadius: isOwn ? '18px 18px 4px 18px' : '18px 18px 18px 4px',
        background: isOwn ? 'var(--accent)' : 'var(--bg2)',
        color: isOwn ? 'var(--accent-fg)' : 'var(--text)',
        fontSize: 15, lineHeight: 1.45, wordBreak: 'break-word',
      }}>
        {msg.body}
      </div>
      <span style={{ fontSize: 11, color: 'var(--muted)', paddingLeft: 2, paddingRight: 2 }}>
        {formatTime(msg.sent_at)}
      </span>
    </div>
  )
}

// ─── Date separator ───────────────────────────────────────────────────────────

function DateSeparator({ label }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 12,
      margin: '16px 0 8px',
    }}>
      <div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
      <span style={{
        fontSize: 12, fontWeight: 700, color: 'var(--muted)',
        letterSpacing: 0.5, whiteSpace: 'nowrap',
      }}>
        {label}
      </span>
      <div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
    </div>
  )
}

// ─── Auto-resize textarea ─────────────────────────────────────────────────────

function AutoTextarea({ value, onChange, onSubmit, placeholder }) {
  const ref = useRef(null)

  useEffect(() => {
    if (!ref.current) return
    ref.current.style.height = 'auto'
    const scrollH = ref.current.scrollHeight
    const lineH = 22 // approx line height
    const maxH = lineH * 3 + 16 // 3 lines + padding
    ref.current.style.height = Math.min(scrollH, maxH) + 'px'
  }, [value])

  function handleKeyDown(e) {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault()
      onSubmit()
    }
  }

  return (
    <textarea
      ref={ref}
      value={value}
      onChange={onChange}
      onKeyDown={handleKeyDown}
      placeholder={placeholder}
      rows={1}
      style={{
        flex: 1, resize: 'none', background: 'var(--bg3)',
        border: '1px solid var(--border)', borderRadius: 22,
        padding: '10px 16px', color: 'var(--text)', fontSize: 15,
        outline: 'none', lineHeight: 1.4, fontFamily: 'inherit',
        maxHeight: 82, overflowY: 'auto',
      }}
    />
  )
}

// ─── Leave confirmation modal ─────────────────────────────────────────────────

function LeaveModal({ onConfirm, onCancel }) {
  return (
    <div className="modal-overlay" onClick={onCancel}>
      <div
        className="modal-sheet"
        onClick={e => e.stopPropagation()}
        style={{ maxHeight: 'auto' }}
      >
        <div className="modal-handle" />
        <h2 className="modal-title" style={{ marginBottom: 8 }}>Αποχώρηση από ομάδα;</h2>
        <p style={{ fontSize: 14, color: 'var(--muted)', lineHeight: 1.5, marginBottom: 20 }}>
          Δεν θα λαμβάνετε πλέον μηνύματα από αυτή την ομάδα.
        </p>
        <div style={{ display: 'flex', gap: 10 }}>
          <button className="btn btn--secondary" style={{ flex: 1 }} onClick={onCancel}>Ακύρωση</button>
          <button
            style={{
              flex: 1, height: 44, borderRadius: 12, border: 'none',
              background: 'var(--danger)', color: '#fff',
              fontSize: 15, fontWeight: 700, cursor: 'pointer',
            }}
            onClick={onConfirm}
          >
            Αποχώρηση
          </button>
        </div>
      </div>
    </div>
  )
}

// ─── Main page ────────────────────────────────────────────────────────────────

export default function ChatThreadPage() {
  const { conversationId } = useParams()
  const navigate = useNavigate()
  const { user } = useAuthStore()

  const {
    conversations, messages: allMessages,
    upsertConversation, markConvRead, addMessage,
    setMessages, prependMessages, updateLastRead,
  } = useChatStore()

  const [inputText, setInputText] = useState('')
  const [sending, setSending] = useState(false)
  const [loadingMore, setLoadingMore] = useState(false)
  const [hasMore, setHasMore] = useState(true)
  const [showLeave, setShowLeave] = useState(false)
  const [initialLoad, setInitialLoad] = useState(true)

  const messagesEl = useRef(null)
  const bottomAnchor = useRef(null)
  const offsetRef = useRef(0)
  const PAGE_SIZE = 50

  const conv = conversations.find(c => c.id === conversationId)
  const rawMessages = allMessages[conversationId] || []
  // API returns newest-first, we display oldest-first
  const displayMessages = [...rawMessages].reverse()

  const isGroup = conv?.type === 'group'
  const isDirect = conv?.type === 'direct'

  const title = isGroup
    ? (conv?.name || 'Ομάδα')
    : (conv?.participants?.find(p => p.user_id !== user?.id)?.username || 'Συνομιλία')

  // ── Mark as read ─────────────────────────────────────────────────────────────

  const markRead = useCallback(async () => {
    try {
      await client.post(`/api/chat/conversations/${conversationId}/read`)
      markConvRead(conversationId)
    } catch {}
  }, [conversationId, markConvRead])

  // ── Initial load ─────────────────────────────────────────────────────────────

  useEffect(() => {
    let cancelled = false

    async function init() {
      // Load conversation metadata if we don't have it
      if (!conv) {
        try {
          const r = await client.get(`/api/chat/conversations/${conversationId}`)
          if (!cancelled) upsertConversation(r.data)
        } catch {}
      }

      // Load first page of messages
      try {
        const r = await client.get(
          `/api/chat/conversations/${conversationId}/messages?offset=0&limit=${PAGE_SIZE}`
        )
        if (!cancelled) {
          const msgs = r.data || []
          setMessages(conversationId, msgs)
          offsetRef.current = msgs.length
          setHasMore(msgs.length === PAGE_SIZE)
          setInitialLoad(false)
        }
      } catch {
        if (!cancelled) setInitialLoad(false)
      }

      markRead()
    }

    init()
    return () => { cancelled = true }
  }, [conversationId])

  // ── Scroll to bottom after initial load ───────────────────────────────────────

  useEffect(() => {
    if (!initialLoad && bottomAnchor.current) {
      bottomAnchor.current.scrollIntoView({ behavior: 'instant' })
    }
  }, [initialLoad])

  // ── Infinite scroll upward ────────────────────────────────────────────────────

  async function loadMore() {
    if (loadingMore || !hasMore) return
    const el = messagesEl.current
    const prevScrollHeight = el?.scrollHeight || 0
    const prevScrollTop = el?.scrollTop || 0

    setLoadingMore(true)
    try {
      const r = await client.get(
        `/api/chat/conversations/${conversationId}/messages?offset=${offsetRef.current}&limit=${PAGE_SIZE}`
      )
      const older = r.data || []
      prependMessages(conversationId, older)
      offsetRef.current += older.length
      setHasMore(older.length === PAGE_SIZE)

      // Restore scroll position after prepend
      requestAnimationFrame(() => {
        if (el) {
          el.scrollTop = el.scrollHeight - prevScrollHeight + prevScrollTop
        }
      })
    } catch {}
    setLoadingMore(false)
  }

  function handleScroll(e) {
    if (e.target.scrollTop < 60 && hasMore && !loadingMore) {
      loadMore()
    }
  }

  // ── SSE wiring ────────────────────────────────────────────────────────────────

  useEffect(() => {
    function onSSE(e) {
      const { type, data } = e.detail
      // conversationId from useParams is a string; SSE payload has an integer
      if (type === 'chat_message' && String(data.conversation_id) === conversationId) {
        // Own messages are handled optimistically in sendMessage — skip the SSE echo
        // to avoid showing the message twice before the optimistic replace completes.
        if (data.sender_id === user?.id) return
        const msg = {
          id: data.message_id,
          conversation_id: data.conversation_id,
          sender_id: data.sender_id,
          sender_name: data.sender_name,
          body: data.body,
          sent_at: data.sent_at,
          is_deleted: false,
        }
        addMessage(conversationId, msg)
        offsetRef.current += 1
        markRead()
        // Scroll to bottom if near bottom
        const el = messagesEl.current
        if (el && el.scrollHeight - el.scrollTop - el.clientHeight < 120) {
          requestAnimationFrame(() => {
            bottomAnchor.current?.scrollIntoView({ behavior: 'smooth' })
          })
        }
        // Update last_message in conv list
        const existingConv = useChatStore.getState().conversations.find(c => c.id === conversationId)
        if (existingConv) {
          upsertConversation({
            ...existingConv,
            last_message: { ...msg },
          })
        }
      } else if (type === 'chat_read' && String(data.conversation_id) === conversationId) {
        updateLastRead(data.conversation_id, data.user_id, data.read_at)
      }
    }
    window.addEventListener('sse-event', onSSE)
    return () => window.removeEventListener('sse-event', onSSE)
  }, [conversationId, addMessage, markRead, upsertConversation, updateLastRead])

  // ── Send message ──────────────────────────────────────────────────────────────

  async function sendMessage() {
    const body = inputText.trim()
    if (!body || sending) return
    setInputText('')
    setSending(true)

    // Optimistic
    const optimisticMsg = {
      id: `opt-${Date.now()}`,
      conversation_id: conversationId,
      sender_id: user?.id,
      sender_name: user?.username,
      body,
      sent_at: new Date().toISOString(),
      is_deleted: false,
      _optimistic: true,
    }
    addMessage(conversationId, optimisticMsg)
    offsetRef.current += 1

    requestAnimationFrame(() => {
      bottomAnchor.current?.scrollIntoView({ behavior: 'smooth' })
    })

    try {
      const r = await client.post(`/api/chat/conversations/${conversationId}/messages`, { body })
      // Replace optimistic with real
      useChatStore.setState(state => {
        const msgs = (state.messages[conversationId] || []).map(m =>
          m.id === optimisticMsg.id ? r.data : m
        )
        return { messages: { ...state.messages, [conversationId]: msgs } }
      })
      const existingConv = useChatStore.getState().conversations.find(c => c.id === conversationId)
      if (existingConv) {
        upsertConversation({ ...existingConv, last_message: r.data })
      }
    } catch {
      // Remove optimistic on failure, restore input
      useChatStore.setState(state => {
        const msgs = (state.messages[conversationId] || []).filter(m => m.id !== optimisticMsg.id)
        return { messages: { ...state.messages, [conversationId]: msgs } }
      })
      setInputText(body)
      offsetRef.current = Math.max(0, offsetRef.current - 1)
    }
    setSending(false)
  }

  // ── Leave group ───────────────────────────────────────────────────────────────

  async function leaveGroup() {
    try {
      await client.post(`/api/chat/conversations/${conversationId}/leave`)
      useChatStore.setState(state => ({
        conversations: state.conversations.filter(c => c.id !== conversationId),
        totalUnread: state.conversations
          .filter(c => c.id !== conversationId)
          .reduce((s, c) => s + (c.unread_count || 0), 0),
      }))
      navigate('/messages', { replace: true })
    } catch {}
    setShowLeave(false)
  }

  // ── Render messages with date separators ──────────────────────────────────────

  function renderMessages() {
    const items = []
    for (let i = 0; i < displayMessages.length; i++) {
      const msg = displayMessages[i]
      const prev = displayMessages[i - 1]

      if (!prev || !sameDay(prev.sent_at, msg.sent_at)) {
        items.push(
          <DateSeparator key={`date-${msg.id}`} label={formatDateLabel(msg.sent_at)} />
        )
      }

      const isOwn = msg.sender_id === user?.id
      // Show sender name on every incoming group message
      const showSender = isGroup && !isOwn

      items.push(
        <MessageBubble
          key={msg.id}
          msg={msg}
          isOwn={isOwn}
          showSender={showSender}
          isGroup={isGroup}
        />
      )
    }
    return items
  }

  const canLeave = isGroup && !conv?.is_system

  return (
    <div className="page" style={{ background: 'var(--bg)' }}>
      {/* Top bar */}
      <header className="top-bar">
        <button
          onClick={() => navigate('/messages')}
          style={{
            display: 'flex', alignItems: 'center', gap: 6,
            background: 'none', border: 'none', cursor: 'pointer',
            color: 'var(--text)', fontSize: 15, fontWeight: 600,
            padding: '0 4px', minHeight: 44, borderRadius: 8,
            flexShrink: 0,
          }}
        >
          <svg width="20" height="20" viewBox="0 0 20 20" fill="none">
            <path d="M12.5 15l-5-5 5-5" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
          Πίσω
        </button>

        <div style={{ flex: 1, textAlign: 'center', minWidth: 0 }}>
          <span className="top-bar__title" style={{
            overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
            display: 'block',
          }}>
            {title}
          </span>
          {isGroup && (
            <span style={{ fontSize: 11, color: 'var(--muted)', display: 'block', marginTop: -2 }}>
              {(conv?.participants || []).length} μέλη
            </span>
          )}
        </div>

        {canLeave ? (
          <button
            onClick={() => setShowLeave(true)}
            style={{
              background: 'none', border: 'none', cursor: 'pointer',
              color: 'var(--danger)', fontSize: 13, fontWeight: 700,
              padding: '0 4px', minHeight: 44, borderRadius: 8, flexShrink: 0,
            }}
          >
            Αποχώρηση
          </button>
        ) : (
          <div style={{ width: 72, flexShrink: 0 }} />
        )}
      </header>

      {/* Messages area */}
      <div
        ref={messagesEl}
        onScroll={handleScroll}
        style={{
          flex: 1, overflowY: 'auto', minHeight: 0,
          padding: '12px 16px',
          display: 'flex', flexDirection: 'column', gap: 6,
          overscrollBehavior: 'contain',
        }}
      >
        {loadingMore && (
          <div style={{ textAlign: 'center', padding: '8px 0', color: 'var(--muted)', fontSize: 13 }}>
            Φόρτωση παλαιότερων…
          </div>
        )}

        {initialLoad && (
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <span style={{ color: 'var(--muted)', fontSize: 14 }}>Φόρτωση…</span>
          </div>
        )}

        {!initialLoad && displayMessages.length === 0 && (
          <div style={{
            flex: 1, display: 'flex', flexDirection: 'column',
            alignItems: 'center', justifyContent: 'center', gap: 10,
          }}>
            <span style={{ fontSize: 40 }}>💬</span>
            <p style={{ fontSize: 15, color: 'var(--muted)', textAlign: 'center', lineHeight: 1.5 }}>
              Δεν υπάρχουν μηνύματα ακόμα.{'\n'}Πείτε γεια!
            </p>
          </div>
        )}

        {!initialLoad && renderMessages()}

        <div ref={bottomAnchor} />
      </div>

      {/* Send bar */}
      <div style={{
        background: 'var(--bg2)', borderTop: '1px solid var(--border)',
        padding: '10px 12px',
        display: 'flex', alignItems: 'flex-end', gap: 10,
        flexShrink: 0,
      }}>
        <AutoTextarea
          value={inputText}
          onChange={e => setInputText(e.target.value)}
          onSubmit={sendMessage}
          placeholder="Γράψτε μήνυμα…"
        />

        <button
          onClick={sendMessage}
          disabled={!inputText.trim() || sending}
          style={{
            width: 44, height: 44, borderRadius: '50%', border: 'none',
            background: inputText.trim() ? 'var(--accent)' : 'var(--bg3)',
            color: inputText.trim() ? 'var(--accent-fg)' : 'var(--muted)',
            cursor: inputText.trim() ? 'pointer' : 'not-allowed',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            flexShrink: 0, transition: 'background 0.15s, color 0.15s',
          }}
        >
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none">
            <path d="M22 2L11 13" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/>
            <path d="M22 2L15 22L11 13L2 9L22 2Z" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </button>
      </div>

      {showLeave && (
        <LeaveModal onConfirm={leaveGroup} onCancel={() => setShowLeave(false)} />
      )}
    </div>
  )
}
