import React, { useContext, useEffect, useRef, useState } from "react";
import styled, { ThemeContext } from "styled-components";
import { Formik, Form, Field } from "formik";
import * as Yup from "yup";
import { AttachFile, Delete, Send, Menu } from "@mui/icons-material"; // Keeping icons for now, can replace later if needed
import { Tooltip } from "@mui/material";
import Markdown from "markdown-to-jsx";

import {
  ConversationPrompt,
} from "../../data";
import { ConversationContext } from "../../contexts/ConversationContext";
import ConversationDetailCard from "../../components/ConversationDetailCard/ConversationDetailCard";
import { WebSocketContext, ConnectionStatus } from "../../contexts/WebSocketContext";
import { MessageContext } from "../../contexts/MessageContext";
import ParticleBackground from "../../components/ParticleBackground/ParticleBackground";

import Header2 from "../../components/Header2/Header2";

// Styled Components
const PageContainer = styled.div`
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  display: flex;
  color: ${({ theme }) => theme.colors.text};
  font-family: 'Inter', sans-serif;
  /* background-color: ${({ theme }) => theme.colors.background}; Removed to show particles */
`;

const Sidebar = styled.div<{ $isOpen: boolean }>`
  width: 280px;
  height: 100%;
  background: ${({ theme }) => theme.darkMode ? 'rgba(0, 0, 0, 0.6)' : 'rgba(255, 255, 255, 0.6)'};
  backdrop-filter: blur(10px);
  border-right: 1px solid ${({ theme }) => theme.colors.cardBorder};
  display: flex;
  flex-direction: column;
  padding: 1rem;
  padding-top: 5rem; // Account for header
  z-index: 20;
  transition: transform 0.3s ease;

  @media (max-width: 768px) {
    position: absolute;
    transform: ${({ $isOpen }) => $isOpen ? 'translateX(0)' : 'translateX(-100%)'};
    background: ${({ theme }) => theme.darkMode ? 'rgba(0, 0, 0, 0.95)' : 'rgba(255, 255, 255, 0.95)'};
    box-shadow: ${({ $isOpen }) => $isOpen ? '0 0 20px rgba(0,0,0,0.5)' : 'none'};
  }
`;

const MobileSidebarToggle = styled.button`
  display: none;
  position: absolute;
  top: 5.5rem; /* Below header */
  left: 1rem;
  z-index: 15;
  padding: 0.5rem 1rem;
  background: ${({ theme }) => theme.main};
  color: white;
  border: none;
  border-radius: 2rem;
  font-weight: 600;
  box-shadow: 0 4px 12px rgba(0,0,0,0.2);
  cursor: pointer;
  transition: all 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0,0,0,0.3);
  }

  @media (max-width: 768px) {
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }
`;

const Overlay = styled.div<{ $isOpen: boolean }>`
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(2px);
  z-index: 15;
  opacity: ${({ $isOpen }) => $isOpen ? 1 : 0};
  pointer-events: ${({ $isOpen }) => $isOpen ? 'auto' : 'none'};
  transition: opacity 0.3s ease;

  @media (max-width: 768px) {
    display: block;
  }
`;

const MainContent = styled.div`
  flex: 1;
  height: 100%;
  display: flex;
  flex-direction: column;
  position: relative;
  z-index: 5;
  padding-top: 4rem; // Account for header
`;

const ChatArea = styled.div`
  flex: 1;
  overflow-y: auto;
  padding: 2rem;
  display: flex;
  flex-direction: column;
  scroll-behavior: smooth;

  &::-webkit-scrollbar {
    width: 8px;
  }
  &::-webkit-scrollbar-track {
    background: transparent;
  }
  &::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.2);
    border-radius: 4px;
  }
`;

const InputArea = styled.div`
  padding: 1.5rem 2rem;
  background: ${({ theme }) => theme.darkMode ? 'rgba(0, 0, 0, 0.4)' : 'rgba(255, 255, 255, 0.4)'};
  backdrop-filter: blur(5px);
  border-top: 1px solid ${({ theme }) => theme.colors.cardBorder};
`;

