import { create } from 'zustand';
import { UserApi } from '../../users/infrastructure/userApi';
import { FriendApi } from '../infrastructure/friendApi';
import type { FriendWithId, FriendRequest, UserPresence } from '../../../core/domain/types';
import { getSocket } from '../../../core/infrastructure/socket';

interface FriendState {
  friends: FriendWithId[];
  friendRequests: FriendRequest[];
  isLoading: boolean;
  searchQuery: string;
  searchResults: UserPresence[];
  isSearching: boolean;

  setSearchQuery: (query: string) => void;
  loadFriends: () => Promise<void>;
  acceptRequest: (requestId: string) => Promise<void>;
  declineRequest: (requestId: string) => Promise<void>;
  removeFriend: (friendshipId: string) => Promise<void>;
  sendRequest: (friendId: string) => Promise<void>;
  searchFriends: (query: string, currentUserId?: string) => Promise<void>;
  clearSearch: () => void;
  initializeSocketEvents: () => () => void;
}

export const useFriendStore = create<FriendState>((set, get) => ({
  friends: [],
  friendRequests: [],
  isLoading: false,
  searchQuery: '',
  searchResults: [],
  isSearching: false,

  setSearchQuery: (query) => set({ searchQuery: query }),

  loadFriends: async () => {
    set({ isLoading: true });
    try {
      const [friendsList, requests] = await Promise.all([
        FriendApi.getFriends(),
        FriendApi.getFriendRequests(),
      ]);
      set({ friends: friendsList, friendRequests: requests });
    } catch (e) {
      console.error('Load friends error:', e);
    } finally {
      set({ isLoading: false });
    }
  },

  acceptRequest: async (requestId) => {
    try {
      await FriendApi.acceptFriendRequest(requestId);
      const req = get().friendRequests.find(r => r.id === requestId);
      if (req) {
        const socket = getSocket();
        if (socket) socket.emit('friend_accepted', { friendId: req.user.id });
      }
      await get().loadFriends();
    } catch (e) {
      console.error(e);
    }
  },

  declineRequest: async (requestId) => {
    try {
      await FriendApi.declineFriendRequest(requestId);
      set((state) => ({
        friendRequests: state.friendRequests.filter(r => r.id !== requestId)
      }));
    } catch (e) {
      console.error(e);
    }
  },

  removeFriend: async (friendshipId) => {
    try {
      const friend = get().friends.find(f => f.friendshipId === friendshipId);
      await FriendApi.removeFriend(friendshipId);
      if (friend) {
        const socket = getSocket();
        if (socket) socket.emit('friend_removed', { friendId: friend.id });
      }
      set((state) => ({
        friends: state.friends.filter(f => f.friendshipId !== friendshipId)
      }));
    } catch (e) {
      console.error(e);
    }
  },

  sendRequest: async (friendId) => {
    try {
      const result = await FriendApi.sendFriendRequest(friendId);
      const socket = getSocket();
      if (socket) socket.emit('friend_request', { friendId });
      
      await get().loadFriends();
      set((state) => ({
        searchResults: state.searchResults.filter(u => u.id !== friendId)
      }));
    } catch (e) {
      console.error(e);
    }
  },

  searchFriends: async (query, currentUserId) => {
    const raw = query.trim();
    const q = raw.startsWith('@') ? raw.slice(1) : raw;
    
    if (q.length < 3) {
      set({ searchResults: [] });
      return;
    }

    set({ isSearching: true });
    try {
      const results = await UserApi.searchUsers(q);
      const { friends } = get();
      const friendIds = new Set(friends.map(f => f.id));
      
      set({ 
        searchResults: results.filter(u => u.id !== currentUserId && !friendIds.has(u.id)) 
      });
    } catch (e) {
      console.error(e);
    } finally {
      set({ isSearching: false });
    }
  },

  clearSearch: () => set({ searchQuery: '', searchResults: [] }),

  initializeSocketEvents: () => {
    const socket = getSocket();
    if (!socket) return () => {};

    const onFriendRequestReceived = () => {
      FriendApi.getFriendRequests()
        .then(reqs => set({ friendRequests: reqs }))
        .catch(() => {});
    };

    const onFriendRequestAccepted = () => {
      get().loadFriends();
    };

    const onFriendRemoved = (data: { userId: string }) => {
      set((state) => ({
        friends: state.friends.filter(f => f.id !== data.userId)
      }));
    };

    socket.on('friend_request_received', onFriendRequestReceived);
    socket.on('friend_request_accepted', onFriendRequestAccepted);
    socket.on('friend_removed', onFriendRemoved);

    return () => {
      socket.off('friend_request_received', onFriendRequestReceived);
      socket.off('friend_request_accepted', onFriendRequestAccepted);
      socket.off('friend_removed', onFriendRemoved);
    };
  }
}));
