import streamlit as st
from graph import EssayWriter, RouteQuery, GraphState
from crew import *
import os
import traceback
import base64

# Install Graphviz if not found
if os.system("which dot") != 0:
    os.system("apt-get update && apt-get install -y graphviz")

st.markdown(
    """
    <h1 style="text-align: center; white-space: nowrap; font-size: 2.5em;">
        Multi-Agent Essay Writing Assistant
    </h1>
    """,
    unsafe_allow_html=True
)

# Ensure session state variables are initialized properly
if "messages" not in st.session_state:
    st.session_state["messages"] = [{"role": "assistant", "content": "Hello! How can I assist you today?"}]

if "app" not in st.session_state:
    st.session_state["app"] = None

if "chat_active" not in st.session_state:
    st.session_state["chat_active"] = True

# Sidebar with essay settings and user-defined length
# Sidebar with essay settings and user-defined length
with st.sidebar:
    st.subheader("About:")
    st.info(
        "\n\n 1. This app uses the 'gpt-4o-mini-2024-07-18' model."
        "\n\n 2. Writing essays may take some time, approximately 1-2 minutes."
    )

    # API Key Retrieval
    openai_key = st.secrets.get("OPENAI_API_KEY", "")

    st.divider()

    # User-defined essay length selection
    st.subheader("📝 Configure Essay Settings:")
    essay_length = st.number_input(
        "Select Essay Length (words):",
        min_value=150,
        max_value=500,
        value=250,
        step=50
    )

    #st.divider()

    #Language Selection
    #st.subheader("🌍 Select Language:")
    language_options = {
        "Arabic (العربية)": "Arabic",
        "Bengali (বাংলা)": "Bengali",
        "Bulgarian (Български)": "Bulgarian",
        "Chinese (中文, Simplified)": "Chinese (Simplified)",
        "Chinese (繁體, Traditional)": "Chinese (Traditional)",
        "Croatian (Hrvatski)": "Croatian",
        "Czech (Čeština)": "Czech",
        "Danish (Dansk)": "Danish",
        "Dutch (Nederlands)": "Dutch",
        "English": "English",
        "Filipino (Tagalog)": "Filipino",
        "Finnish (Suomi)": "Finnish",
        "French (Français)": "French",
        "German (Deutsch)": "German",
        "Greek (Ελληνικά)": "Greek",
        "Gujarati (ગુજરાતી)": "Gujarati",
        "Hebrew (עברית)": "Hebrew",
        "Hindi (हिन्दी)": "Hindi",
        "Hungarian (Magyar)": "Hungarian",
        "Indonesian (Bahasa Indonesia)": "Indonesian",
        "Italian (Italiano)": "Italian",
        "Japanese (日本語)": "Japanese",
        "Korean (한국어)": "Korean",
        "Malay (Bahasa Melayu)": "Malay",
        "Malayalam (മലയാളം)": "Malayalam",
        "Marathi (मराठी)": "Marathi",
        "Nepali (नेपाली)": "Nepali",
        "Norwegian (Norsk)": "Norwegian",
        "Persian (فارسی)": "Persian",
        "Polish (Polski)": "Polish",
        "Portuguese (Português)": "Portuguese",
        "Punjabi (ਪੰਜਾਬੀ)": "Punjabi",
        "Romanian (Română)": "Romanian",
        "Russian (Русский)": "Russian",
        "Serbian (Српски)": "Serbian",
        "Sinhala (සිංහල)": "Sinhala",
        "Slovak (Slovenčina)": "Slovak",
        "Spanish (Español)": "Spanish",
        "Swahili (Kiswahili)": "Swahili",
        "Swedish (Svenska)": "Swedish",
        "Tamil (தமிழ்)": "Tamil",
        "Telugu (తెలుగు)": "Telugu",
        "Thai (ไทย)": "Thai",
        "Turkish (Türkçe)": "Turkish",
        "Ukrainian (Українська)": "Ukrainian",
        "Urdu (اردو)": "Urdu",
        "Vietnamese (Tiếng Việt)": "Vietnamese"
    }
    
    selected_language = st.selectbox("Choose Language:", sorted(language_options.keys()), index=list(language_options.keys()).index("English"))

    st.divider()

    # Reference section
    st.subheader("📖 References:")
    st.markdown(
        "[1. Multi-Agent System with CrewAI and LangChain](https://discuss.streamlit.io/t/new-project-i-have-build-a-multi-agent-system-with-crewai-and-langchain/84002)",
        unsafe_allow_html=True
    )


