import React, { forwardRef, useState, useEffect, useRef } from 'react';
import {
  Box,
  Paper,
  Button,
  Divider,
  useTheme,
  useMediaQuery,
  Tooltip,
} from '@mui/material';
import {
  Send as SendIcon
} from '@mui/icons-material';
import { useAuth } from 'hooks/AuthContext';
import { ChatMessage, ChatSession, ChatMessageUser, ChatMessageError, ChatMessageStreaming, ChatMessageStatus } from 'types/types';
import { ConversationHandle } from 'components/Conversation';
import { BackstoryPageProps } from 'components/BackstoryTab';
import { Message } from 'components/Message';
import { DeleteConfirmation } from 'components/DeleteConfirmation';
import { CandidateInfo } from 'components/ui/CandidateInfo';
import { useNavigate } from 'react-router-dom';
import { useAppState, useSelectedCandidate } from 'hooks/GlobalContext';
import PropagateLoader from 'react-spinners/PropagateLoader';
import { BackstoryTextField, BackstoryTextFieldRef } from 'components/BackstoryTextField';
import { BackstoryQuery } from 'components/BackstoryQuery';

const defaultMessage: ChatMessage = {
  status: "done", type: "text", sessionId: "", timestamp: new Date(), content: "", role: "user"
};

const CandidateChatPage = forwardRef<ConversationHandle, BackstoryPageProps>((props: BackstoryPageProps, ref) => {
  const { apiClient } = useAuth();
  const navigate = useNavigate();
  const { selectedCandidate } = useSelectedCandidate()
  const theme = useTheme();
  const [processingMessage, setProcessingMessage] = useState<ChatMessageStatus | ChatMessageError | null>(null);
  const [streamingMessage, setStreamingMessage] = useState<ChatMessage | null>(null);
  const backstoryTextRef = useRef<BackstoryTextFieldRef>(null);

  const { setSnack } = useAppState();  

  const [chatSession, setChatSession] = useState<ChatSession | null>(null);
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [streaming, setStreaming] = useState<boolean>(false);
  const messagesEndRef = useRef(null);

  // Load messages for current session
  const loadMessages = async () => {
    if (!chatSession?.id) return;
    
    try {
      const result = await apiClient.getChatMessages(chatSession.id);
      const chatMessages: ChatMessage[] = result.data;
      setMessages(chatMessages);
      setProcessingMessage(null);
      setStreamingMessage(null);
      console.log(`getChatMessages returned ${chatMessages.length} messages.`, chatMessages);
    } catch (error) {
      console.error('Failed to load messages:', error);
    }
  };

  const onDelete = async (session: ChatSession) => {
    if (!session.id) {
      return;
    }
    try {
      await apiClient.resetChatSession(session.id);
      // If we're deleting the currently selected session, clear it
      setMessages([]);
      setSnack('Session reset succeeded', 'success');
    } catch (error) {
      console.error('Failed to delete session:', error);
      setSnack('Failed to delete session', 'error');
    }
  };

  // Send message
  const sendMessage = async (message: string) => {
    if (!message.trim() || !chatSession?.id || streaming || !selectedCandidate) return;

    const messageContent = message;
    setStreaming(true);

    const chatMessage: ChatMessageUser = {
      sessionId: chatSession.id,
      role: "user",
      content: messageContent,
      status: "done",
      type: "text",
      timestamp: new Date()
    };

    setProcessingMessage({ ...defaultMessage, status: 'status', content: `Establishing connection with ${selectedCandidate.firstName}'s chat session.` });

    setMessages(prev => {
      const filtered = prev.filter((m: any) => m.id !== chatMessage.id);
      return [...filtered, chatMessage] as any;
    });

    try {
      apiClient.sendMessageStream(chatMessage, {
        onMessage: (msg: ChatMessage) => {
          setMessages(prev => {
            const filtered = prev.filter((m: any) => m.id !== msg.id);
            return [...filtered, msg] as any;
          });
          setStreamingMessage(null);
          setProcessingMessage(null);
        },
        onError: (error: string | ChatMessageError) => {
          console.log("onError:", error);
          let message: string;
          // Type-guard to determine if this is a ChatMessageBase or a string
          if (typeof error === "object" && error !== null && "content" in error) {
            setProcessingMessage(error);
            message = error.content as string;
          } else {
            setProcessingMessage({ ...defaultMessage, status: "error", content: error })
          }
          setStreaming(false);
        },
        onStreaming: (chunk: ChatMessageStreaming) => {
          // console.log("onStreaming:", chunk);
          setStreamingMessage({ ...chunk, role: 'assistant' });
        },
        onStatus: (status: ChatMessageStatus) => {
          setProcessingMessage(status);
        },
        onComplete: () => {
          console.log("onComplete");
          setStreamingMessage(null);
          setProcessingMessage(null);
          setStreaming(false);
        }
      });
    } catch (error) {
      console.error('Failed to send message:', error);
      setStreaming(false);
    }
  };

  // Auto-scroll to bottom when new messages arrive
  useEffect(() => {
    (messagesEndRef.current as any)?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  // Load sessions when username changes
  useEffect(() => {
    if (!selectedCandidate) return;
    try {
      setLoading(true);
      apiClient.getOrCreateChatSession(selectedCandidate, `Backstory chat with ${selectedCandidate.fullName}`, 'candidate_chat')
        .then(session => {
          setChatSession(session);
          setLoading(false);
        });
    } catch (error) {
      setSnack('Unable to load chat session', 'error');
    } finally {
      setLoading(false);
    }
  }, [selectedCandidate]);

  // Load messages when session changes
  useEffect(() => {
    if (chatSession?.id) {
      loadMessages();
    }
  }, [chatSession]);

  if (!selectedCandidate) {
    navigate('/find-a-candidate');
    return (<></>);
  }

  const welcomeMessage: ChatMessage = {
    sessionId: chatSession?.id || '',
    role: "information",
    type: "text",
    status: "done",
    timestamp: new Date(),
    content: `Welcome to the Backstory Chat about ${selectedCandidate.fullName}. Ask any questions you have about ${selectedCandidate.firstName}.`
  };

  return (
    <Box ref={ref} sx={{
      width: "100%",
      display: "flex",
      flexDirection: "column",
      gap: 1,
    }}>
      <CandidateInfo
        action={`Chat with Backstory about ${selectedCandidate.firstName}`}
        elevation={4}
        candidate={selectedCandidate}
        variant="small"
        sx={{ flexShrink: 0 }} // Prevent header from shrinking
      />

      {/* Chat Interface */}
      <Paper
        sx={{
          display: 'flex',
          flexDirection: 'column',
          flexGrow: 1,
          width: '100%',
          minHeight: 'max-content'
        }}
      >
        {/* Scrollable Messages Area */}
        {chatSession && <>
          <Box sx={{
            flexGrow: 1,
            p: 2,
            display: 'flex',
            flexDirection: 'column',
            minHeight: 'max-content', // Important for flex child
            // Custom scrollbar styling
            '&::-webkit-scrollbar': {
              width: '8px',
            },
            '&::-webkit-scrollbar-track': {
              backgroundColor: theme.palette.grey[100],
              borderRadius: '4px',
            },
            '&::-webkit-scrollbar-thumb': {
              backgroundColor: theme.palette.grey[400],
              borderRadius: '4px',
              '&:hover': {
                backgroundColor: theme.palette.grey[600],
              },
            },
          }}>
            {messages.length === 0 && <Message {...{ chatSession, message: welcomeMessage, }} />}
            {messages.map((message: ChatMessage) => (
              <Message key={message.id} {...{ chatSession, message }} />
            ))}
            {processingMessage !== null && (
              <Message {...{ chatSession, message: processingMessage }} />
            )}
            {streamingMessage !== null && (
              <Message {...{ chatSession, message: streamingMessage }} />
            )}
            {streaming && (
              <Box sx={{
                display: "flex",
                flexDirection: "column",
                alignItems: "center",
                justifyContent: "center",
                m: 1,
              }}>
                <PropagateLoader
                  size="10px"
                  loading={streaming}
                  aria-label="Loading Spinner"
                  data-testid="loader"
                />
              </Box>
            )}
            <div ref={messagesEndRef} />
          </Box>
        </>}
      </Paper>
      {selectedCandidate.questions?.length !== 0 && selectedCandidate.questions?.map(q => <BackstoryQuery question={q} />)}
      {/* Fixed Message Input */}
      <Box sx={{ display: 'flex', flexShrink: 0, gap: 1 }}>
        <DeleteConfirmation
          onDelete={() => { chatSession && onDelete(chatSession); }}
          disabled={!chatSession}
          sx={{ minWidth: 'auto', px: 2, maxHeight: "min-content" }}
          action="reset"
          label="chat session"
          title="Reset Chat Session"
          message={`Are you sure you want to reset the session? This action cannot be undone.`}
        />
        <BackstoryTextField
          placeholder="Type your message about the candidate..."
          ref={backstoryTextRef}
          onEnter={sendMessage}
          disabled={streaming || loading}
        />
        <Tooltip title="Send">
          <span style={{ minWidth: 'auto', maxHeight: "min-content", alignSelf: "center" }}
          >
        <Button
          variant="contained"
          onClick={() => { sendMessage((backstoryTextRef.current && backstoryTextRef.current.getAndResetValue()) || ""); }}
              disabled={streaming || loading}
        >
          <SendIcon />

        </Button>
          </span>
        </Tooltip>
      </Box>
    </Box>
  );
});

export { CandidateChatPage };