'use client'

import { useState, useEffect, useRef, useCallback, useMemo } from 'react'
import { useChatContext } from '@/app/contexts/ChatContext'
import { useMessages } from './hooks'
import { useSocket } from './hooks/useSocket'
import { useUserPresence } from './hooks/useUserPresence'
import { useConversations } from './hooks'
import { supabase } from '@/lib/supabase'
import { Avatar } from './components'
import EmptyState from './components/EmptyState'
import { MessageSkeleton } from './components/MessageSkeleton'
import {
  ArrowLeft,
  X,
  Phone,
  Video,
  MoreVertical,
  Paperclip,
  Send,
  Check,
  CheckCheck,
} from 'lucide-react'
import type { ChatConversation, SupabaseUser } from './types/supabase'
import { useTranslations } from 'next-intl'

export default function ChatPage() {
  const { selectedChat, setSelectedChat, setShowMobileChat } = useChatContext()
  const { conversations } = useConversations()
  const { messages, loading, error, sending, sendMessage } =
    useMessages(selectedChat)
  const { supabaseUserId, presenceByUserId } = useUserPresence()
  const [messageText, setMessageText] = useState('')
  const [conversation, setConversation] = useState<ChatConversation | null>(
    null
  )
  const [participants, setParticipants] = useState<SupabaseUser[]>([])
  const [typingUsers, setTypingUsers] = useState<Set<string>>(new Set())
  const messagesEndRef = useRef<HTMLDivElement>(null)
  const textareaRef = useRef<HTMLTextAreaElement>(null)
  const isInitialLoadRef = useRef(false)
  const previousSelectedChatRef = useRef<string | null>(null)
  const firstUnreadMessageIdRef = useRef<string | null>(null)
  const t = useTranslations('chat.page')

  // Verrou: si l'utilisateur courant a envoyé tous les messages (aucune réponse du destinataire),
  // on désactive temporairement l'envoi jusqu'à ce qu'il reçoive une réponse
  const inputLocked = useMemo(() => {
    if (!supabaseUserId || messages.length === 0) return false
    const hasOnlyMyMessages = messages.every(
      (m) => m.sender_id === supabaseUserId
    )
    return hasOnlyMyMessages
  }, [messages, supabaseUserId])

  const handleBackToList = () => {
    setSelectedChat(null)
    setShowMobileChat(false)
  }

  // Callbacks pour Socket.IO
  const handleNewMessage = useCallback((message: any) => {
    // Les messages sont déjà gérés par useMessages via Socket.IO
  }, [])

  const handleUserTyping = useCallback(
    (data: { userId: string; isTyping: boolean; conversationId: string }) => {
      // Ignorer si le typing n'est pas dans la conversation actuelle
      if (data.conversationId !== selectedChat) return
      
      setTypingUsers((prev) => {
        const newSet = new Set(prev)
        if (data.isTyping) {
          newSet.add(data.userId)
        } else {
          newSet.delete(data.userId)
        }
        return newSet
      })
    },
    [selectedChat]
  )

  // Hook Socket.IO
  const { handleTyping } = useSocket({
    conversationId: selectedChat || null,
    onNewMessage: handleNewMessage,
    onUserTyping: handleUserTyping,
  })

  // Charger les détails de la conversation depuis Supabase
  useEffect(() => {
    const loadConversationDetails = async () => {
      if (!selectedChat) {
        setConversation(null)
        setParticipants([])
        return
      }

      // Trouver la conversation dans la liste chargée
      const conv = conversations.find((c) => c.id === selectedChat)
      if (conv) {
        setConversation(conv)

        // Charger les participants depuis Supabase
        const { data: participantsData } = await supabase
          .from('conversation_participants')
          .select('user_id, users (*)')
          .eq('conversation_id', selectedChat)

        if (participantsData) {
          const users = participantsData
            .map((p: any) => p.users as unknown as SupabaseUser)
            .filter((u: SupabaseUser | null) => u !== null) as SupabaseUser[]
          setParticipants(users)

          // Si conversation directe et sans nom, utiliser le nom de l'autre participant
          const isGroup = conv.type === 'group'
          const hasName = !!(conv.name && conv.name.trim())
          if (!isGroup && !hasName) {
            const other = users.find((u) => u.id !== supabaseUserId)
            if (other?.name) {
              setConversation((prev) => (prev ? { ...prev, name: other.name } : prev))
            }
          }
        }
      } else {
        // Si pas dans la liste, charger directement depuis Supabase
        const { data: convData } = await supabase
          .from('conversations')
          .select('*')
          .eq('id', selectedChat)
          .single()

        if (convData) {
          // Charger les participants
          const { data: participantsData } = await supabase
            .from('conversation_participants')
            .select('user_id, users (*)')
            .eq('conversation_id', selectedChat)

          if (participantsData) {
            const users = participantsData
              .map((p: any) => p.users as unknown as SupabaseUser)
              .filter((u: SupabaseUser | null) => u !== null) as SupabaseUser[]
            setParticipants(users)

            // Convertir en ChatConversation
            const participantIds = participantsData.map((p) => p.user_id)
            // Déterminer le nom si direct et manquant
            let resolvedName = convData.name as string | null | undefined
            if (convData.type === 'direct' && (!resolvedName || !resolvedName.trim())) {
              const other = users.find((u) => u.id !== supabaseUserId)
              resolvedName = other?.name || null
            }
            setConversation({
              ...convData,
              name: resolvedName || convData.name || null,
              isGroup: convData.type === 'group',
              participants: participantIds,
              unreadCount: 0,
            })
          }
        }
      }
    }

    loadConversationDetails()
  }, [selectedChat, conversations])

  // Détecter l'ouverture d'une nouvelle conversation
  useEffect(() => {
    if (selectedChat && selectedChat !== previousSelectedChatRef.current) {
      // Nouvelle conversation sélectionnée
      isInitialLoadRef.current = true
      firstUnreadMessageIdRef.current = null
      previousSelectedChatRef.current = selectedChat
    }
  }, [selectedChat])

  // Capturer le premier message non lu dès qu'il est disponible
  useEffect(() => {
    if (isInitialLoadRef.current && messages.length > 0 && !loading) {
      const firstUnread = messages.find(
        (msg) => !msg.isRead && msg.sender_id !== supabaseUserId
      )
      if (firstUnread) {
        firstUnreadMessageIdRef.current = firstUnread.id
      }
    }
  }, [messages, loading, supabaseUserId])

  // Auto-scroll vers le premier message non lu ou le dernier message
  useEffect(() => {
    if (messages.length === 0 || loading) {
      return
    }

    // Scroll lors du chargement initial d'une conversation
    if (isInitialLoadRef.current) {
      // Utiliser un délai plus long pour s'assurer que le DOM est complètement rendu
      const scrollTimeout = setTimeout(() => {
        const unreadId = firstUnreadMessageIdRef.current

        if (unreadId) {
          // Chercher l'élément dans le DOM par data attribute
          const element = document.querySelector(
            `[data-message-id="${unreadId}"]`
          )

          if (element) {
            // Scroller vers le premier message non lu
            element.scrollIntoView({ behavior: 'auto', block: 'center' })
            isInitialLoadRef.current = false
            firstUnreadMessageIdRef.current = null
            return
          }
        }

        // Si aucun message non lu ou élément non trouvé, scroller vers le dernier message
        messagesEndRef.current?.scrollIntoView({ behavior: 'auto' })
        isInitialLoadRef.current = false
        firstUnreadMessageIdRef.current = null
      }, 300)

      return () => clearTimeout(scrollTimeout)
    } else {
      // Scroll smooth vers le bas pour les nouveaux messages en temps réel
      messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
    }
  }, [messages, loading])

  // Gestionnaire pour la touche Echap (PC uniquement)
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape' && selectedChat) {
        setSelectedChat(null)
      }
    }

    // Ajouter l'écouteur d'événement
    document.addEventListener('keydown', handleKeyDown)

    // Nettoyer l'écouteur d'événement
    return () => {
      document.removeEventListener('keydown', handleKeyDown)
    }
  }, [selectedChat, setSelectedChat])

  // Maintenir le focus sur la zone de saisie
  useEffect(() => {
    if (!selectedChat || !textareaRef.current || sending) {
      return
    }

    // Utiliser setTimeout pour s'assurer que le DOM est prêt
    const focusTimeout = setTimeout(() => {
      textareaRef.current?.focus()
    }, 100)

    return () => clearTimeout(focusTimeout)
  }, [selectedChat, sending])

  // Remettre le focus après l'envoi d'un message (quand le message est vide)
  useEffect(() => {
    if (selectedChat && !sending && messageText === '' && textareaRef.current) {
      // Petit délai pour s'assurer que le DOM est mis à jour
      const focusTimeout = setTimeout(() => {
        textareaRef.current?.focus()
      }, 50)

      return () => clearTimeout(focusTimeout)
    }
  }, [sending, messageText, selectedChat])

  const handleSendMessage = async () => {
    if (!messageText.trim() || sending || !supabaseUserId || inputLocked) return

    // Envoyer le message (sauvegarde Supabase + diffusion Socket.IO dans useMessages)
    const result = await sendMessage(messageText)
    const preview = messageText
    setMessageText('')

    // Arrêter le typing indicator
    handleTyping(supabaseUserId, false)

    // Notifier les autres participants (push) uniquement si l'envoi a réussi
    if (result?.success && result.message) {
      const notificationPayload = {
        conversationId: selectedChat,
        messagePreview: preview,
        conversationName: conversation?.name,
      }

      fetch('/api/push/notify-message', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify(notificationPayload),
      }).catch((error) => {
        console.error('Error triggering push notification:', error)
      })
    }

    // Remettre le textarea à sa hauteur minimale et remettre le focus
    if (textareaRef.current) {
      textareaRef.current.style.height = 'auto'
      textareaRef.current.style.height = '40px'
      // Remettre le focus après un court délai
      setTimeout(() => {
        textareaRef.current?.focus()
      }, 50)
    }
  }

  const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault()
      handleSendMessage()
    }
  }

  // Auto-resize du textarea
  const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    setMessageText(e.target.value)

    // Auto-resize
    const textarea = e.target
    textarea.style.height = 'auto'
    textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px'

    // Gérer les typing indicators avec UUID Supabase
    if (supabaseUserId && !inputLocked) {
      if (e.target.value.trim()) {
        handleTyping(supabaseUserId, true) // Commencer à taper
      } else {
        handleTyping(supabaseUserId, false) // Arrêter de taper
      }
    }
  }

  // Fonction pour tronquer le nom de conversation
  const truncateConversationName = (name: string): string => {
    // 16 caractères en mobile, 25 en desktop
    const maxLength =
      typeof window !== 'undefined' && window.innerWidth >= 1024 ? 25 : 16

    if (name.length <= maxLength) {
      return name
    }
    return name.substring(0, maxLength) + '...'
  }

  // Si aucune conversation n'est sélectionnée, afficher l'état vide
  if (!selectedChat) {
    return <EmptyState />
  }

  return (
    <>
      {/* Header de la conversation */}
      <div className="sticky top-0 z-10 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 p-4 lg:p-6 lg:relative lg:z-auto">
        <div className="flex items-center justify-between">
          {/* Partie gauche : Bouton retour + Avatar + Nom/Statut */}
          <div className="flex items-center space-x-3 lg:space-x-4 flex-1 min-w-0">
            {/* Bouton retour mobile */}
            <button
              onClick={handleBackToList}
              className="lg:hidden p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-xl transition-colors flex-shrink-0"
            >
              <ArrowLeft className="w-5 h-5" />
            </button>
            {conversation ? (
              <Avatar
                avatar={conversation.avatar || null}
                name={conversation.name || t('conversation')}
                size="md"
              />
            ) : (
              <div className="w-10 h-10 lg:w-12 lg:h-12 bg-teal-500 rounded-xl flex items-center justify-center text-white text-lg lg:text-xl flex-shrink-0">
                💬
              </div>
            )}
            <div className="flex-1 min-w-0">
              <h2 className="text-base lg:text-lg font-semibold text-gray-900 dark:text-white truncate">
                {conversation
                  ? truncateConversationName(
                      conversation.name || t('conversation')
                    )
                  : t('loading')}
              </h2>
              <p className="text-xs lg:text-sm text-gray-500 dark:text-gray-400 truncate flex items-center gap-1.5">
                {conversation?.isGroup ? (
                  `${participants.length} ${t('participants')}`
                ) : (
                  (() => {
                    const other = participants.find((p) => p.id !== supabaseUserId)
                    const liveStatus = other ? presenceByUserId[other.id] : undefined
                    const isOnline = (liveStatus || other?.status) === 'online'
                    return (
                      <>
                        <span
                          className={`w-2 h-2 rounded-full ${isOnline ? 'bg-green-500' : 'bg-slate-400'}`}
                        />
                        {isOnline ? t('online') : t('offline')}
                      </>
                    )
                  })()
                )}
              </p>
            </div>
          </div>

          {/* Partie droite : Bouton fermer + Boutons d'action */}
          <div className="flex items-center space-x-1 lg:space-x-2 flex-shrink-0">
            {/* Bouton fermer conversation (PC uniquement) */}
            <button
              onClick={() => setSelectedChat(null)}
              className="hidden lg:flex p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-xl transition-colors"
              title={t('closeConversation')}
            >
              <X className="w-5 h-5 text-gray-500 dark:text-gray-400" />
            </button>
            <button aria-disabled="true" className="p-2 lg:p-3 rounded-xl transition-colors cursor-not-allowed">
              <Phone className="w-4 h-4 lg:w-5 lg:h-5 text-gray-400 dark:text-gray-500" />
            </button>
            <button aria-disabled="true" className="p-2 lg:p-3 rounded-xl transition-colors cursor-not-allowed">
              <Video className="w-4 h-4 lg:w-5 lg:h-5 text-gray-400 dark:text-gray-500" />
            </button>
            <button aria-disabled="true" className="p-2 lg:p-3 rounded-xl transition-colors cursor-not-allowed">
              <MoreVertical className="w-4 h-4 lg:w-5 lg:h-5 text-gray-400 dark:text-gray-500" />
            </button>
          </div>
        </div>
      </div>

      {/* Messages */}
      <div className="flex-1 overflow-y-auto p-4 lg:p-6 pb-20 lg:pb-6 space-y-3 lg:space-y-4 bg-gray-50 dark:bg-gray-900">
        {/* État de chargement */}
        {loading && messages.length === 0 && <MessageSkeleton />}

        {/* État d'erreur */}
        {error && (
          <div className="flex items-center justify-center h-full">
            <div className="p-6 bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-300 rounded-xl text-center">
              <p>{error}</p>
            </div>
          </div>
        )}

        {/* Messages */}
        {!loading &&
          !error &&
          messages.map((message) => {
            const sender = participants.find((p) => p.id === message.sender_id)
            const isMe = message.sender_id === supabaseUserId

            return (
              <div
                key={message.id}
                data-message-id={message.id}
                className={`flex ${isMe ? 'justify-end' : 'justify-start'}`}
              >
                <div className="flex items-end space-x-2 max-w-xs sm:max-w-sm lg:max-w-md">
                  {!isMe && (
                    <Avatar
                      avatar={sender?.avatar_url || null}
                      name={sender?.name || t('conversation')}
                      size="sm"
                    />
                  )}
                  <div>
                    {!isMe && (
                      <p className="text-xs text-gray-500 dark:text-gray-400 mb-1 ml-1">
                        {sender?.name || t('conversation')}
                      </p>
                    )}
                    <div
                      className={`px-3 lg:px-4 py-2 lg:py-3 rounded-2xl ${
                        isMe
                          ? 'bg-teal-500 text-white'
                          : 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white border border-gray-200 dark:border-gray-600'
                      }`}
                      style={{ whiteSpace: 'pre-wrap' }}
                    >
                      <p className="text-sm">{message.text}</p>
                      <div className="flex items-center gap-1 mt-1">
                        <p
                          className={`text-xs ${
                            isMe
                              ? 'text-teal-100'
                              : 'text-gray-500 dark:text-gray-400'
                          }`}
                        >
                          {message.time}
                        </p>
                        {isMe && (
                          message.isReadByOthers ? (
                            <CheckCheck className="w-3.5 h-3.5 text-teal-100" />
                          ) : (
                            <Check className="w-3.5 h-3.5 text-teal-100" />
                          )
                        )}
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            )
          })}

        {/* Typing indicators */}
        {typingUsers.size > 0 && (
          <div className="flex justify-start">
            <div className="flex items-end space-x-2 max-w-xs sm:max-w-sm lg:max-w-md">
              <div className="w-8 h-8 bg-gray-300 rounded-full flex items-center justify-center">
                <div className="w-3 h-3 bg-gray-500 rounded-full animate-pulse"></div>
              </div>
              <div className="px-3 lg:px-4 py-2 lg:py-3 rounded-2xl bg-white dark:bg-gray-700 text-gray-900 dark:text-white border border-gray-200 dark:border-gray-600">
                <div className="flex items-center space-x-1">
                  <div className="flex space-x-1">
                    <div
                      className="w-2 h-2 bg-gray-400 rounded-full animate-bounce"
                      style={{ animationDelay: '0ms' }}
                    ></div>
                    <div
                      className="w-2 h-2 bg-gray-400 rounded-full animate-bounce"
                      style={{ animationDelay: '150ms' }}
                    ></div>
                    <div
                      className="w-2 h-2 bg-gray-400 rounded-full animate-bounce"
                      style={{ animationDelay: '300ms' }}
                    ></div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        )}

        {/* Référence pour l'auto-scroll */}
        <div ref={messagesEndRef} />
      </div>

      {/* Zone de saisie */}
      <div className="sticky bottom-0 z-10 bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-600 p-4 lg:p-6 lg:relative lg:z-auto">
        <div className="flex items-center space-x-2 lg:space-x-3">
          <button aria-disabled="true" className="p-2 lg:p-3 rounded-xl transition-colors cursor-not-allowed">
            <Paperclip className="w-4 h-4 lg:w-5 lg:h-5 text-gray-400 dark:text-gray-500" />
          </button>
          <div className="flex-1 relative">
            <textarea
              ref={textareaRef}
              placeholder={t('messagePlaceholder')}
              value={messageText}
              onChange={handleTextareaChange}
              onKeyDown={handleKeyDown}
              disabled={sending || inputLocked}
              rows={1}
              className="w-full px-3 lg:px-4 py-2 lg:py-3 border-0 rounded-xl bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-teal-500 text-base lg:text-lg disabled:opacity-50 resize-none overflow-hidden"
              style={{
                minHeight: '40px',
                maxHeight: '120px',
              }}
            />
          </div>
          <button
            onClick={handleSendMessage}
            disabled={!messageText.trim() || sending || inputLocked}
            className="p-2 lg:p-3 bg-teal-500 text-white rounded-xl hover:bg-teal-600 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
          >
            {sending ? (
              <div className="animate-spin rounded-full h-4 w-4 lg:h-5 lg:w-5 border-b-2 border-white"></div>
            ) : (
              <Send className="w-4 h-4 lg:w-5 lg:h-5" />
            )}
          </button>
        </div>
        {inputLocked && (
          <div className="mt-2 text-xs text-gray-500 dark:text-gray-400">
            {t('awaitingReplyHelper')}
          </div>
        )}
      </div>
    </>
  )
}