const StyledInputContainer = styled.div`
  position: relative;
  max-width: 900px;
  margin: 0 auto;
  background: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.05)' : 'rgba(0, 0, 0, 0.05)'};
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  border-radius: 1.5rem;
  padding: 0.5rem 1rem;
  display: flex;
  align-items: center;
  transition: all 0.3s ease;

  &:focus-within {
    background: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'};
    border-color: ${({ theme }) => theme.main};
    box-shadow: 0 0 15px ${({ theme }) => theme.main}33;
  }
`;

const StyledInput = styled.textarea`
  flex: 1;
  background: transparent;
  border: none;
  color: ${({ theme }) => theme.colors.text};
  font-size: 1rem;
  padding: 0.8rem;
  outline: none;
  resize: none;
  overflow-y: auto;
  max-height: 150px; /* Approx 5 lines */
  font-family: inherit;
  line-height: 1.5;

  &::placeholder {
    color: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.4)' : 'rgba(0, 0, 0, 0.4)'};
  }
`;

const IconButton = styled.button`
  background: transparent;
  border: none;
  color: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.6)' : 'rgba(0, 0, 0, 0.6)'};
  cursor: pointer;
  padding: 0.5rem;
  border-radius: 50%;
  transition: all 0.2s ease;
  display: flex;
  align-items: center;
  justify-content: center;

  &:hover {
    color: ${({ theme }) => theme.colors.text};
    background: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'};
  }

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
`;

const StyledSelect = styled.select`
  background: transparent;
  border: none;
  color: ${({ theme }) => theme.colors.text};
  font-size: 0.9rem;
  padding: 0.5rem;
  outline: none;
  cursor: pointer;
  margin-right: 0.5rem;
  border-right: 1px solid ${({ theme }) => theme.colors.cardBorder};
  
  option {
    background: ${({ theme }) => theme.colors.background || '#1a1a1a'};
    color: ${({ theme }) => theme.colors.text};
  }
`;

const ConversationItem = styled.div<{ $active: boolean }>`
  padding: 0.8rem 1rem;
  margin-bottom: 0.5rem;
  border-radius: 0.5rem;
  cursor: pointer;
  background: ${(props) => (props.$active ? props.theme.main + "33" : "transparent")};
  color: ${(props) => (props.$active ? props.theme.colors.text : props.theme.darkMode ? "rgba(255, 255, 255, 0.7)" : "rgba(0, 0, 0, 0.7)")};
  transition: all 0.2s ease;
  border: 1px solid ${(props) => (props.$active ? props.theme.main + "66" : "transparent")};
  display: flex;
  justify-content: space-between;
  align-items: center;

  &:hover {
    background: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'};
    color: ${({ theme }) => theme.colors.text};
  }
`;

const ConversationTitle = styled.span`
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
  margin-right: 8px;
`;

const NewChatButton = styled.button`
  width: 100%;
  padding: 0.8rem;
  margin-bottom: 1rem;
  background: ${({ theme }) => theme.main};
  border: none;
  border-radius: 0.5rem;
  color: #fff;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px ${({ theme }) => theme.main}66;
  }
`;

const VisuallyHiddenInput = styled.input`
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  bottom: 0;
  left: 0;
  white-space: nowrap;
  width: 1px;
`;

const validationSchema = Yup.object().shape({
  prompt: Yup.string()
    .min(1, "Need to have at least one character")
    .required("This is required"),
});

type PromptValues = {
  prompt: string;
  file: Blob | null;
  fileType: string | null;
  modelName: string;
};

const AlwaysScrollToBottom = (): JSX.Element => {
  const elementRef = useRef<any>();
  useEffect(() => elementRef.current?.scrollIntoView({ behavior: "smooth" }));
  return <div ref={elementRef} />;
};

