"use client"

import { useEffect, useMemo, useRef, useState } from "react"
import { useMutation, useQuery } from "convex/react"
import type { Id } from "@/convex/_generated/dataModel"
import { api } from "@/convex/_generated/api"
import { useAuth } from "@/lib/auth-client"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader } from "@/components/ui/card"
import { Spinner } from "@/components/ui/spinner"
import { cn } from "@/lib/utils"
import { toast } from "sonner"
import { formatDistanceToNowStrict } from "date-fns"
import { ptBR } from "date-fns/locale"
import { MessageCircle, Send, WifiOff, X, User, Headphones } from "lucide-react"

const MAX_MESSAGE_LENGTH = 4000

function formatRelative(timestamp: number) {
  try {
    return formatDistanceToNowStrict(timestamp, { locale: ptBR, addSuffix: true })
  } catch {
    return new Date(timestamp).toLocaleString("pt-BR")
  }
}

function formatTime(timestamp: number) {
  return new Date(timestamp).toLocaleTimeString("pt-BR", {
    hour: "2-digit",
    minute: "2-digit",
  })
}

type TicketChatPanelProps = {
  ticketId: string
}

export function TicketChatPanel({ ticketId }: TicketChatPanelProps) {
  const { convexUserId } = useAuth()
  const viewerId = convexUserId ?? null
  const chat = useQuery(
    api.tickets.listChatMessages,
    viewerId ? { ticketId: ticketId as Id<"tickets">, viewerId: viewerId as Id<"users"> } : "skip"
  ) as
    | {
        ticketId: string
        chatEnabled: boolean
        status: string
        canPost: boolean
        reopenDeadline: number | null
        liveChat?: {
          hasMachine: boolean
          machineOnline: boolean
          machineHostname: string | null
          activeSession: {
            sessionId: Id<"liveChatSessions">
            agentId: Id<"users">
            agentName: string | null
            startedAt: number
            unreadByAgent: number
          } | null
        }
        messages: Array<{
          id: Id<"ticketChatMessages">
          body: string
          createdAt: number
          updatedAt: number
          authorId: string
          authorName: string | null
          authorEmail: string | null
          attachments: Array<{ storageId: Id<"_storage">; name: string; size: number | null; type: string | null }>
          readBy: Array<{ userId: string; readAt: number }>
        }>
      }
    | null
    | undefined

  const markChatRead = useMutation(api.tickets.markChatRead)
  const postChatMessage = useMutation(api.tickets.postChatMessage)
  const startLiveChat = useMutation(api.liveChat.startSession)
  const endLiveChat = useMutation(api.liveChat.endSession)

  const messagesEndRef = useRef<HTMLDivElement | null>(null)
  const inputRef = useRef<HTMLTextAreaElement | null>(null)
  const containerRef = useRef<HTMLDivElement | null>(null)
  const [draft, setDraft] = useState("")
  const [isVisible, setIsVisible] = useState(false)
  const [isSending, setIsSending] = useState(false)
  const [isStartingChat, setIsStartingChat] = useState(false)
  const [isEndingChat, setIsEndingChat] = useState(false)

  const messages = chat?.messages ?? []
  const canPost = Boolean(chat?.canPost && viewerId)
  const chatEnabled = Boolean(chat?.chatEnabled)
  const liveChat = chat?.liveChat
  const hasActiveSession = Boolean(liveChat?.activeSession)

  // Detectar visibilidade do componente na viewport
  useEffect(() => {
    const container = containerRef.current
    if (!container) return

    const observer = new IntersectionObserver(
      ([entry]) => {
        setIsVisible(entry.isIntersecting)
      },
      { threshold: 0.1 }
    )
    observer.observe(container)
    return () => observer.disconnect()
  }, [])

  // Detectar se a aba esta ativa
  useEffect(() => {
    const handleVisibilityChange = () => {
      if (document.visibilityState === "hidden") {
        setIsVisible(false)
      }
    }
    document.addEventListener("visibilitychange", handleVisibilityChange)
    return () => document.removeEventListener("visibilitychange", handleVisibilityChange)
  }, [])

  // Marcar como lido apenas quando o componente esta visivel E a aba esta ativa
  useEffect(() => {
    if (!viewerId || !chat || !Array.isArray(chat.messages) || chat.messages.length === 0) return
    // Verificar se o componente esta visivel e a aba esta ativa
    if (!isVisible || document.visibilityState === "hidden") return

    const unreadIds = chat.messages
      .filter((message) => {
        const alreadyRead = (message.readBy ?? []).some((entry) => entry.userId === viewerId)
        return !alreadyRead
      })
      .map((message) => message.id)
    if (unreadIds.length === 0) return
    void markChatRead({
      ticketId: ticketId as Id<"tickets">,
      actorId: viewerId as Id<"users">,
      messageIds: unreadIds,
    }).catch((error) => {
      console.error("Failed to mark chat messages as read", error)
    })
  }, [markChatRead, chat, ticketId, viewerId, isVisible])

  useEffect(() => {
    if (messagesEndRef.current) {
      messagesEndRef.current.scrollIntoView({ behavior: "smooth" })
    }
  }, [messages.length])

  const disabledReason = useMemo(() => {
    if (!chatEnabled) return "Chat desativado para este ticket"
    if (!canPost) return "Voce nao tem permissao para enviar mensagens"
    return null
  }, [canPost, chatEnabled])

  const handleStartLiveChat = async () => {
    if (!viewerId) return
    setIsStartingChat(true)
    toast.dismiss("live-chat")
    try {
      const result = await startLiveChat({
        ticketId: ticketId as Id<"tickets">,
        actorId: viewerId as Id<"users">,
      })
      if (result.isNew) {
        toast.success("Chat ao vivo iniciado", { id: "live-chat" })
      } else {
        toast.info("Já existe uma sessão de chat ativa", { id: "live-chat" })
      }
    } catch (error: unknown) {
      console.error("[LiveChat] Erro ao iniciar chat:", error)
      // Extrair mensagem amigável do erro do Convex
      let message = "Não foi possível iniciar o chat"
      if (error instanceof Error) {
        const errorMsg = error.message.toLowerCase()
        if (errorMsg.includes("offline")) {
          message = "Máquina offline. Aguarde a máquina ficar online para iniciar o chat."
        } else if (errorMsg.includes("não encontrad") || errorMsg.includes("not found")) {
          message = "Máquina não encontrada"
        }
      }
      toast.error(message, { id: "live-chat" })
    } finally {
      setIsStartingChat(false)
    }
  }

  const handleEndLiveChat = async () => {
    if (!viewerId || !chat?.liveChat?.activeSession) return
    setIsEndingChat(true)
    toast.dismiss("live-chat")
    try {
      await endLiveChat({
        sessionId: chat.liveChat.activeSession.sessionId,
        actorId: viewerId as Id<"users">,
      })
      toast.success("Chat ao vivo encerrado.", { id: "live-chat" })
    } catch (error: unknown) {
      const message = error instanceof Error ? error.message : "Não foi possível encerrar o chat"
      toast.error(message, { id: "live-chat" })
    } finally {
      setIsEndingChat(false)
    }
  }

  const handleSend = async () => {
    if (!viewerId || !canPost || draft.trim().length === 0) return
    if (draft.length > MAX_MESSAGE_LENGTH) {
      toast.error(`Mensagem muito longa (max. ${MAX_MESSAGE_LENGTH} caracteres).`)
      return
    }

    // Garantir que a sessão de chat ao vivo exista antes de enviar
    if (liveChat?.hasMachine && !hasActiveSession) {
      try {
        await startLiveChat({
          ticketId: ticketId as Id<"tickets">,
          actorId: viewerId as Id<"users">,
        })
      } catch (error: unknown) {
        const message = (() => {
          if (error instanceof Error) {
            const errorMsg = error.message.toLowerCase()
            if (errorMsg.includes("offline")) return "Máquina offline. Aguarde a máquina ficar online para iniciar o chat."
            if (errorMsg.includes("não encontrad") || errorMsg.includes("not found")) return "Máquina não encontrada"
          }
          return "Não foi possível iniciar o chat ao vivo."
        })()
        toast.error(message, { id: "live-chat" })
        return
      }
    }

    setIsSending(true)
    try {
      await postChatMessage({
        ticketId: ticketId as Id<"tickets">,
        actorId: viewerId as Id<"users">,
        body: draft.trim(),
      })
      setDraft("")
      inputRef.current?.focus()
    } catch (error) {
      console.error(error)
      toast.error("Não foi possível enviar a mensagem.")
    } finally {
      setIsSending(false)
    }
  }

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault()
      handleSend()
    }
  }

  if (!viewerId) {
    return null
  }

  return (
    <Card ref={containerRef} className="flex flex-col overflow-hidden border-slate-200">
      {/* Header */}
      <CardHeader className="flex flex-row items-center justify-between gap-2 border-b border-slate-100 bg-slate-50 px-4 pr-3 py-3">
        <div className="flex items-center gap-3">
          <div className="flex size-10 items-center justify-center rounded-full bg-black text-white">
            <MessageCircle className="size-5" />
          </div>
          <div>
            <p className="text-sm font-semibold text-slate-900">Chat do Atendimento</p>
            <div className="flex items-center gap-2">
              {liveChat?.hasMachine && (
                <>
                  {liveChat.machineOnline ? (
                    <span className="flex items-center gap-1 text-xs text-green-600">
                      <span className="size-1.5 rounded-full bg-green-500" />
                      {liveChat.machineHostname ?? "Maquina"} online
                    </span>
                  ) : (
                    <span className="flex items-center gap-1 text-xs text-slate-400">
                      <WifiOff className="size-3" />
                      {liveChat.machineHostname ?? "Maquina"} offline
                    </span>
                  )}
                </>
              )}
              {hasActiveSession && (
                <span className="flex items-center gap-1 rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-700">
                  Chat ativo
                </span>
              )}
            </div>
          </div>
        </div>
        <div className="flex items-center gap-2">
          {liveChat?.hasMachine && (
            <>
              {hasActiveSession ? (
                <Button
                  type="button"
                  variant="ghost"
                  size="sm"
                  onClick={handleEndLiveChat}
                  disabled={isEndingChat}
                  className="gap-1.5 border border-red-300 text-red-600 hover:border-red-400 hover:bg-red-50 hover:text-red-700"
                >
                  {isEndingChat ? <Spinner className="size-3" /> : <X className="size-3" />}
                  Encerrar
                </Button>
              ) : (
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  onClick={handleStartLiveChat}
                  disabled={isStartingChat || !liveChat.machineOnline}
                  className="gap-1.5"
                  title={!liveChat.machineOnline ? "A maquina precisa estar online para iniciar o chat" : undefined}
                >
                  {isStartingChat ? <Spinner className="size-3" /> : <MessageCircle className="size-3" />}
                  Iniciar Chat
                </Button>
              )}
            </>
          )}
        </div>
      </CardHeader>

      {/* Messages */}
      <CardContent className="flex-1 overflow-y-auto bg-slate-50/50 p-0">
        <div className="min-h-[300px] max-h-[400px] overflow-y-auto p-4">
          {chat === undefined ? (
            <div className="flex h-full min-h-[200px] items-center justify-center">
              <div className="flex flex-col items-center gap-2 text-slate-400">
                <Spinner className="size-6" />
                <p className="text-sm">Carregando mensagens...</p>
              </div>
            </div>
          ) : messages.length === 0 ? (
            <div className="flex h-full min-h-[200px] flex-col items-center justify-center text-center">
              <div className="flex size-12 items-center justify-center rounded-full bg-slate-100">
                <MessageCircle className="size-6 text-slate-400" />
              </div>
              <p className="mt-3 text-sm font-medium text-slate-600">Nenhuma mensagem ainda</p>
              <p className="mt-1 text-xs text-slate-400">
                {hasActiveSession ? "Envie uma mensagem para iniciar a conversa" : "Inicie um chat para conversar com o cliente"}
              </p>
            </div>
          ) : (
            <div className="space-y-4">
              {messages.map((message) => {
                const isOwn = String(message.authorId) === String(viewerId)
                return (
                  <div
                    key={message.id}
                    className={cn("flex gap-2", isOwn ? "flex-row-reverse" : "flex-row")}
                  >
                    {/* Avatar */}
                    <div
                      className={cn(
                        "flex size-8 shrink-0 items-center justify-center rounded-full",
                        isOwn ? "bg-black text-white" : "bg-slate-200 text-slate-600"
                      )}
                    >
                      {isOwn ? <Headphones className="size-4" /> : <User className="size-4" />}
                    </div>

                    {/* Bubble */}
                    <div
                      className={cn(
                        "max-w-[75%] rounded-2xl px-4 py-2",
                        isOwn
                          ? "rounded-br-md bg-black text-white"
                          : "rounded-bl-md bg-white text-slate-900 shadow-sm border border-slate-100"
                      )}
                    >
                      {!isOwn && (
                        <p className={cn("mb-1 text-xs font-medium", isOwn ? "text-white/70" : "text-slate-500")}>
                          {message.authorName ?? "Usuario"}
                        </p>
                      )}
                      <p className="whitespace-pre-wrap text-sm">{message.body}</p>
                      <p
                        className={cn(
                          "mt-1 text-right text-xs",
                          isOwn ? "text-white/60" : "text-slate-400"
                        )}
                      >
                        {formatTime(message.createdAt)}
                      </p>
                    </div>
                  </div>
                )
              })}
              <div ref={messagesEndRef} />
            </div>
          )}
        </div>
      </CardContent>

      {/* Input */}
      <div className="border-t border-slate-200 bg-white p-3">
        {!chatEnabled ? (
          <p className="text-center text-sm text-slate-400">Chat desativado para este ticket</p>
        ) : !canPost ? (
          <p className="text-center text-sm text-slate-400">Voce nao pode enviar mensagens neste chat</p>
        ) : (
          <div className="flex items-end gap-2">
            <textarea
              ref={inputRef}
              value={draft}
              onChange={(e) => setDraft(e.target.value)}
              onKeyDown={handleKeyDown}
              placeholder="Digite sua mensagem..."
              className="max-h-24 min-h-[40px] flex-1 resize-none rounded-lg border border-slate-200 px-3 py-2 text-sm focus:border-black focus:outline-none focus:ring-1 focus:ring-black"
              rows={1}
              disabled={isSending}
            />
            <Button
              type="button"
              onClick={handleSend}
              disabled={!draft.trim() || isSending}
              className="flex size-10 items-center justify-center rounded-lg bg-black text-white hover:bg-black/90"
            >
              {isSending ? (
                <Spinner className="size-4" />
              ) : (
                <Send className="size-4" />
              )}
            </Button>
          </div>
        )}
      </div>
    </Card>
  )
}