# Initialize agents function
def initialize_agents():
    if not openai_key:
        st.error("⚠️ OpenAI API key is missing! Please provide a valid key through Hugging Face Secrets.")
        st.session_state["chat_active"] = True
        return None

    os.environ["OPENAI_API_KEY"] = openai_key
    try:
        # Prevent re-initialization
        if "app" in st.session_state and st.session_state["app"] is not None:
            return st.session_state["app"]
        
        # Initialize the full EssayWriter instance
        essay_writer = EssayWriter()  # Store the full instance
        st.session_state["app"] = essay_writer  # Now contains `graph`
        st.session_state["chat_active"] = False  # Enable chat after successful initialization

        return essay_writer
    except Exception as e:
        st.error(f"❌ Error initializing agents: {e}")
        st.session_state["chat_active"] = True
        return None


# Automatically initialize agents on app load
if st.session_state["app"] is None:
    st.session_state["app"] = initialize_agents()

if st.session_state["app"] is None:
    st.error("⚠️ Failed to initialize agents. Please check your API key and restart the app.")

app = st.session_state["app"]

# Function to invoke the agent and generate a response
def generate_response(topic, length, selected_language):
    if not app or not hasattr(app, "graph"):
        st.error("⚠️ Agents are not initialized. Please check the system or restart the app.")
        return {"response": "Error: Agents not initialized."}

    # Define section allocations dynamically based on length
    if length <= 300:
        intro_limit = length // 5  # Shorter intro (~20% of total)
        body_limit = length // 2   # 2-3 key sections only (~50% of total)
        conclusion_limit = length // 5  # Brief closing (~20% of total)
        num_sections = 2  # Fewer key points
    elif length <= 400:
        intro_limit = length // 6  # Slightly shorter intro (~17% of total)
        body_limit = length // 1.8  # Allows more depth (~55% of total)
        conclusion_limit = length // 6  # Balanced closing (~17% of total)
        num_sections = 3  # More sections
    else:
        intro_limit = length // 7  # Even shorter intro (~15% of total)
        body_limit = length // 1.7  # More depth in body (~60% of total)
        conclusion_limit = length // 7  # Shorter but strong closing (~15% of total)
        num_sections = 4  # Maximum sections for deeper discussion

    # Adjusted structured prompt with language enforcement
    refined_prompt = f"""
    Write a well-structured, engaging, and informative essay on "{topic}" in **{selected_language}** with **EXACTLY {length} words**.

    ### **Structure:**
    - **Title**: A compelling, creative title (max 10 words).
    - **Introduction** ({intro_limit} words max):
      - Define the topic & its importance concisely.
      - Provide a strong thesis statement.
      - Briefly mention key themes.

    - **Main Body** ({body_limit} words max):
      - Cover **{num_sections} key aspects only**.
      - Each section must have:
        - A clear **subheading**.
        - A **topic sentence** & supporting details.
        - **Examples, statistics, or historical references** (if relevant).
      - Ensure logical transitions between sections.

    - **Conclusion** ({conclusion_limit} words max):
      - Summarize key insights concisely.
      - Reinforce thesis based on discussion.
      - End with a **thought-provoking** final statement (question, reflection, or call to action).

    ### **Important Rules:**
    - 🚫 **DO NOT exceed {length} words**.
    - ✅ **Avoid redundancy & filler sentences**.
    - 🔄 **Merge similar ideas** to keep flow natural.
    - ✂ **Use precise, impactful language**.
    - 🎯 **Ensure balanced coverage** (not too broad or too specific).
    - **STOP when {length} words are reached**.
    - Write in **{selected_language}** ONLY.
    """

    # Invoke AI model with controlled word limit
    response = app.graph.invoke(input={
        "topic": topic,
        "length": length,
        "prompt": refined_prompt,
        "max_tokens": length * 1.2  # Ensures generation doesn’t exceed limit
    })

    return response


# Define Tabs
tab1, tab2 = st.tabs(["📜 Essay Generation", "📊 Workflow Viz"])

