import { createSignal, createEffect, For, Show, onMount } from 'solid-js';
import { gql } from '@urql/core';
import { createQuery, createMutation, createSubscription } from '@urql/solid';
import { Message } from '../types';
import 'emoji-picker-element';
import { EmojiClickEvent } from 'emoji-picker-element/shared';
import { Picker } from 'emoji-picker-element';

const ROOM_QUERY = gql`
  query GetRoom($id: ID!) {
    room(id: $id) {
      id
      name
      description
      isPrivate
      owner {
        id
        username
      }
      members {
        id
        username
      }
      messages {
        id
        content
        createdAt
        user {
          id
          username
        }
      }
    }
  }
`;

const SEND_MESSAGE_MUTATION = gql`
  mutation SendMessage($content: String!, $roomId: ID!) {
    sendMessage(content: $content, roomId: $roomId) {
      id
      content
      createdAt
      user {
        id
        username
      }
    }
  }
`;

const MESSAGE_SUBSCRIPTION = gql`
  subscription OnMessageAdded($roomId: ID!) {
    messageAdded(roomId: $roomId) {
      id
      content
      createdAt
      user {
        id
        username
      }
    }
  }
`;

const LEAVE_ROOM_MUTATION = gql`
  mutation LeaveRoom($roomId: ID!) {
    leaveRoom(roomId: $roomId)
  }
`;

interface ChatRoomProps {
  roomId: string;
  userId: string;
  onLeaveRoom?: () => void;
}

