'use client';

import { createContext, useContext, useState, useEffect, useRef, useCallback } from 'react';
import { useSession } from 'next-auth/react';
import { agentsService } from '@/services/agents.service';
import { usersService } from '@/services/users.service';
import { uploadService } from '@/services/upload.service';
import { notificationsApiService } from '@/services/notifications-api.service';
import { messagesService } from '@/services/messages.service';
import { socketService } from '@/services';

interface HeaderData {
  profileImage: string | null;
  profileName: string | null;
  profileTitle: string | null;
  avatarLoaded: boolean;
  setAvatarLoaded: (loaded: boolean) => void;
  notificationCount: number;
  messageCount: number;
}

const HeaderContext = createContext<HeaderData>({
  profileImage: null,
  profileName: null,
  profileTitle: null,
  avatarLoaded: false,
  setAvatarLoaded: () => {},
  notificationCount: 0,
  messageCount: 0,
});

export function useHeaderData() {
  return useContext(HeaderContext);
}

export function HeaderProvider({ children }: { children: React.ReactNode }) {
  const { data: session, status } = useSession();
  const [profileImage, setProfileImage] = useState<string | null>(null);
  const [profileName, setProfileName] = useState<string | null>(null);
  const [profileTitle, setProfileTitle] = useState<string | null>(null);
  const [avatarLoaded, setAvatarLoaded] = useState(false);
  const [notificationCount, setNotificationCount] = useState(0);
  const [messageCount, setMessageCount] = useState(0);
  const lastAvatarKeyRef = useRef<string | null>(null);
  const hasFetchedRef = useRef(false);

  const fetchProfileData = useCallback(async (forceRefresh = false) => {
    try {
      const role = (session?.user as any)?.role;
      let avatar: string | null = null;
      let name: string | null = null;
      let title: string | null = null;

      if (role === 'AGENT') {
        const profile = await agentsService.getMyProfile();
        avatar = profile.avatar;
        name = profile.firstName ? `${profile.firstName} ${profile.lastName || ''}`.trim() : null;
        title = profile.agentType?.name || 'Real Estate Agent';
      } else if (role === 'USER') {
        const profile = await usersService.getMyProfile();
        avatar = profile.avatar;
        name = profile.firstName ? `${profile.firstName} ${profile.lastName || ''}`.trim() : null;
        title = 'Member';
      }

      if (name) setProfileName(name);
      if (title) setProfileTitle(title);

      if (avatar && (avatar !== lastAvatarKeyRef.current || forceRefresh)) {
        lastAvatarKeyRef.current = avatar;
        setAvatarLoaded(false);
        try {
          const avatarUrl = await uploadService.getPresignedDownloadUrl(avatar);
          setProfileImage(avatarUrl);
        } catch {
          setProfileImage(avatar);
        }
      }
    } catch (err) {
      console.error('Failed to fetch profile data:', err);
    }
  }, [session]);

  // Fetch once on auth
  useEffect(() => {
    if (status === 'authenticated' && session?.user && !hasFetchedRef.current) {
      hasFetchedRef.current = true;
      fetchProfileData();
    }
    if (status === 'unauthenticated') {
      hasFetchedRef.current = false;
      setProfileImage(null);
      setProfileName(null);
      setProfileTitle(null);
      setAvatarLoaded(false);
      lastAvatarKeyRef.current = null;
    }
  }, [status, session, fetchProfileData]);

  // Listen for profile-updated events
  useEffect(() => {
    const handleProfileUpdate = () => {
      lastAvatarKeyRef.current = null;
      fetchProfileData(true);
    };
    window.addEventListener('profile-updated', handleProfileUpdate);
    return () => window.removeEventListener('profile-updated', handleProfileUpdate);
  }, [fetchProfileData]);

  // Notification count polling + real-time socket updates
  useEffect(() => {
    if (status !== 'authenticated') return;

    const fetchCount = async () => {
      try {
        const count = await notificationsApiService.getUnreadCount();
        setNotificationCount(count);
      } catch {
        // Silently fail
      }
    };

    const fetchMessageCount = async () => {
      try {
        const count = await messagesService.getUnreadCount();
        setMessageCount(count);
      } catch {
        // Silently fail
      }
    };

    const fetchBothCounts = () => { fetchCount(); fetchMessageCount(); };

    fetchCount();
    fetchMessageCount();
    const interval = setInterval(fetchCount, 30000);
    const messageInterval = setInterval(fetchMessageCount, 30000);
    const handleNotification = () => fetchCount();
    window.addEventListener('notification-received', handleNotification);

    // Instantly refresh both counts when messages are read
    // (dispatched by useMessaging when user views a conversation)
    window.addEventListener('messages-read', fetchBothCounts);

    // Listen to socket events for immediate notification count refresh
    const unsubConnectionReq = socketService.onConnectionRequest(() => fetchCount());
    const unsubConnectionRes = socketService.onConnectionResponse(() => fetchCount());
    const unsubNewMessage = socketService.onNewMessage(() => { fetchCount(); fetchMessageCount(); });

    // Listen to messages_read socket event (when other party reads, or when
    // mark_read response comes back) to keep counts synchronized
    const unsubMessagesRead = socketService.onMessagesRead(() => fetchBothCounts());

    return () => {
      clearInterval(interval);
      clearInterval(messageInterval);
      window.removeEventListener('notification-received', handleNotification);
      window.removeEventListener('messages-read', fetchBothCounts);
      unsubConnectionReq();
      unsubConnectionRes();
      unsubNewMessage();
      unsubMessagesRead();
    };
  }, [status]);

  return (
    <HeaderContext.Provider value={{ profileImage, profileName, profileTitle, avatarLoaded, setAvatarLoaded, notificationCount, messageCount }}>
      {children}
    </HeaderContext.Provider>
  );
}
