'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import Link from 'next/link';
import { ArrowLeft, Loader2, MessageCircle, Send, X } from 'lucide-react';
import { AvatarWithPresence } from '@/components/family/avatar-with-presence';
import { useFamilyOverlay } from '@/components/family/family-overlay-provider';
import { useAuth } from '@/components/id/auth-provider';
import { useToast } from '@/components/id/toast-provider';
import { useRealtime } from '@/components/notifications/realtime-provider';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { useSelectedFamily } from '@/hooks/use-primary-family';
import { FamilyGroupSelector } from '@/components/family/family-group-selector';
import {
  ChatMessage,
  ChatRoom,
  fetchChatMessages,
  fetchChatRooms,
  getApiErrorMessage,
  markChatRoomRead,
  sendChatMessage
} from '@/lib/api';
import { findOrCreateMemberChat, roomDisplayLabel } from '@/lib/family-chat';
import { cn } from '@/lib/utils';

function formatMessageTime(value: string) {
  return new Intl.DateTimeFormat('ru-RU', { hour: '2-digit', minute: '2-digit' }).format(new Date(value));
}

export function MiniFamilyChat() {
  const { user, token, isPinLocked } = useAuth();
  const { showToast } = useToast();
  const { subscribe } = useRealtime();
  const {
    group,
    groupSummaries,
    hasFamily,
    selectedGroupId,
    setSelectedGroupId,
    presenceByUserId
  } = useSelectedFamily(Boolean(user && token && !isPinLocked));
  const {
    miniChatOpen,
    openMiniChat,
    closeMiniChat,
    pendingRoomId,
    pendingMember,
    clearPending
  } = useFamilyOverlay();

  const [view, setView] = useState<'picker' | 'chat'>('picker');
  const [rooms, setRooms] = useState<ChatRoom[]>([]);
  const [activeRoom, setActiveRoom] = useState<ChatRoom | null>(null);
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  const [draft, setDraft] = useState('');
  const [loadingRooms, setLoadingRooms] = useState(false);
  const [loadingMessages, setLoadingMessages] = useState(false);
  const [sending, setSending] = useState(false);
  const [openingMemberId, setOpeningMemberId] = useState<string | null>(null);
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const previousGroupIdRef = useRef<string | null>(null);

  const loadRooms = useCallback(async () => {
    if (!group || !token) return;
    setLoadingRooms(true);
    try {
      const response = await fetchChatRooms(group.id, token);
      setRooms(response.rooms ?? []);
    } catch (error) {
      showToast(getApiErrorMessage(error, 'Не удалось загрузить чаты') ?? 'Ошибка');
    } finally {
      setLoadingRooms(false);
    }
  }, [group, showToast, token]);

  const openRoom = useCallback(
    async (room: ChatRoom) => {
      setActiveRoom(room);
      setView('chat');
      setLoadingMessages(true);
      try {
        const response = await fetchChatMessages(room.id, token);
        setMessages(response.messages ?? []);
      } catch (error) {
        showToast(getApiErrorMessage(error, 'Не удалось загрузить сообщения') ?? 'Ошибка');
      } finally {
        setLoadingMessages(false);
      }
    },
    [showToast, token]
  );

  const openMemberChat = useCallback(
    async (memberUserId: string, memberName: string) => {
      if (!group || !token || !user) return;
      setOpeningMemberId(memberUserId);
      try {
        const room = await findOrCreateMemberChat(group.id, memberUserId, memberName, user.id, token);
        await loadRooms();
        await openRoom(room);
      } catch (error) {
        showToast(getApiErrorMessage(error, 'Не удалось открыть чат') ?? 'Ошибка');
      } finally {
        setOpeningMemberId(null);
      }
    },
    [group, loadRooms, openRoom, showToast, token, user]
  );

  useEffect(() => {
    if (!miniChatOpen || !hasFamily) return;
    void loadRooms();
  }, [group?.id, hasFamily, loadRooms, miniChatOpen]);

  useEffect(() => {
    if (!group?.id) return;
    if (previousGroupIdRef.current && previousGroupIdRef.current !== group.id && miniChatOpen) {
      setView('picker');
      setActiveRoom(null);
      setMessages([]);
      setDraft('');
    }
    previousGroupIdRef.current = group.id;
  }, [group?.id, miniChatOpen]);

  useEffect(() => {
    if (!miniChatOpen) {
      setView('picker');
      setActiveRoom(null);
      setMessages([]);
      setDraft('');
      clearPending();
      return;
    }

    if (pendingRoomId && rooms.length) {
      const room = rooms.find((item) => item.id === pendingRoomId);
      if (room) {
        void openRoom(room);
        clearPending();
      }
    } else if (pendingMember && user) {
      void openMemberChat(pendingMember.userId, pendingMember.name);
      clearPending();
    }
  }, [clearPending, miniChatOpen, openMemberChat, openRoom, pendingMember, pendingRoomId, rooms, user]);

  useEffect(() => {
    if (!activeRoom) return;
    return subscribe((event) => {
      const payload = event.payload;
      if (payload?.roomId && payload.roomId !== activeRoom.id) return;
      if (event.type === 'chat_message' && payload?.message) {
        const message = payload.message as ChatMessage;
        setMessages((current) => {
          if (current.some((item) => item.id === message.id)) return current;
          return [...current, message];
        });
      }
      if (event.type === 'chat_message_updated' || event.type === 'chat_message_deleted') {
        const updated = payload?.message;
        if (updated) {
          setMessages((current) => current.map((item) => (item.id === updated.id ? updated : item)));
        }
      }
    });
  }, [activeRoom, subscribe]);

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  useEffect(() => {
    if (!activeRoom || !token || !messages.length) return;
    const last = messages[messages.length - 1];
    const timer = window.setTimeout(() => {
      void markChatRoomRead(activeRoom.id, last.id, token).catch(() => {});
    }, 400);
    return () => window.clearTimeout(timer);
  }, [activeRoom, messages, token]);

  async function handleSend() {
    if (!token || !activeRoom || !draft.trim()) return;
    setSending(true);
    try {
      const message = await sendChatMessage(activeRoom.id, { type: 'TEXT', content: draft.trim() }, token);
      setMessages((current) => [...current, message]);
      setDraft('');
      void loadRooms();
    } catch (error) {
      showToast(getApiErrorMessage(error, 'Не удалось отправить сообщение') ?? 'Ошибка');
    } finally {
      setSending(false);
    }
  }

  const otherMembers = useMemo(
    () => (group?.members ?? []).filter((member) => member.userId !== user?.id),
    [group?.members, user?.id]
  );

  if (!user || !token || isPinLocked) return null;

  return (
    <>
      <button
        type="button"
        onClick={() => (miniChatOpen ? closeMiniChat() : openMiniChat())}
        className={cn(
          'fixed bottom-5 right-5 z-50 flex h-12 w-12 items-center justify-center rounded-full bg-[#3390ec] text-white shadow-lg transition hover:bg-[#2b7fd4] lg:bottom-6 lg:right-6',
          miniChatOpen && 'scale-95'
        )}
        aria-label={miniChatOpen ? 'Закрыть чат семьи' : 'Открыть чат семьи'}
      >
        {miniChatOpen ? <X className="h-5 w-5" /> : <MessageCircle className="h-5 w-5" />}
      </button>

      {miniChatOpen ? (
        <div className="fixed bottom-20 right-5 z-50 flex w-[min(92vw,380px)] flex-col overflow-hidden rounded-[24px] border border-[#eceef4] bg-white shadow-2xl lg:bottom-[5.5rem] lg:right-6">
          <div className="flex items-center gap-2 border-b border-[#eceef4] px-4 py-3">
            {view === 'chat' ? (
              <Button type="button" variant="ghost" size="icon" className="h-8 w-8 shrink-0" onClick={() => setView('picker')}>
                <ArrowLeft className="h-4 w-4" />
              </Button>
            ) : null}
            <div className="min-w-0 flex-1">
              <p className="truncate text-sm font-semibold">
                {view === 'chat' && activeRoom && user ? roomDisplayLabel(activeRoom, user.id) : 'Чат семьи'}
              </p>
              {hasFamily ? (
                <FamilyGroupSelector
                  groups={groupSummaries}
                  selectedGroupId={selectedGroupId}
                  onSelect={setSelectedGroupId}
                  href={`/family/${group!.id}`}
                  nameClassName="text-xs text-[#667085]"
                />
              ) : (
                <p className="text-xs text-[#667085]">Семья не создана</p>
              )}
            </div>
            <Button type="button" variant="ghost" size="icon" className="h-8 w-8 shrink-0" onClick={closeMiniChat}>
              <X className="h-4 w-4" />
            </Button>
          </div>

          {!hasFamily ? (
            <div className="space-y-3 p-5 text-sm text-[#667085]">
              <p>Создайте семейную группу, чтобы общаться с близкими из любого раздела.</p>
              <Link href="/family" className="inline-flex text-[#3390ec] hover:underline" onClick={closeMiniChat}>
                Перейти к созданию семьи
              </Link>
            </div>
          ) : view === 'picker' ? (
            <div className="max-h-[min(60vh,460px)] overflow-y-auto p-3">
              <section className="mb-4">
                <p className="mb-2 px-1 text-xs font-semibold uppercase tracking-wide text-[#667085]">Чаты</p>
                {loadingRooms ? (
                  <div className="flex items-center gap-2 px-2 py-3 text-sm text-[#667085]">
                    <Loader2 className="h-4 w-4 animate-spin" />
                    Загрузка...
                  </div>
                ) : rooms.length ? (
                  <div className="space-y-1">
                    {rooms.map((room) => (
                      <button
                        key={room.id}
                        type="button"
                        className="flex w-full items-center gap-3 rounded-xl px-2 py-2 text-left transition hover:bg-[#f4f5f8]"
                        onClick={() => void openRoom(room)}
                      >
                        <div className="flex h-9 w-9 items-center justify-center rounded-full bg-[#eef4ff] text-xs font-semibold text-[#3390ec]">
                          {room.type === 'GENERAL' ? 'В' : room.name.slice(0, 2).toUpperCase()}
                        </div>
                        <div className="min-w-0 flex-1">
                          <p className="truncate text-sm font-medium">{user ? roomDisplayLabel(room, user.id) : room.name}</p>
                          <p className="truncate text-xs text-[#667085]">
                            {room.lastMessage?.isDeleted
                              ? 'Сообщение удалено'
                              : room.lastMessage?.content ?? 'Нет сообщений'}
                          </p>
                        </div>
                      </button>
                    ))}
                  </div>
                ) : (
                  <p className="px-2 py-2 text-sm text-[#667085]">Чаты пока не созданы</p>
                )}
              </section>

              <section>
                <p className="mb-2 px-1 text-xs font-semibold uppercase tracking-wide text-[#667085]">Написать участнику</p>
                <div className="space-y-1">
                  {otherMembers.map((member) => {
                    const presence = presenceByUserId.get(member.userId);
                    return (
                      <button
                        key={member.id}
                        type="button"
                        disabled={openingMemberId === member.userId}
                        className="flex w-full items-center gap-3 rounded-xl px-2 py-2 text-left transition hover:bg-[#f4f5f8] disabled:opacity-60"
                        onClick={() => void openMemberChat(member.userId, member.displayName)}
                      >
                        <AvatarWithPresence
                          userId={member.userId}
                          displayName={member.displayName}
                          hasAvatar={member.hasAvatar}
                          token={token}
                          isVerified={member.isVerified}
                          verificationIcon={member.verificationIcon}
                          online={presence?.online}
                          className="h-9 w-9"
                        />
                        <div className="min-w-0 flex-1">
                          <p className="truncate text-sm font-medium">{member.displayName}</p>
                          <p className={cn('text-xs', presence?.online ? 'text-emerald-600' : 'text-[#667085]')}>
                            {presence?.online ? 'В сети' : 'Личный чат'}
                          </p>
                        </div>
                        {openingMemberId === member.userId ? <Loader2 className="h-4 w-4 animate-spin text-[#667085]" /> : null}
                      </button>
                    );
                  })}
                  {!otherMembers.length ? (
                    <p className="px-2 py-2 text-sm text-[#667085]">Пригласите участников в семью</p>
                  ) : null}
                </div>
              </section>

              <Link
                href={`/family/${group!.id}`}
                className="mt-3 block rounded-xl bg-[#f4f5f8] px-3 py-2 text-center text-xs font-medium text-[#3390ec] hover:bg-[#eceef4]"
                onClick={closeMiniChat}
              >
                Открыть семью полностью
              </Link>
            </div>
          ) : (
            <>
              <div className="flex-1 space-y-2 overflow-y-auto bg-[#eef1f6] p-3" style={{ maxHeight: 'min(50vh,380px)' }}>
                {loadingMessages ? (
                  <div className="flex items-center justify-center gap-2 py-8 text-sm text-[#667085]">
                    <Loader2 className="h-4 w-4 animate-spin" />
                    Загрузка...
                  </div>
                ) : messages.length ? (
                  messages.map((message) => {
                    const mine = message.senderId === user.id;
                    return (
                      <div key={message.id} className={cn('flex', mine ? 'justify-end' : 'justify-start')}>
                        <div
                          className={cn(
                            'max-w-[85%] rounded-[16px] px-3 py-2 text-sm shadow-sm',
                            mine ? 'bg-[#effdde]' : 'bg-white',
                            message.isDeleted && 'italic text-[#667085]'
                          )}
                        >
                          {!mine ? <p className="mb-0.5 text-[11px] font-semibold text-[#3390ec]">{message.senderName}</p> : null}
                          <p>{message.isDeleted ? 'Сообщение удалено' : message.content ?? '…'}</p>
                          <p className="mt-1 text-[10px] text-[#a8adbc]">{formatMessageTime(message.createdAt)}</p>
                        </div>
                      </div>
                    );
                  })
                ) : (
                  <p className="py-8 text-center text-sm text-[#667085]">Сообщений пока нет</p>
                )}
                <div ref={messagesEndRef} />
              </div>
              <div className="flex items-center gap-2 border-t border-[#eceef4] p-3">
                <Input
                  value={draft}
                  onChange={(event) => setDraft(event.target.value)}
                  placeholder="Сообщение"
                  className="rounded-xl"
                  onKeyDown={(event) => {
                    if (event.key === 'Enter' && !event.shiftKey) {
                      event.preventDefault();
                      void handleSend();
                    }
                  }}
                />
                <Button className="h-10 w-10 shrink-0 rounded-full p-0" disabled={sending || !draft.trim()} onClick={() => void handleSend()}>
                  {sending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Send className="h-4 w-4" />}
                </Button>
              </div>
            </>
          )}
        </div>
      ) : null}
    </>
  );
}