export function ChatRoom(props: ChatRoomProps) {
  const [variables, setVariables] = createSignal({
    id: props.roomId,
    roomId: props.roomId,
  });
  const [message, setMessage] = createSignal('');
  const [messages, setMessages] = createSignal<Message[]>([]);
  const [confirmLeave, setConfirmLeave] = createSignal(false);
  const [leaveError, setLeaveError] = createSignal<string | null>(null);
  const [showEmojiPicker, setShowEmojiPicker] = createSignal(false);
  const [emojiPickerRef, setPickerRef] = createSignal<Picker | undefined>(
    undefined
  );
  let messagesContainer: HTMLDivElement | undefined;
  let messageInput: HTMLInputElement | undefined;
  let emojiPickerContainer: HTMLDivElement | undefined;

  const scrollToBottom = () => {
    if (messagesContainer) {
      messagesContainer.scrollTop = messagesContainer.scrollHeight;
    }
  };

  // Query room details
  const [roomQuery] = createQuery({
    query: ROOM_QUERY,
    variables: variables,
    context: {
      requestPolicy: 'network-only', // Force refetch when variables change
    },
  });

  // Send message mutation
  const [, sendMessage] = createMutation(SEND_MESSAGE_MUTATION);

  // Subscribe to new messages
  const [messageSubscription] = createSubscription({
    query: MESSAGE_SUBSCRIPTION,
    variables: variables,
    pause: false, // Ensure subscription is active
  });

  // Leave room mutation
  const [leaveRoomResult, leaveRoom] = createMutation(LEAVE_ROOM_MUTATION);

  // Reset messages when room changes
  createEffect(() => {
    // Access props.roomId to create a dependency
    setVariables({ id: props.roomId, roomId: props.roomId });
    // Reset messages when room changes
    // Clear any errors or confirmations
    setLeaveError(null);
    setConfirmLeave(false);
  });

  // Load initial messages
  createEffect(() => {
    const result = roomQuery;
    if (result.data?.room) {
      setMessages(result.data.room.messages);
    }
  });

  createEffect(() => {
    if (messages().length > 0) {
      scrollToBottom();
    }
  });

  // Handle new messages from subscription
  createEffect(() => {
    const result = messageSubscription;
    if (result.data?.messageAdded) {
      const newMessage = result.data.messageAdded;
      setMessages((prev) => [...prev, newMessage]);
      scrollToBottom();
    }
  });

  // Handle leave room error
  createEffect(() => {
    if (leaveRoomResult.error) {
      setLeaveError(leaveRoomResult.error.message);
      setConfirmLeave(false);
    }
  });

  const MAX_MESSAGE_LENGTH = 2048;

  const handleSendMessage = async (e: Event) => {
    e.preventDefault();

    const trimmedMessage = message().trim();
    if (!trimmedMessage) return;
    if (trimmedMessage.length > MAX_MESSAGE_LENGTH) return;

    try {
      await sendMessage({
        content: trimmedMessage,
        roomId: props.roomId,
      });
      setMessage('');
      scrollToBottom();
    } catch (error) {
      console.error('Failed to send message:', error);
    }
  };

  const handleLeaveRoom = async () => {
    if (!confirmLeave()) {
      setConfirmLeave(true);
      return;
    }

    setLeaveError(null);
    try {
      const result = await leaveRoom({ roomId: props.roomId });
      if (result.data?.leaveRoom) {
        if (props.onLeaveRoom) {
          props.onLeaveRoom();
        }
      }
    } catch (err) {
      console.error('Failed to leave room:', err);
    }
  };

  const cancelLeave = () => {
    setConfirmLeave(false);
    setLeaveError(null);
  };

  const formatTime = (dateString: string) => {
    const date = new Date(dateString);
    return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
  };

  const toggleEmojiPicker = () => {
    setShowEmojiPicker(!showEmojiPicker());
  };

  createEffect(() => {
    const handleEmojiSelect = (event: EmojiClickEvent) => {
      setMessage((prev) => prev + event.detail.unicode);
      messageInput?.focus();
    };
    const ref = emojiPickerRef();
    if (ref) {
      ref.addEventListener('emoji-click', handleEmojiSelect);
      return () => {
        ref.removeEventListener('emoji-click', handleEmojiSelect);
      };
    }
  });

  // Close emoji picker when clicking outside
  onMount(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        emojiPickerContainer &&
        !emojiPickerContainer.contains(event.target as Node)
      ) {
        setShowEmojiPicker(false);
      }
    };

    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  });

  // Function to generate avatar URL
  const getUserAvatarUrl = (userId: string, size: number = 40) =>
    `https://avatars.jusemon.com/${userId}?size=${size}`;

  return (
    <div class='chat-room'>
      <Show when={roomQuery.data?.room} fallback={<div>Loading room...</div>}>
        <div class='chat-header'>
          <h2>{roomQuery.data?.room.name}</h2>
          <p>{roomQuery.data?.room.description}</p>
          <div class='room-actions'>
            <Show when={leaveError()}>
              <div class='error-message'>{leaveError()}</div>
            </Show>
            <Show when={confirmLeave()}>
              <div class='confirm-leave'>
                <span>Are you sure you want to leave this room?</span>
                <button onClick={handleLeaveRoom}>Yes</button>
                <button onClick={cancelLeave}>No</button>
              </div>
            </Show>
            <Show when={!confirmLeave()}>
              <button class='leave-button' onClick={handleLeaveRoom}>
                Leave Room
              </button>
            </Show>
          </div>
        </div>
      </Show>

      <div class='chat-messages' ref={messagesContainer}>
        <Show
          when={!roomQuery.fetching}
          fallback={<div>Loading messages...</div>}
        >
          <For each={messages()}>
            {(message) => (
              <div
                class={`message-wrapper ${message.user.id === props.userId ? 'own-message-wrapper' : 'other-message-wrapper'}`}
              >
                {message.user.id !== props.userId && (
                  <img
                    src={getUserAvatarUrl(message.user.id)}
                    alt={`${message.user.username}'s avatar`}
                    class='message-avatar'
                  />
                )}
                <div
                  class={`message ${message.user.id === props.userId ? 'own-message' : 'other-message'}`}
                >
                  <div class='message-header'>
                    <span class='username'>{message.user.username}</span>
                    <span class='time'>{formatTime(message.createdAt)}</span>
                  </div>
                  <div class='message-content'>{message.content}</div>
                </div>
              </div>
            )}
          </For>
        </Show>
      </div>

      <form class='message-form' onSubmit={handleSendMessage}>
        <div class='message-input-container'>
          <input
            ref={messageInput}
            type='text'
            value={message()}
            onInput={(e) => {
              const inputValue = e.currentTarget.value;
              if (inputValue.length <= MAX_MESSAGE_LENGTH) {
                setMessage(inputValue);
              }
            }}
            placeholder='Type a message...'
          />
          <button
            type='button'
            class='emoji-toggle-button'
            onClick={toggleEmojiPicker}
          >
            😊
          </button>
        </div>
        <div class='message-length-counter'>
          {message().length}/{MAX_MESSAGE_LENGTH}
        </div>
        <button
          type='submit'
          disabled={
            message().trim().length === 0 ||
            message().length > MAX_MESSAGE_LENGTH
          }
        >
          Send
        </button>

        {showEmojiPicker() && (
          <div ref={emojiPickerContainer} class='emoji-picker-container'>
            {/* @ts-ignore */}
            <emoji-picker ref={(el: Picker) => setPickerRef(el)}></emoji-picker>
          </div>
        )}
      </form>
    </div>
  );
}