# 📜 Tab 1: Essay Generation
with tab1:
    # Display chat messages from the session
    if "messages" not in st.session_state:
        st.session_state["messages"] = [{"role": "assistant", "content": "Hello! How can I assist you today?"}]

    for message in st.session_state["messages"]:
        with st.chat_message(message["role"]):
            st.markdown(message["content"], unsafe_allow_html=True)

    # Input
    topic = st.text_input("📝 Provide an essay topic:", value="Write an essay on the cultural diversity of India")

    # Add spacing
    st.write("")

    # Generate button
    if st.button("🚀 Generate Essay"):
        if topic and topic.strip():  # Ensure it's not empty
            # Store user message only if it's not already stored
            if not any(msg["content"] == topic for msg in st.session_state["messages"]):
                st.session_state["messages"].append({"role": "user", "content": topic})

            with st.spinner("⏳ Generating your essay..."):
                response = None
                if app:
                    response = app.write_essay({"topic": topic})
                else:
                    st.error("⚠️ Agents are not initialized. Please check the system or restart the app.")

            # Store and display assistant response
            if response and "essay" in response:
                essay = response["essay"]

                assistant_response = f"Here is your {essay_length}-word essay preview and the download link."
                st.session_state["messages"].append({"role": "assistant", "content": assistant_response})

                st.chat_message("assistant").markdown(assistant_response)

                # Create Two-Column Layout
                col1, col2 = st.columns(2)

                with col1:
                    st.markdown(f"### 📝 Essay Preview ({essay_length} words)")
                    st.markdown(f"#### {essay['header']}")
                    st.markdown(essay["entry"])

                    for para in essay["paragraphs"]:
                        st.markdown(f"**{para['sub_header']}**")
                        st.markdown(para["paragraph"])

                    st.markdown("**🖊️ Conclusion:**")
                    st.markdown(essay["conclusion"])

                with col2:
                    st.markdown("### ✍️ Edit Your Essay:")

                    # Combine all parts of the essay into one editable text field
                    full_essay_text = f"## {essay['header']}\n\n{essay['entry']}\n\n"
                    for para in essay["paragraphs"]:
                        full_essay_text += f"### {para['sub_header']}\n{para['paragraph']}\n\n"
                    full_essay_text += f"**Conclusion:**\n{essay['conclusion']}"

                    # Editable text area for the user
                    edited_essay = st.text_area("Edit Here:", value=full_essay_text, height=300)

                    # Save and Download buttons
                    save_col1, save_col2 = st.columns(2)

                    with save_col1:
                        if st.button("💾 Save as TXT"):
                            with open("edited_essay.txt", "w", encoding="utf-8") as file:
                                file.write(edited_essay)
                            with open("edited_essay.txt", "rb") as file:
                                st.download_button(label="⬇️ Download TXT", data=file, file_name="edited_essay.txt", mime="text/plain")

                    with save_col2:
                        if st.button("📄 Save as PDF"):
                            from fpdf import FPDF

                            pdf = FPDF()
                            pdf.set_auto_page_break(auto=True, margin=15)
                            pdf.add_page()
                            pdf.set_font("Arial", size=12)

                            for line in edited_essay.split("\n"):
                                pdf.cell(200, 10, txt=line, ln=True, align='L')

                            pdf.output("edited_essay.pdf")

                            with open("edited_essay.pdf", "rb") as file:
                                st.download_button(label="⬇️ Download PDF", data=file, file_name="edited_essay.pdf", mime="application/pdf")

                # Provide download link for the original PDF 
                pdf_name = response.get("pdf_name")
                if pdf_name and os.path.exists(pdf_name):
                    with open(pdf_name, "rb") as pdf_file:
                        b64 = base64.b64encode(pdf_file.read()).decode()
                        href = f"<a href='data:application/octet-stream;base64,{b64}' download='{pdf_name}'>📄 Click here to download the original PDF</a>"
                        st.markdown(href, unsafe_allow_html=True)

                # Save response in session state
                st.session_state["messages"].append(
                    {"role": "assistant", "content": f"Here is your {essay_length}-word essay preview and the download link."}
                )
            elif response:
                st.markdown(response["response"])
                st.session_state["messages"].append({"role": "assistant", "content": response["response"]})
            else:
                st.error("⚠️ No response received. Please try again.")



# 📊 Tab 2: Workflow Visualization
with tab2:
    #st.subheader("📊 Multi-Agent Essay Writer Workflow Viz")

    try:
        graph_path = "/tmp/graph.png"  
        if os.path.exists(graph_path):
            st.image(graph_path, caption="Multi-Agent Essay Writer Workflow Visualization", use_container_width=True)
        else:
            st.warning("⚠️ Workflow graph not found. Please run `graph.py` to regenerate `graph.png`.")

    except Exception as e:
        st.error("❌ An error occurred while generating the workflow visualization.")
        st.text_area("Error Details:", traceback.format_exc(), height=500)


# Acknowledgement Section
st.markdown(
    """
    <div style="text-align: center; font-size: 14px; color: #555; padding-top: 200px; margin-top: 200px;">
        <strong>Acknowledgement:</strong> This app is based on Mesut Duman's work: 
        <a href="https://github.com/mesutdmn/Autonomous-Multi-Agent-Systems-with-CrewAI-Essay-Writer/tree/main" 
           target="_blank" style="color: #007BFF; text-decoration: none;">
           CrewAI Essay Writer
        </a>
    </div>
    """,
    unsafe_allow_html=True,
)