import { createSignal, createEffect, For, Show } from 'solid-js';
import { gql } from '@urql/core';
import { createQuery, createSubscription, createMutation } from '@urql/solid';
import { Room } from '../types';

const ROOMS_QUERY = gql`
  query GetRooms {
    rooms {
      id
      name
      description
      isPrivate
      createdAt
      members {
        id
      }
    }
  }
`;

const ROOM_ADDED_SUBSCRIPTION = gql`
  subscription OnRoomAdded {
    roomAdded {
      id
      name
      description
      isPrivate
      createdAt
      members {
        id
      }
    }
  }
`;

const ROOM_UPDATED_SUBSCRIPTION = gql`
  subscription OnRoomUpdated {
    roomUpdated {
      id
      name
      description
      isPrivate
      createdAt
      members {
        id
      }
    }
  }
`;

const JOIN_ROOM_MUTATION = gql`
  mutation JoinRoom($roomId: ID!) {
    joinRoom(roomId: $roomId) {
      id
      name
      members {
        id
      }
    }
  }
`;

interface RoomListProps {
  onSelectRoom: (roomId: string) => void;
  selectedRoomId?: string;
}

export function RoomList(props: RoomListProps) {
  const [rooms, setRooms] = createSignal<Room[]>([]);
  const [error, setError] = createSignal<string | null>(null);
  const [isJoining, setIsJoining] = createSignal(false);

  // Query rooms
  const [roomsQuery] = createQuery({
    query: ROOMS_QUERY,
    context: {
      requestPolicy: 'network-only',
    },
  });

  // Subscribe to new rooms
  const [roomAddedSubscription] = createSubscription<{
    roomAdded: Room;
  }>({
    query: ROOM_ADDED_SUBSCRIPTION,
  });

  // Subscribe to room updates (when members change)
  const [roomUpdatedSubscription] = createSubscription<{
    roomUpdated: Room;
  }>({
    query: ROOM_UPDATED_SUBSCRIPTION,
  });

  // Join room mutation
  const [joinRoomResult, joinRoom] = createMutation<{
    joinRoom: Room;
  }>(JOIN_ROOM_MUTATION);

  // Load initial rooms
  createEffect(() => {
    const result = roomsQuery;
    if (result.data?.rooms) {
      setRooms(result.data.rooms);
    }
  });

  // Handle new rooms from subscription
  createEffect(() => {
    const result = roomAddedSubscription;
    if (result.data?.roomAdded) {
      const newRoom = result.data.roomAdded;
      setRooms((prev) => {
        // Check if room already exists
        if (prev.some((room) => room.id === newRoom.id)) {
          return prev;
        }
        return [...prev, newRoom];
      });
    }
  });

  // Handle room updates from subscription
  createEffect(() => {
    const result = roomUpdatedSubscription;
    if (result.data?.roomUpdated) {
      const updatedRoom = result.data.roomUpdated;
      setRooms((prev) => {
        return prev.map((room) => {
          if (room.id === updatedRoom.id) {
            return { ...room, ...updatedRoom };
          }
          return room;
        });
      });
    }
  });

  // Handle join room error
  createEffect(() => {
    if (joinRoomResult.error) {
      setError(joinRoomResult.error.message);
      setIsJoining(false);
    }
  });

  const handleJoinRoom = async (roomId: string, event: MouseEvent) => {
    event.stopPropagation();
    setError(null);
    setIsJoining(true);

    try {
      const result = await joinRoom({ roomId });
      if (result.data?.joinRoom) {
        // Update the local room data with the joined room
        setRooms((prev) =>
          prev.map((room) =>
            room.id === roomId
              ? { ...room, members: result.data!.joinRoom.members }
              : room
          )
        );
        // Select the room after joining
        props.onSelectRoom(roomId);
      }
    } catch (err) {
      console.error('Failed to join room:', err);
    } finally {
      setIsJoining(false);
    }
  };

  // Check if the current user is a member of a room
  const isMember = (room: Room) => {
    const userId = window.localStorage.getItem('userId');
    return room.members?.some((member) => member.id === userId);
  };

  return (
    <div class='room-list'>
      <h2>Chat Rooms</h2>
      <Show when={error()}>
        <div class='error-message'>{error()}</div>
      </Show>
      <Show when={!roomsQuery.fetching} fallback={<div>Loading rooms...</div>}>
        <For each={rooms()}>
          {(room) => (
            <div class='room-item'>
              <div
                class={`room-info ${props.selectedRoomId === room.id ? 'selected' : ''}`}
                onClick={() =>
                  isMember(room) ? props.onSelectRoom(room.id) : null
                }
              >
                <div class='room-name'>
                  {room.name}
                  {isMember(room) && <span class='member-badge'>Member</span>}
                </div>
                <div class='room-description'>{room.description}</div>
              </div>
              <Show when={!isMember(room)}>
                <button
                  class='join-button'
                  onClick={(e) => handleJoinRoom(room.id, e)}
                  disabled={isJoining()}
                >
                  {isJoining() ? 'Joining...' : 'Join'}
                </button>
              </Show>
            </div>
          )}
        </For>
      </Show>
    </div>
  );
}
