import { useEffect, useState } from 'react';
import { twMerge } from 'tailwind-merge';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import Avatar from '@/components/image/Avatar';
import { toast } from '@/components/toast/Toast';
import { ArrowUpIcon } from '@/icons';
import { useApiClient } from '@/lib/apiClient';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { FALLBACK_IMAGE_URL } from '@/utils/constants';

import { ChatMessageSentResponse } from './interfaces';

interface ChatInputProps {
  className?: string;
  onMessageSent?: () => void;
  commentsEnabled?: () => boolean; // Returns true if message can be sent
  inputRef?: React.RefObject<HTMLInputElement | null>;
  stationId: string;
  replyTo?: string; // Username to reply to, will prepend @username to the message
  setReplyTo?: (handle: string | undefined) => void; // Function to clear reply state
}

export function ChatInput({
  className = '',
  onMessageSent,
  commentsEnabled,
  inputRef,
  stationId,
  replyTo,
  setReplyTo,
}: ChatInputProps) {
  const { session } = useStores();
  const [message, setMessage] = useState('');
  const [lastSentTime, setLastSentTime] = useState<number>(0);
  const apiClient = useApiClient();

  // Handle reply prepending when replyTo prop changes
  useEffect(() => {
    if (replyTo) {
      setMessage(`@${replyTo} ${message}`);
      // Focus the input after prepending
      if (inputRef?.current) {
        inputRef.current.focus();
        // Set cursor to end of input
        if (inputRef.current) {
          inputRef.current.setSelectionRange(
            inputRef.current.value.length,
            inputRef.current.value.length
          );
        }
      }
      setReplyTo?.(undefined); // Clear reply state after prepending
    }
  }, [replyTo, inputRef]);

  const handleSend = async () => {
    if (!message.trim()) return;

    // Check if parent wants to validate before sending
    if (commentsEnabled && !commentsEnabled()) {
      return;
    }
    // Rate Limiting
    const now = Date.now();
    const timeSinceLastMessage = now - lastSentTime;
    const rateLimitMs = 1000;

    if (timeSinceLastMessage < rateLimitMs) {
      toast({
        title: 'Slow down!',
        description: `Hold on there, cowboy! You're sending messages too fast!`,
        status: 'error',
        duration: 2000,
        isClosable: true,
      });
      return;
    }

    const errorToastContents: {
      title: string;
      description: string;
    } = {
      title: 'Failed to send message',
      description: 'Please try again.',
    };

    try {
      const response: ChatMessageSentResponse = await apiClient.POST(
        '/api/living_radio/{station_id}/chat',
        {
          params: { path: { station_id: stationId } },
          body: { message: message },
        }
      );

      if (response.error) {
        if (response.response.status === 400) {
          errorToastContents.title = 'Message not sent';
          errorToastContents.description = response.error.detail
            ? response.error.detail
            : 'Please try again.';
          throw new Error(errorToastContents.description);
        } else {
          errorToastContents.title = 'Failed to send message';
          errorToastContents.description = response.error.detail
            ? response.error.detail
            : 'Please try again.';
        }
        throw new Error(errorToastContents.description);
      }

      // Update last sent time after successful send
      setLastSentTime(now);

      // Log successful message sent
      logWebUserEvent({
        actionName: 'LivingRadioMessageSent',
        principalObjectType: 'livingRadioChat',
        principalObjectValue: stationId,
        context: {
          userId: session.userId || '',
          stationId: stationId,
          messageLength: message.length,
          message,
          messageType: 'text',
        },
      });

      setMessage(''); // Clear input after successful send
      onMessageSent?.();
    } catch (error) {
      toast({
        ...errorToastContents,
        status: 'error',
        duration: 4000,
        isClosable: true,
      });
    }
  };

  return (
    <div
      className={twMerge(
        'flex h-[40px] items-center gap-2 rounded-full p-2 md:h-[50px] md:gap-3 md:p-3',
        'border border-white/10 bg-background-glass-thick',
        'focus-within:bg-white/20 hover:border-white/20 hover:bg-white/20',
        'transition-colors focus-within:border-white/20',
        className
      )}
    >
      {/* User profile picture */}
      <div className='h-5 w-5 shrink-0 overflow-hidden rounded-full md:h-7 md:w-7'>
        <Avatar
          src={session.user?.avatar_image_url || FALLBACK_IMAGE_URL}
          displayName={session.user?.display_name || 'User'}
          size={24}
          className='h-full w-full object-cover'
        />
      </div>

      {/* Text input */}
      <input
        ref={inputRef}
        type='text'
        value={message}
        onChange={(e) => {
          if (e.target.value.length > 300) {
            toast({
              title: 'Message too long',
              description: 'Please keep your message under 300 characters.',
              status: 'error',
            });
            setMessage(e.target.value.slice(0, 300));
            return;
          }
          setMessage(e.target.value);
        }}
        placeholder='Type a message...'
        className='live-radio-chat-input min-w-0 flex-1 border-none bg-transparent text-base text-white placeholder-white/50 outline-none'
        onKeyDown={(e) => {
          if (e.key === 'Enter' && !e.shiftKey) {
            e.preventDefault();
            handleSend();
          }
        }}
      />

      {/* Send button */}
      <Button
        onClick={handleSend}
        className='flex h-6 w-6 shrink-0 items-center justify-center p-0! md:h-8 md:w-8'
        aria-label='Send message'
        disabled={!message.trim()}
        variant={ButtonVariant.Primary}
        size={ButtonSize.Mini}
        shape={ButtonShape.Pill}
        icon={ArrowUpIcon}
        iconClassName='w-3 h-3 md:w-4 md:h-4'
      />
    </div>
  );
}
