import React, { useEffect, useRef, useState, useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {
  selectChatMessages,
  selectFetchStatus,
  selectActiveChannel,
  selectIsUploading,
  selectUploadFileName,
  fetchChatHistory
} from '../../../store/features/sessionChatSlice';
import { selectSessionId } from '../../../store/features/activeSessionSlice';
import JKChatMessage from './JKChatMessage';
import JKChatLoadingSpinner from './JKChatLoadingSpinner';
import JKChatEmptyState from './JKChatEmptyState';
import JKChatUploadProgress from './JKChatUploadProgress';

/**
 * JKChatMessageList - Message list component with auto-scroll behavior
 *
 * Displays list of messages for the active channel with auto-scroll to bottom.
 *
 * Auto-scroll behavior:
 * - Scrolls to bottom on component mount
 * - Scrolls to bottom when new message arrives (if user is at bottom)
 * - Disables auto-scroll when user manually scrolls up
 * - Re-enables auto-scroll when user scrolls back to bottom (within 50px)
 *
 * States:
 * - Loading: Shows spinner while fetching history
 * - Empty: Shows "No messages yet" when channel is empty
 * - Messages: Scrollable list of messages with auto-scroll
 */
const JKChatMessageList = () => {
  const dispatch = useDispatch();
  const activeChannel = useSelector(selectActiveChannel);
  const sessionId = useSelector(selectSessionId);
  const messages = useSelector((state) => selectChatMessages(state, activeChannel));
  const fetchStatus = useSelector((state) => selectFetchStatus(state, activeChannel));
  const isUploading = useSelector(selectIsUploading);
  const uploadFileName = useSelector(selectUploadFileName);

  const listRef = useRef(null);
  const [isUserScrolling, setIsUserScrolling] = useState(false);
  const scrollTimeoutRef = useRef(null);

  /**
   * Scroll to bottom helper
   * Uses smooth scrolling for better UX
   */
  const scrollToBottom = useCallback(() => {
    if (listRef.current) {
      listRef.current.scrollTo({
        top: listRef.current.scrollHeight,
        behavior: 'smooth'
      });
    }
  }, []);

  /**
   * Detect if user is at bottom (within 50px threshold)
   * @returns {boolean} True if user is at or near bottom
   */
  const isAtBottom = useCallback(() => {
    if (!listRef.current) return false;
    const { scrollTop, scrollHeight, clientHeight } = listRef.current;
    return scrollHeight - scrollTop - clientHeight < 50;
  }, []);

  /**
   * Handle scroll events
   * Debounces scroll detection with 300ms timeout
   * Re-enables auto-scroll if user scrolls back to bottom
   */
  const handleScroll = useCallback(() => {
    if (!listRef.current) return;

    // Clear existing timeout
    if (scrollTimeoutRef.current) {
      clearTimeout(scrollTimeoutRef.current);
    }

    // Set user scrolling flag
    setIsUserScrolling(true);

    // Reset flag after scroll stops (300ms debounce)
    scrollTimeoutRef.current = setTimeout(() => {
      setIsUserScrolling(false);

      // Re-enable auto-scroll if user scrolled to bottom
      if (isAtBottom()) {
        setIsUserScrolling(false);
      }
    }, 300);
  }, [isAtBottom]);

  /**
   * Auto-scroll on new messages (if user at bottom or not manually scrolling)
   * Only triggers when message count changes
   */
  useEffect(() => {
    if (!isUserScrolling && messages.length > 0) {
      scrollToBottom();
    }
  }, [messages.length, isUserScrolling, scrollToBottom]);

  /**
   * Scroll to bottom on mount
   * Delayed by 100ms to ensure DOM is rendered
   */
  useEffect(() => {
    if (messages.length > 0) {
      setTimeout(scrollToBottom, 100);
    }
  }, [scrollToBottom]);

  /**
   * Cleanup timeout on unmount
   * Prevents memory leaks
   */
  useEffect(() => {
    return () => {
      if (scrollTimeoutRef.current) {
        clearTimeout(scrollTimeoutRef.current);
      }
    };
  }, []);

  /**
   * Fetch chat history when channel becomes active
   * Only fetches once per channel (when status is 'idle')
   * Does NOT retry on failure to avoid infinite loops
   */
  useEffect(() => {
    // Only fetch when status is 'idle' (initial state)
    // This prevents infinite loops on API failure ('failed' status)
    if (activeChannel && fetchStatus === 'idle') {
      // For session chat, activeChannel is the sessionId
      // Pass sessionId so the thunk knows to fetch 'session' channel type
      dispatch(fetchChatHistory({
        channel: activeChannel,
        sessionId: sessionId || activeChannel  // Use sessionId from Redux, fallback to activeChannel
      }));
    }
  }, [dispatch, activeChannel, sessionId, fetchStatus]);

  // Loading state
  if (fetchStatus === 'loading' && messages.length === 0) {
    return <JKChatLoadingSpinner />;
  }

  // Fetch error state
  if (fetchStatus === 'failed' && messages.length === 0) {
    return (
      <div
        style={{
          padding: '16px',
          textAlign: 'center',
          color: '#dc3545',
          fontSize: '14px'
        }}
      >
        Failed to load message history
      </div>
    );
  }

  // Empty state
  if (messages.length === 0) {
    return <JKChatEmptyState />;
  }

  // Message list
  return (
    <div
      ref={listRef}
      onScroll={handleScroll}
      style={{
        flex: 1,
        overflowY: 'auto',
        padding: '16px',
        backgroundColor: '#ffffff'
      }}
    >
      {/* Loading spinner at top during pagination */}
      {fetchStatus === 'loading' && messages.length > 0 && (
        <div style={{ padding: '8px', textAlign: 'center' }}>
          <JKChatLoadingSpinner />
        </div>
      )}
      {messages.map((message) => (
        <JKChatMessage key={message.id} message={message} />
      ))}
      {/* Upload progress indicator */}
      {isUploading && uploadFileName && (
        <JKChatUploadProgress fileName={uploadFileName} />
      )}
    </div>
  );
};

export default JKChatMessageList;
