import { useSocket } from '@/hooks/useSocket';
import { useAuthStore } from '@/stores/authStore';
import { Image, Mic, Send, Smile, X } from 'lucide-react';
import {
  useEffect,
  useRef,
  useState,
  type ChangeEvent,
  type FC,
  type FormEvent,
} from 'react';
import { toast } from 'sonner';
import { Button } from './ui/button';
import { Input } from './ui/input';

type MessageInputProps = {
  roomId: string;
};

export const MessageInput: FC<MessageInputProps> = ({ roomId }) => {
  const [message, setMessage] = useState('');
  const [isRateLimited, setIsRateLimited] = useState(false);
  const [showEmojiPicker, setShowEmojiPicker] = useState(false);
  const [isFocused, setIsFocused] = useState(false);
  const [isTyping, setIsTyping] = useState(false);
  const [imagePreview, setImagePreview] = useState<string | null>(null);
  const { socket } = useSocket();
  const { user } = useAuthStore();
  const inputRef = useRef<HTMLInputElement>(null);
  const imageInputRef = useRef<HTMLInputElement>(null);
  const typingTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  useEffect(() => {
    if (!socket) return;

    const handleRateLimitExceeded = (data: {
      message: string;
      remainingTime?: number;
    }) => {
      setIsRateLimited(true);
      toast.error(data.message);

      const resetTime = data.remainingTime ?? 60000;
      setTimeout(() => {
        setIsRateLimited(false);
      }, resetTime);
    };

    socket.on('rate_limit_exceeded', handleRateLimitExceeded);

    return () => {
      socket.off('rate_limit_exceeded', handleRateLimitExceeded);
    };
  }, [socket, toast]);

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();

    if ((!message.trim() && !imagePreview) || !socket || isRateLimited) return;

    socket.emit('send_message', {
      roomId,
      content: message.trim(),
      image: imagePreview,
    });

    if (isTyping && user) {
      socket.emit('typing_stop', { roomId, username: user.username });
      setIsTyping(false);
    }

    setMessage('');
    setImagePreview(null);

    if (imageInputRef.current) {
      imageInputRef.current.value = '';
    }
  };

  const handleEmojiClick = (emoji: string) => {
    setMessage((prev) => prev + emoji);
    inputRef.current?.focus();
    setShowEmojiPicker(false);
  };

  const handleTypingStart = () => {
    if (!socket || !user || isRateLimited) return;

    if (!isTyping) {
      socket.emit('typing_start', { roomId, username: user.username });
      setIsTyping(true);
    }

    if (typingTimeoutRef.current) {
      clearTimeout(typingTimeoutRef.current);
    }

    typingTimeoutRef.current = setTimeout(() => {
      if (socket && isTyping && user) {
        socket.emit('typing_stop', { roomId, username: user.username });
        setIsTyping(false);
      }
    }, 5000);
  };

  const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
    setMessage(e.target.value);
    handleTypingStart();
  };

  const handleFileSelect = () => {
    imageInputRef.current?.click();
  };

  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    if (file.size > 1024 * 1024 * 2) {
      toast.error('Image too large. Please select an image under 2MB.');
      return;
    }

    const reader = new FileReader();
    reader.onload = (event) => {
      const base64 = event.target?.result as string;
      setImagePreview(base64);
    };
    reader.readAsDataURL(file);
  };

  const handleRemoveImage = () => {
    setImagePreview(null);
    if (imageInputRef.current) {
      imageInputRef.current.value = '';
    }
  };

  useEffect(() => {
    return () => {
      if (typingTimeoutRef.current) {
        clearTimeout(typingTimeoutRef.current);
      }

      if (socket && isTyping && user) {
        socket.emit('typing_stop', { roomId, username: user.username });
      }
    };
  }, [socket, isTyping, user, roomId]);

  return (
    <div className="p-4 border-t border-gray-200 bg-white dark:bg-gray-900 transition-all duration-200">
      <div className="max-w-4xl mx-auto">
        {imagePreview && (
          <div className="mb-2 p-2 border rounded-lg bg-gray-50 dark:bg-gray-800 relative">
            <div className="relative w-full max-h-[200px] overflow-hidden rounded-md">
              <img
                src={imagePreview}
                alt="Image preview"
                className="max-w-full max-h-[180px] object-contain mx-auto"
              />
              <Button
                type="button"
                variant="destructive"
                size="icon"
                className="absolute top-1 right-1 h-6 w-6 rounded-full"
                onClick={handleRemoveImage}
              >
                <X className="h-3 w-3" />
              </Button>
            </div>
          </div>
        )}

        <form onSubmit={handleSubmit} className="relative">
          <div
            className={`flex items-center space-x-2 p-1 rounded-full border ${
              isFocused ? 'border-blue-400 shadow-sm' : 'border-gray-300'
            } bg-white dark:bg-gray-800 transition-all duration-200`}
          >
            <Button
              type="button"
              variant="ghost"
              size="icon"
              className="rounded-full h-9 w-9 text-gray-500 hover:text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-700"
              onClick={() => setShowEmojiPicker((prev) => !prev)}
            >
              <Smile className="h-5 w-5" />
            </Button>

            <Button
              type="button"
              variant="ghost"
              size="icon"
              className="rounded-full h-9 w-9 text-gray-500 hover:text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-700"
              onClick={handleFileSelect}
            >
              <Image className="h-5 w-5" />
            </Button>

            <input
              type="file"
              ref={imageInputRef}
              accept="image/*"
              onChange={handleFileChange}
              className="hidden"
            />

            <Input
              ref={inputRef}
              value={message}
              onChange={handleInputChange}
              onFocus={() => setIsFocused(true)}
              onBlur={() => setIsFocused(false)}
              placeholder={
                isRateLimited
                  ? 'Rate limited - please wait...'
                  : imagePreview
                    ? 'Add a caption...'
                    : 'Type your message...'
              }
              disabled={isRateLimited}
              className="flex-1 border-0 focus-visible:ring-0 focus-visible:ring-offset-0 bg-transparent py-2 px-3"
            />

            {message.trim() || imagePreview ? (
              <Button
                type="submit"
                size="icon"
                disabled={(!message.trim() && !imagePreview) || isRateLimited}
                className="rounded-full h-9 w-9 bg-blue-500 hover:bg-blue-600 text-white"
              >
                <Send className="h-4 w-4" />
              </Button>
            ) : (
              <Button
                type="button"
                variant="ghost"
                size="icon"
                className="rounded-full h-9 w-9 text-gray-500 hover:text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-700"
              >
                <Mic className="h-5 w-5" />
              </Button>
            )}
          </div>

          {/* Emoji picker TODO: implement emoji-mart */}
          {showEmojiPicker && (
            <div className="absolute bottom-full mb-2 p-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700">
              <div className="grid grid-cols-8 gap-1">
                {['😀', '😂', '❤️', '👍', '🎉', '🔥', '👏', '😢'].map(
                  (emoji) => (
                    <button
                      key={emoji}
                      type="button"
                      onClick={() => handleEmojiClick(emoji)}
                      className="p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors"
                    >
                      {emoji}
                    </button>
                  )
                )}
              </div>
            </div>
          )}
        </form>

        {isFocused && !isRateLimited && (
          <div className="mt-1 text-xs text-gray-500 dark:text-gray-400 flex justify-between">
            <span>Press Enter to send</span>
            <span>{message.length} / 2000</span>
          </div>
        )}
      </div>
    </div>
  );
};