const AsyncDashboardInner = (): JSX.Element => {
  const [, , , sendMessage, isConnected, connectionStatus] =
    useContext(WebSocketContext);

  const { conversations, selectedConversation, setSelectedConversation, deleteConversation } =
    useContext(ConversationContext);

  const {
    conversationDetails,
    setConversationDetails,
    stateMessage,
    streamInterrupted,
  } = useContext(MessageContext);

  const conversationRef = useRef(conversationDetails);
  const theme = useContext(ThemeContext);
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const [isSidebarOpen, setIsSidebarOpen] = useState(false);

  const connectionBanner = (() => {
    if (connectionStatus === ConnectionStatus.CONNECTED || isConnected) {
      return null;
    }
    if (connectionStatus === ConnectionStatus.CONNECTING) {
      return { text: "Connecting to chat…", color: "#f0a500" };
    }
    if (connectionStatus === ConnectionStatus.RECONNECTING) {
      return { text: "Reconnecting…", color: "#f0a500" };
    }
    return { text: "Connection to the LLM is not active", color: "#ff4444" };
  })();

  const handlePromptSubmit = async (
    { prompt, file, fileType, modelName }: PromptValues,
    { resetForm }: any,
  ): Promise<void> => {
    try {
      const tempConversations: ConversationPrompt[] = [
        ...conversationDetails,
        new ConversationPrompt({ message: prompt, user_created: true }),
        new ConversationPrompt({ message: "", user_created: false }),
      ];

      conversationRef.current = tempConversations;
      setConversationDetails(tempConversations);
      sendMessage(prompt, selectedConversation, file, fileType, modelName);
      resetForm({
        values: {
          prompt: "",
          file: null,
          fileType: null,
          modelName: modelName, // Keep the selected model
        }
      });

      // Reset textarea height
      if (textareaRef.current) {
        textareaRef.current.style.height = 'auto';
      }
    } catch (e) {
      console.log(`error ${e}`);
    }
  };

  const adjustHeight = () => {
    const textarea = textareaRef.current;
    if (textarea) {
      textarea.style.height = 'auto';
      textarea.style.height = `${textarea.scrollHeight}px`;
    }
  };

  return (
    <PageContainer>
      <ParticleBackground />
      <Header2 />

      <Overlay $isOpen={isSidebarOpen} onClick={() => setIsSidebarOpen(false)} />

      <MobileSidebarToggle onClick={() => setIsSidebarOpen(true)}>
        <Menu fontSize="small" />
        <span>Conversations</span>
      </MobileSidebarToggle>

      <Sidebar $isOpen={isSidebarOpen}>
        <NewChatButton onClick={() => {
          setSelectedConversation(undefined);
          setIsSidebarOpen(false);
        }}>
          + New Chat
        </NewChatButton>
        <div style={{ overflowY: 'auto', flex: 1 }}>
          {conversations.map((convo) => (
            <ConversationItem
              key={convo.id}
              $active={convo.id === selectedConversation}
              onClick={() => {
                setSelectedConversation(convo.id);
                setIsSidebarOpen(false);
              }}
            >
              <ConversationTitle>{convo.title || "New Conversation"}</ConversationTitle>
              {convo.id === selectedConversation && (
                <IconButton
                  as="div"
                  onClick={(e) => {
                    e.stopPropagation();
                    deleteConversation(convo.id);
                  }}
                  style={{ padding: 4, width: 'auto', height: 'auto' }}
                >
                  <Delete fontSize="small" />
                </IconButton>
              )}
            </ConversationItem>
          ))}
        </div>
      </Sidebar>

      <MainContent>
        <ChatArea>
          {conversationDetails.length > 0 ? (
            conversationDetails.map((convo_detail, index) =>
              convo_detail.message.length > 0 ? (
                <ConversationDetailCard
                  message={convo_detail.message}
                  user_created={convo_detail.user_created}
                  key={convo_detail.id || index}
                />
              ) : (
                <ConversationDetailCard
                  message={stateMessage}
                  user_created={convo_detail.user_created}
                  key={convo_detail.id || index}
                />
              )
            )
          ) : (
            <div style={{
              display: 'flex',
              justifyContent: 'center',
              alignItems: 'center',
              height: '100%',
              color: theme?.darkMode ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.5)',
              fontSize: '1.2rem'
            }}>
              <Markdown>Select a conversation or start a new one.</Markdown>
            </div>
          )}
          <AlwaysScrollToBottom />
        </ChatArea>

        <InputArea>
          <Formik
            initialValues={{
              prompt: "",
              file: null,
              fileType: null,
              modelName: "FAST",
            }}
            validationSchema={validationSchema}
            onSubmit={handlePromptSubmit}
          >
            {(formik) => (
              <Form>
                {connectionBanner && (
                  <div style={{
                    color: connectionBanner.color,
                    textAlign: 'center',
                    marginBottom: '0.5rem',
                    fontSize: '0.9rem',
                    fontWeight: 500
                  }}>
                    {connectionBanner.text}
                  </div>
                )}
                {streamInterrupted && isConnected && (
                  <div style={{
                    color: '#f0a500',
                    textAlign: 'center',
                    marginBottom: '0.5rem',
                    fontSize: '0.85rem',
                    fontWeight: 500
                  }}>
                    Last response was interrupted. You can re-send your message.
                  </div>
                )}
                <StyledInputContainer>
                  <label htmlFor="file-upload" style={{ cursor: 'pointer', display: 'flex' }}>
                    <IconButton as="span">
                      <AttachFile />
                    </IconButton>
                  </label>
                  <VisuallyHiddenInput
                    id="file-upload"
                    type="file"
                    accept=".csv,.xlsx,.txt,.pdf,.PDF"
                    onChange={(event) => {
                      const file = event.target.files?.[0];
                      if (file) {
                        formik.setFieldValue("file", file);
                        formik.setFieldValue("fileType", file.type);
                      } else {
                        formik.setFieldValue("file", null);
                        formik.setFieldValue("fileType", null);
                      }
                    }}
                  />

                  <Field
                    as={StyledSelect}
                    name="modelName"
                  >
                    <option value="FAST">FAST</option>
                    <option value="THINKING">THINKING</option>
                  </Field>

                  <Field name="prompt">
                    {({ field }: any) => (
                      <StyledInput
                        {...field}
                        ref={textareaRef}
                        placeholder="Type a message..."
                        rows={1}
                        onKeyDown={(e: React.KeyboardEvent) => {
                          if (e.key === 'Enter' && !e.shiftKey) {
                            e.preventDefault();
                            if (formik.isValid && formik.dirty) {
                              formik.submitForm();
                            }
                          }
                        }}
                        onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
                          field.onChange(e);
                          adjustHeight();
                        }}
                      />
                    )}
                  </Field>

                  <Tooltip title={!isConnected ? "Connection to the LLM is not active" : "Send message"}>
                    <span>
                      <IconButton
                        type="submit"
                        disabled={!formik.isValid || !formik.dirty || !isConnected}
                        style={{
                          color: (formik.isValid && formik.dirty && isConnected) ? '#fff' : undefined,
                          background: (formik.isValid && formik.dirty && isConnected) ? theme?.main : undefined
                        }}
                      >
                        <Send />
                      </IconButton>
                    </span>
                  </Tooltip>
                </StyledInputContainer>
                {formik.values.file && (
                  <div style={{
                    marginTop: '0.5rem',
                    fontSize: '0.8rem',
                    color: theme?.darkMode ? 'rgba(255,255,255,0.6)' : 'rgba(0,0,0,0.6)',
                    textAlign: 'center'
                  }}>
                    Attached: {(formik.values.file as File).name}
                  </div>
                )}
              </Form>
            )}
          </Formik>
        </InputArea>
      </MainContent>
    </PageContainer>
  );
};

const AsyncDashboard2 = (): JSX.Element => {
  return <AsyncDashboardInner />;
};

export default AsyncDashboard2;
