import React from 'react'

export default function ConversationList({ conversations, loading, activeId, currentUserId, onlineUserIds = [], typingByConversation = {}, onSelect }) {
  return (
    <div className="flex flex-1 flex-col overflow-hidden">
      <div className="flex items-center justify-between border-b border-white/[0.06] px-4 py-3">
        <div>
          <p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-white/35">Conversations</p>
          <p className="mt-1 text-xs text-white/35">Recent threads and group rooms</p>
        </div>
        <span className="rounded-full border border-white/[0.08] bg-white/[0.04] px-2.5 py-1 text-[11px] text-white/45">
          {conversations.length}
        </span>
      </div>

      <ul className="nova-scrollbar-message flex-1 space-y-2 overflow-y-auto p-3 pr-2">
        {loading ? (
          <li className="rounded-2xl border border-white/[0.06] bg-white/[0.025] px-4 py-8 text-center text-sm text-white/40">Loading conversations…</li>
        ) : null}

        {!loading && conversations.length === 0 ? (
          <li className="rounded-2xl border border-white/[0.06] bg-white/[0.025] px-4 py-8 text-center text-sm text-white/40">No conversations yet.</li>
        ) : null}

        {conversations.map((conversation) => (
          <ConversationRow
            key={conversation.id}
            conv={conversation}
            isActive={conversation.id === activeId}
            currentUserId={currentUserId}
            onlineUserIds={onlineUserIds}
            typingUsers={typingByConversation[conversation.id] ?? []}
            onClick={() => onSelect(conversation.id)}
          />
        ))}
      </ul>
    </div>
  )
}

function ConversationRow({ conv, isActive, currentUserId, onlineUserIds, typingUsers, onClick }) {
  const label = convLabel(conv, currentUserId)
  const lastMsg = Array.isArray(conv.latest_message) ? conv.latest_message[0] : conv.latest_message
  const preview = typingUsers.length > 0
    ? buildTypingPreview(typingUsers)
    : lastMsg?.body ? truncate(lastMsg.body, 88) : 'No messages yet'
  const unread = conv.unread_count ?? 0
  const myParticipant = conv.all_participants?.find((participant) => participant.user_id === currentUserId)
  const otherParticipant = conv.all_participants?.find((participant) => participant.user_id !== currentUserId)
  const isArchived = myParticipant?.is_archived ?? false
  const isPinned = myParticipant?.is_pinned ?? false
  const activeMembers = conv.all_participants?.filter((participant) => !participant.left_at).length ?? 0
  const onlineMembers = conv.type === 'group'
    ? conv.all_participants?.filter((participant) => participant.user_id !== currentUserId && onlineUserIds.includes(Number(participant.user_id)) && !participant.left_at).length ?? 0
    : 0
  const isDirectOnline = conv.type === 'direct' && otherParticipant ? onlineUserIds.includes(Number(otherParticipant.user_id)) : false
  const typeLabel = conv.type === 'group'
    ? (onlineMembers > 0 ? `${onlineMembers} online` : `${activeMembers} members`)
    : (isDirectOnline ? 'Online now' : 'Direct message')
  const senderLabel = lastMsg?.sender?.username ? `@${lastMsg.sender.username}` : null
  const initials = label
    .split(/\s+/)
    .filter(Boolean)
    .slice(0, 2)
    .map((part) => part.charAt(0).toUpperCase())
    .join('') || 'M'

  return (
    <li>
      <button
        onClick={onClick}
        className={`w-full rounded-[24px] border px-4 py-4 text-left transition ${isActive ? 'border-sky-400/28 bg-sky-500/[0.12] shadow-[0_0_0_1px_rgba(56,189,248,0.08)]' : 'border-white/[0.06] bg-white/[0.03] hover:border-white/[0.1] hover:bg-white/[0.05]'} ${isArchived ? 'opacity-65' : ''}`}
      >
        <div className="flex gap-3">
          <div className="relative shrink-0">
            <div className={`flex h-12 w-12 items-center justify-center rounded-2xl text-sm font-semibold text-white shadow-[0_10px_25px_rgba(0,0,0,0.18)] ${conv.type === 'group' ? 'bg-gradient-to-br from-fuchsia-500 to-violet-600' : 'bg-gradient-to-br from-sky-500 to-cyan-500'}`}>
              {initials}
            </div>
            {isDirectOnline ? <span className="absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 rounded-full border-2 border-[#0a101a] bg-emerald-300 shadow-[0_0_0_6px_rgba(16,185,129,0.08)]" /> : null}
          </div>

          <div className="min-w-0 flex-1">
            <div className="flex items-start justify-between gap-3">
              <div className="min-w-0">
                <div className="flex items-center gap-2">
                  <span className={`truncate text-sm font-semibold ${isActive ? 'text-sky-100' : 'text-white/90'}`}>
                    {label}
                  </span>
                  {isPinned ? <span className="rounded-full border border-amber-400/20 bg-amber-500/10 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.16em] text-amber-200">Pinned</span> : null}
                  {isArchived ? <span className="rounded-full border border-white/[0.08] bg-white/[0.04] px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.16em] text-white/45">Archived</span> : null}
                </div>
                <p className="mt-1 text-[11px] uppercase tracking-[0.18em] text-white/30">{typeLabel}</p>
              </div>

              <div className="flex shrink-0 flex-col items-end gap-2">
                {conv.last_message_at ? <span className="text-[11px] text-white/30">{relativeTime(conv.last_message_at)}</span> : null}
                {unread > 0 ? (
                  <span className="inline-flex min-w-[1.55rem] items-center justify-center rounded-full border border-sky-400/20 bg-sky-500/14 px-1.5 py-0.5 text-[11px] font-semibold text-sky-100">
                    {unread > 99 ? '99+' : unread}
                  </span>
                ) : null}
              </div>
            </div>

            <div className="mt-3 rounded-2xl border border-white/[0.04] bg-black/10 px-3 py-2.5">
              {typingUsers.length === 0 && senderLabel ? <p className="text-[11px] text-white/35">{senderLabel}</p> : null}
              <p data-testid={`conversation-preview-${conv.id}`} className={`mt-1 flex items-center gap-2 truncate text-sm ${typingUsers.length > 0 ? 'text-emerald-200' : 'text-white/62'}`}>
                {typingUsers.length > 0 ? <SidebarTypingIcon /> : null}
                <span className="truncate">{preview}</span>
              </p>
            </div>
          </div>
        </div>
      </button>
    </li>
  )
}

function convLabel(conv, currentUserId) {
  if (conv.type === 'group') return conv.title ?? 'Group'
  const other = conv.all_participants?.find((participant) => participant.user_id !== currentUserId)
  return other?.user?.username ?? 'Direct message'
}

function truncate(str, max) {
  if (!str) return ''
  return str.length > max ? `${str.slice(0, max)}…` : str
}

function buildTypingPreview(users) {
  const names = users.map((user) => `@${user.username}`)
  if (names.length === 1) return `${names[0]} is typing...`
  if (names.length === 2) return `${names[0]} and ${names[1]} are typing...`
  return `${names[0]}, ${names[1]} and ${names.length - 2} others are typing...`
}

function SidebarTypingIcon() {
  return (
    <span className="inline-flex shrink-0 items-center gap-1">
      <span className="h-1.5 w-1.5 rounded-full bg-emerald-300 animate-[pulse_1s_ease-in-out_infinite]" />
      <span className="h-1.5 w-1.5 rounded-full bg-emerald-300/80 animate-[pulse_1s_ease-in-out_150ms_infinite]" />
      <span className="h-1.5 w-1.5 rounded-full bg-emerald-300/60 animate-[pulse_1s_ease-in-out_300ms_infinite]" />
    </span>
  )
}

function relativeTime(iso) {
  if (!iso) return 'No activity'
  const diff = (Date.now() - new Date(iso).getTime()) / 1000
  if (diff < 60) return 'Now'
  if (diff < 3600) return `${Math.floor(diff / 60)}m`
  if (diff < 86400) return `${Math.floor(diff / 3600)}h`
  return `${Math.floor(diff / 86400)}d`
}
