import streamlit as st
from io import BytesIO
from datetime import datetime

# Assuming these are correctly defined and accessible
from utils.pdf_utils import extract_text
from clients.azure_client import AzureClient
from clients.gemini_client import GeminiClient

from agents.tariff_agent import TariffTradeAgent
from agents.sales_agent import SalesAgent
from agents.supply_chain_agent import SupplyChainAgent
from agents.overall_agent import OverallAgent
from agents.enhanced_chat_agent import EnhancedChatAgent

def analyze_documents(mode, agent, processed_files, sess, custom_prompt=None):
    
    # Process individual files
    for filename, file_bytes in sess['uploaded_files'].items():
        if filename not in processed_files:
            try:
                file_obj = BytesIO(file_bytes)
                file_obj.name = filename
                text = extract_text(file_obj)
                if text:
                    if mode == "overall":
                        topics = agent.analyze_document(text, custom_prompt)
                    else:
                        topics = agent.analyze_document(text, custom_prompt) # Pass custom_prompt to other agents too
                    processed_files[filename] = {
                        "text": text,
                        "topics": topics,
                        "context": text,
                    }
                    st.toast(f"✅ Processed {filename}")
                else:
                    st.error(f"❌ Failed to extract text for {filename}")
            except Exception as e:
                st.error(f"Error processing {filename}: {str(e)}")

    # Generate consolidated summary
    if mode == "overall":
        summary = agent.generate_consolidated_summary_from_topics(processed_files, custom_prompt)
    else:
        summary = agent.generate_consolidated_summary_from_topics(processed_files, custom_prompt) # Pass custom_prompt
    
    if mode == "overall":
        sess['consolidated_summary_overall'] = summary
    elif mode == "tariff":
        sess['consolidated_summary_tariff'] = summary
    elif mode == "sales":
        sess['consolidated_summary_sales'] = summary
    elif mode == "supplychain":
        sess['consolidated_summary_supplychain'] = summary

    sess['last_analysis_mode'] = mode
    sess['active_file'] = None
    sess['active_topic'] = None
    st.success(f"Analysis and summary generated for {mode.replace('supplychain', 'supply chain')}.")

def main():
    st.set_page_config(page_title="Macy's Document Analysis Pro", layout="wide")
    st.title("📄 Macy's Document Analysis & Chat Tool")

    # Mode selection
    provider_select = st.radio("Select AI Provider", ["Azure GPT", "Google Gemini"])

    # Session Initialization
    if "session" not in st.session_state:
        st.session_state.session = {
            'uploaded_files': {},
            'processed_files_overall': {},
            'processed_files_tariff': {},
            'processed_files_sales': {},
            'processed_files_supplychain': {},
            'active_file': None,
            'active_topic': None,
            'topic_details_cache': {},
            'chat_history': [],
            'consolidated_summary_overall': None,
            'consolidated_summary_tariff': None,
            'consolidated_summary_sales': None,
            'consolidated_summary_supplychain': None,
            'last_analysis_mode': None,
            'custom_prompt_enabled': {}, # New: To track if custom prompt is enabled for each mode
            'custom_prompt_text': {}     # New: To store custom prompt text for each mode
        }

    if "client" not in st.session_state or st.session_state.get("provider") != provider_select:
        if provider_select == "Azure GPT":
            st.session_state.client = AzureClient()
            is_azure = True
        else:
            st.session_state.client = GeminiClient()
            is_azure = False

        # Initialize agents
        st.session_state.agent_overall = OverallAgent(st.session_state.client, is_azure)
        st.session_state.agent_tariff = TariffTradeAgent(st.session_state.client, is_azure)
        st.session_state.agent_sales = SalesAgent(st.session_state.client, is_azure)
        st.session_state.agent_supplychain = SupplyChainAgent(st.session_state.client, is_azure)
        st.session_state.chat_agent = EnhancedChatAgent(st.session_state.client, is_azure)
        st.session_state.provider = provider_select

    sess = st.session_state.session

    # --- File Upload ---
    st.subheader("1. Upload Documents")
    uploaded_files = st.file_uploader(
        "Upload PDF documents",
        type=["pdf"],
        accept_multiple_files=True,
        key="file_uploader",
    )
    if uploaded_files:
        new_files_added = False
        for file in uploaded_files:
            if file.name not in sess['uploaded_files']:
                sess['uploaded_files'][file.name] = file.getvalue()
                new_files_added = True

        if new_files_added:
            with st.spinner("🔍 Analyzing new documents with Overall Agent..."):
                # Always run initial overall analysis for new files
                analyze_documents(
                    mode="overall",
                    agent=st.session_state.agent_overall,
                    processed_files=sess['processed_files_overall'],
                    sess=sess
                )

    # --- Custom Prompts & Analysis ---
    st.subheader("2. Custom Prompts & Analysis")
    
    # Initialize custom prompts in session state
    if 'custom_prompts' not in sess:
        sess['custom_prompts'] = {
            'overall': {
                'summary': OverallAgent.prompt_summary,
                'analyze': OverallAgent.prompt_analyze,
                'detail': OverallAgent.prompt_detail
            },
            'tariff': {
                'summary': TariffTradeAgent.prompt_summary,
                'analyze': TariffTradeAgent.prompt_analyze,
                'detail': TariffTradeAgent.prompt_detail
            },
            'sales': {
                'summary': SalesAgent.prompt_summary,
                'analyze': SalesAgent.prompt_analyze,
                'detail': SalesAgent.prompt_detail
            },
            'supplychain': {
                'summary': SupplyChainAgent.prompt_summary,
                'analyze': SupplyChainAgent.prompt_analyze,
                'detail': SupplyChainAgent.prompt_detail
            }
        }
    
    # Create tabs for each agent's custom prompts
    tab_overall, tab_tariff, tab_sales, tab_supply = st.tabs([
        "📑 Overall", "🔍 Tariff", "📈 Sales", "🚚 Supply Chain"
    ])
    
    # Store which mode we're generating for
    generate_mode = None
    
    with tab_overall:
        st.subheader("Overall Prompts")
        use_custom = st.checkbox("✏️ Use Custom Prompts", key="custom_overall")
        
        if use_custom:
            sess['custom_prompts']['overall']['summary'] = st.text_area(
                "Summary Prompt:",
                value=sess['custom_prompts']['overall']['summary'],
                height=150,
                key="overall_prompt_summary"
            )
            sess['custom_prompts']['overall']['analyze'] = st.text_area(
                "Analysis Prompt:",
                value=sess['custom_prompts']['overall']['analyze'],
                height=150,
                key="overall_prompt_analyze"
            )
            sess['custom_prompts']['overall']['detail'] = st.text_area(
                "Detail Prompt:",
                value=sess['custom_prompts']['overall']['detail'],
                height=150,
                key="overall_prompt_detail"
            )
            
            if st.button("🔄 Generate with Custom Prompts", key="generate_overall"):
                generate_mode = "overall"
    
    with tab_tariff:
        st.subheader("Tariff Prompts")
        use_custom = st.checkbox("✏️ Use Custom Prompts", key="custom_tariff")
        
        if use_custom:
            sess['custom_prompts']['tariff']['summary'] = st.text_area(
                "Summary Prompt:",
                value=sess['custom_prompts']['tariff']['summary'],
                height=150,
                key="tariff_prompt_summary"
            )
            sess['custom_prompts']['tariff']['analyze'] = st.text_area(
                "Analysis Prompt:",
                value=sess['custom_prompts']['tariff']['analyze'],
                height=150,
                key="tariff_prompt_analyze"
            )
            sess['custom_prompts']['tariff']['detail'] = st.text_area(
                "Detail Prompt:",
                value=sess['custom_prompts']['tariff']['detail'],
                height=150,
                key="tariff_prompt_detail"
            )
            
            if st.button("🔄 Generate with Custom Prompts", key="generate_tariff"):
                generate_mode = "tariff"
    
    with tab_sales:
        st.subheader("Sales Prompts")
        use_custom = st.checkbox("✏️ Use Custom Prompts", key="custom_sales")
        
        if use_custom:
            sess['custom_prompts']['sales']['summary'] = st.text_area(
                "Summary Prompt:",
                value=sess['custom_prompts']['sales']['summary'],
                height=150,
                key="sales_prompt_summary"
            )
            sess['custom_prompts']['sales']['analyze'] = st.text_area(
                "Analysis Prompt:",
                value=sess['custom_prompts']['sales']['analyze'],
                height=150,
                key="sales_prompt_analyze"
            )
            sess['custom_prompts']['sales']['detail'] = st.text_area(
                "Detail Prompt:",
                value=sess['custom_prompts']['sales']['detail'],
                height=150,
                key="sales_prompt_detail"
            )
            
            if st.button("🔄 Generate with Custom Prompts", key="generate_sales"):
                generate_mode = "sales"
    
    with tab_supply:
        st.subheader("Supply Chain Prompts")
        use_custom = st.checkbox("✏️ Use Custom Prompts", key="custom_supply")
        
        if use_custom:
            sess['custom_prompts']['supplychain']['summary'] = st.text_area(
                "Summary Prompt:",
                value=sess['custom_prompts']['supplychain']['summary'],
                height=150,
                key="supply_prompt_summary"
            )
            sess['custom_prompts']['supplychain']['analyze'] = st.text_area(
                "Analysis Prompt:",
                value=sess['custom_prompts']['supplychain']['analyze'],
                height=150,
                key="supply_prompt_analyze"
            )
            sess['custom_prompts']['supplychain']['detail'] = st.text_area(
                "Detail Prompt:",
                value=sess['custom_prompts']['supplychain']['detail'],
                height=150,
                key="supply_prompt_detail"
            )
            
            if st.button("🔄 Generate with Custom Prompts", key="generate_supplychain"):
                generate_mode = "supplychain"

    # --- Analysis Buttons ---
    st.subheader("Quick Analysis")
    col0, col1, col2, col3 = st.columns(4)
    analyze_overall = col0.button("📑 Overall Summary")
    analyze_tariff = col1.button("🔍 Analyze Tariffs")
    analyze_sales = col2.button("📈 Analyze Sales")
    analyze_supplychain = col3.button("🚚 Supply Chain")

    # Handle generation requests
    if generate_mode or analyze_overall or analyze_tariff or analyze_sales or analyze_supplychain:
        if not sess['uploaded_files']:
            st.error("Please upload documents first.")
            st.stop()

        mode = generate_mode or (
            "overall" if analyze_overall else
            "tariff" if analyze_tariff else
            "sales" if analyze_sales else
            "supplychain" if analyze_supplychain else None
        )
        
        agent = None
        processed_files = None

        if mode == "overall":
            agent = st.session_state.agent_overall
            processed_files = sess['processed_files_overall']
        elif mode == "tariff":
            agent = st.session_state.agent_tariff
            processed_files = sess['processed_files_tariff']
        elif mode == "sales":
            agent = st.session_state.agent_sales
            processed_files = sess['processed_files_sales']
        elif mode == "supplychain":
            agent = st.session_state.agent_supplychain
            processed_files = sess['processed_files_supplychain']

        # Update agent with custom prompts if used
        if generate_mode:
            agent.prompt_summary = sess['custom_prompts'][mode]['summary']
            agent.prompt_analyze = sess['custom_prompts'][mode]['analyze']
            agent.prompt_detail = sess['custom_prompts'][mode]['detail']
            st.toast(f"Using custom prompts for {mode} analysis")
        else:
            # Reset to default prompts
            if mode == "overall":
                agent.prompt_summary = OverallAgent.prompt_summary
                agent.prompt_analyze = OverallAgent.prompt_analyze
                agent.prompt_detail = OverallAgent.prompt_detail
            elif mode == "tariff":
                agent.prompt_summary = TariffTradeAgent.prompt_summary
                agent.prompt_analyze = TariffTradeAgent.prompt_analyze
                agent.prompt_detail = TariffTradeAgent.prompt_detail
            elif mode == "sales":
                agent.prompt_summary = SalesAgent.prompt_summary
                agent.prompt_analyze = SalesAgent.prompt_analyze
                agent.prompt_detail = SalesAgent.prompt_detail
            elif mode == "supplychain":
                agent.prompt_summary = SupplyChainAgent.prompt_summary
                agent.prompt_analyze = SupplyChainAgent.prompt_analyze
                agent.prompt_detail = SupplyChainAgent.prompt_detail

        with st.spinner(f"🔍 Analyzing {mode.replace('supplychain', 'supply chain')} documents..."):
            analyze_documents(
                mode, 
                agent, 
                processed_files, 
                sess
            )

    # ... rest of the code (main display, topic analysis, chat interface) ...
            # After analysis, ensure the display mode is correctly set for the next render
            sess['last_analysis_mode'] = mode
            st.rerun() # Rerun to refresh UI after analysis and prompt updates

    # --- Main Display ---
    last_mode = sess['last_analysis_mode']
    if last_mode is None:
        st.info("Select an analysis type to begin.")
        return

    # Consolidated data setup
    mode_config = {
        'overall': {
            'files': sess['processed_files_overall'],
            'summary': sess['consolidated_summary_overall'],
            'sidebar_header': "Overall Topics",
            'main_header': "🌟 Executive Summary",
            'agent': st.session_state.agent_overall
        },
        'tariff': {
            'files': sess['processed_files_tariff'],
            'summary': sess['consolidated_summary_tariff'],
            'sidebar_header': "Tariff Topics",
            'main_header': "🌟 Tariff Analysis",
            'agent': st.session_state.agent_tariff
        },
        'sales': {
            'files': sess['processed_files_sales'],
            'summary': sess['consolidated_summary_sales'],
            'sidebar_header': "Sales Topics",
            'main_header': "🌟 Sales Analysis",
            'agent': st.session_state.agent_sales
        },
        'supplychain': {
            'files': sess['processed_files_supplychain'],
            'summary': sess['consolidated_summary_supplychain'],
            'sidebar_header': "Supply Chain Topics",
            'main_header': "🌟 Supply Chain Analysis",
            'agent': st.session_state.agent_supplychain
        }
    }

    current_mode = mode_config[last_mode]

    # --- Sidebar Topics ---
    st.sidebar.header(current_mode['sidebar_header'])

    if last_mode == "overall":
        topics_by_file = {}
        for filename, filedata in current_mode['files'].items():
            for topic in filedata["topics"]:
                topics_by_file.setdefault(topic['name'], []).append({
                    'file': filename,
                    'score': topic['score']
                })

        a = sorted(topics_by_file.items(),
                                                key=lambda x: max(x[1], key=lambda y: y['score'])['score'],
                                                reverse=True)
        before_view_more , after_view_more = a[:3] , a[3:]

        for topic_name, occurrences in before_view_more:
            total_score = sum(occ['score'] for occ in occurrences)
            file_count = len(occurrences)
            btn_label = f"{topic_name} (📈 {total_score:.1f} | 📑 {file_count})"

            if st.sidebar.button(
                btn_label,
                key=f"overall_topic_{topic_name}",
                use_container_width=True,
            ):
                sess['active_topic'] = topic_name
                sess['active_file'] = None

        if st.sidebar.button('View More',key = '1234' , use_container_width=True):
            for topic_name, occurrences in after_view_more:
                total_score = sum(occ['score'] for occ in occurrences)
                file_count = len(occurrences)
                btn_label = f"{topic_name} (📈 {total_score:.1f} | 📑 {file_count})"

                if st.sidebar.button(
                    btn_label,
                    key=f"overall_topic_more_{topic_name}", # Changed key to avoid collision
                    use_container_width=True,
                ):
                    sess['active_topic'] = topic_name
                    sess['active_file'] = None

    else: # For Tariff, Sales, Supply Chain modes
        for filename, filedata in current_mode['files'].items():
            expanded = (filename == sess['active_file'])
            with st.sidebar.expander(f"📄 {filename}", expanded=expanded):
                topics = sorted(filedata["topics"], key=lambda t: t["score"], reverse=True)
                for topic in topics[:3]:
                    is_selected = (
                        sess['active_file'] == filename and sess['active_topic'] == topic['name']
                    )
                    style = "primary" if is_selected else "secondary"

                    if st.button(
                        f"• {topic['name']} (Score: {topic['score']})",
                        key=f"{last_mode}_topic_{filename}_{topic['name']}",
                        type=style,
                        use_container_width=True,
                    ):
                        sess['active_file'] = filename
                        sess['active_topic'] = topic['name']

                if len(topics) > 3 and st.sidebar.button(f'View More for {filename}',key = f'{filename}_view_more' ,use_container_width=True):
                    for topic in topics[3:]:
                        is_selected = (
                            sess['active_file'] == filename and sess['active_topic'] == topic['name']
                        )
                        style = "primary" if is_selected else "secondary"

                        if st.button(
                            f"• {topic['name']} (Score: {topic['score']})",
                            key=f"{last_mode}_topic_more_{filename}_{topic['name']}", # Changed key
                            type=style,
                            use_container_width=True,
                        ):
                            sess['active_file'] = filename
                            sess['active_topic'] = topic['name']

    # --- Topic Analysis ---
    st.subheader("Detailed Analysis")
    if last_mode == "overall" and sess['active_topic']:
        mentions = []
        for filename, filedata in current_mode['files'].items():
            for topic in filedata["topics"]:
                if topic['name'] == sess['active_topic']:
                    mentions.append({
                        'file': filename,
                        'summary': topic.get('summary', ''),
                        'score': topic['score'],
                        'context': filedata['context']
                    })

        with st.expander("📊 Topic Prevalence"):
            cols = st.columns(3)
            cols[0].metric("Total Documents", len(mentions))
            avg_relevance = (sum(m['score'] for m in mentions)/len(mentions)) if mentions else 0
            cols[1].metric("Average Relevance", f"{avg_relevance:.1f}")
            cols[2].metric("First Mentioned", mentions[0]['file'] if mentions else "N/A")

        if mentions:
            combined_context = "\n\n".join(f"=== {m['file']} ===\n{m['context']}" for m in mentions)
            key_cache = (last_mode, sess['active_topic'])
            if key_cache in sess['topic_details_cache']:
                st.markdown(sess['topic_details_cache'][key_cache])
            else:
                placeholder = st.empty()
                collected_text = ""
                try:
                    for chunk in current_mode['agent'].generate_topic_detail(combined_context, sess['active_topic']):
                        collected_text = chunk
                        placeholder.markdown(collected_text + (" ▌" if "▌" in collected_text else ""))
                    sess['topic_details_cache'][key_cache] = collected_text
                except Exception as e:
                    st.error(f"Analysis error: {str(e)}")
    elif sess['active_file'] and sess['active_topic']:
        key_cache = (last_mode, sess['active_file'], sess['active_topic'])
        if key_cache in sess['topic_details_cache']:
            st.markdown(sess['topic_details_cache'][key_cache])
        else:
            placeholder = st.empty()
            collected_text = ""
            try:
                for chunk in current_mode['agent'].generate_topic_detail(
                    current_mode['files'][sess['active_file']]['context'],
                    sess['active_topic'],
                ):
                    collected_text = chunk
                    placeholder.markdown(collected_text + (" ▌" if "▌" in collected_text else ""))
                sess['topic_details_cache'][key_cache] = collected_text
            except Exception as e:
                st.error(f"Analysis error: {str(e)}")
    else:
        st.info("Select a topic from the sidebar")

    st.markdown("---")

    # --- Consolidated Summary ---
    st.header(current_mode['main_header'])
    if current_mode['summary']:
        st.markdown(current_mode['summary'])
    else:
        st.info("Summary not available yet")

    st.divider()

    # --- Chat Interface ---
    st.subheader("💬 Document Chat")
    
    # File selection
    available_files = list(current_mode['files'].keys())
    selected_files = st.multiselect(
        "Select documents for context:",
        available_files,
        key=f"chat_selector_{last_mode}"
    )

    # Chat history
    for msg in sess['chat_history']:
        with st.chat_message(msg["role"]):
            st.markdown(msg["content"])

    # Question handling
    question = st.chat_input("Ask about the documents...")
    if question:
        if not selected_files:
            st.error("Please select documents first")
            st.stop()

        sess['chat_history'].append({
            "role": "user",
            "content": question,
            "timestamp": datetime.utcnow().isoformat(),
        })

        try:
            context = "\n\n".join([
                f"=== {fname} ===\n{current_mode['files'][fname]['context']}"
                for fname in selected_files
            ])

            with st.chat_message("assistant"):
                response_placeholder = st.empty()
                full_response = ""
                q_type = None
                
                # Ensure custom_prompt_text_for_mode is available here if needed for chat_agent
                # For now, it's used only for analysis in analyze_documents, adjust if chat_agent needs it.
                for chunk, q_type in st.session_state.chat_agent.generate_answer(question, context):
                    full_response = chunk
                    response_placeholder.markdown(full_response + " ▌")
                
                response_placeholder.markdown(full_response)
                
                sess['chat_history'].append({
                    "role": "assistant",
                    "content": full_response,
                    "timestamp": datetime.utcnow().isoformat(),
                    "analysis_type": q_type
                })

        except Exception as e:
            st.error(f"Chat error: {str(e)}")
            sess['chat_history'].append({
                "role": "assistant",
                "content": f"Error: {str(e)}",
                "timestamp": datetime.utcnow().isoformat(),
            })

    # Reset button
    if st.button("🔄 Reset Session", type="secondary"):
        # Preserve long-lived objects like client and agents to avoid overhead on re-init
        preserved_keys = [
            "client", "agent_overall", "agent_tariff",
            "agent_sales", "agent_supplychain", "chat_agent", "provider"
        ]
        preserved = {k: st.session_state[k] for k in preserved_keys if k in st.session_state}
        
        # Clear entire session state
        st.session_state.clear()
        
        # Restore preserved keys back
        st.session_state.update(preserved)

        # Reset session-specific stored data completely
        st.session_state.session = {
            'uploaded_files': {},
            'processed_files_overall': {},
            'processed_files_tariff': {},
            'processed_files_sales': {},
            'processed_files_supplychain': {},
            'active_file': None,
            'active_topic': None,
            'topic_details_cache': {},
            'chat_history': [],
            'consolidated_summary_overall': None,
            'consolidated_summary_tariff': None,
            'consolidated_summary_sales': None,
            'consolidated_summary_supplychain': None,
            'last_analysis_mode': None,
            'custom_prompt_enabled': {},
            'custom_prompt_text': {}
        }
        
        # Trigger a rerun for fresh UI without old content
        st.rerun()

if __name__ == "__main__":
    main()

this is my code for main.py

from utils.pdf_utils import parse_topics

class BaseAgent:
    def __init__(self, client, is_azure):
        self.client = client
        self.is_azure = is_azure

    def analyze_document(self, prompt_system, prompt_user, text):
        if self.is_azure:
            messages = [
                {"role": "system", "content": prompt_system},
                {"role": "user", "content": prompt_user + "\n\n" + text},
            ]
            response = self.client.generate(messages=messages, temperature=0)
            raw_text = response.choices[0].message.content.strip()
        else:
            raw_text = self.client.generate(prompt_system, prompt_user + "\n\n" + text)
        return parse_topics(raw_text)

    def generate_consolidated_summary_from_topics(self, prompt_system, prompt_user_template, processed_files):
        topics_block = ""
        for filename, filedata in processed_files.items():
            topics_block += f"### Topics from document: {filename}\n"
            for topic in sorted(filedata["topics"], key=lambda x: x["score"], reverse=True):
                topics_block += f"- **{topic['name']}**: {topic['summary']} (Relevance: {topic['score']})\n"
            topics_block += "\n"

        prompt_user = prompt_user_template.format(topics_block=topics_block)

        if self.is_azure:
            messages = [
                {"role": "system", "content": prompt_system},
                {"role": "user", "content": prompt_user},
            ]
            response = self.client.generate(messages=messages, temperature=0)
            return response.choices[0].message.content.strip()
        else:
            return self.client.generate(prompt_system, prompt_user)

    def generate_topic_detail(self, prompt_system, prompt_user_template, document_text, topic):
        prompt_user = prompt_user_template.format(text=document_text, topic=topic)
        if self.is_azure:
            messages = [
                {"role": "system", "content": prompt_system},
                {"role": "user", "content": prompt_user},
            ]
            response = self.client.generate(messages=messages, temperature=0, stream=True)
            
            collected_chunks = []
            for chunk in response:
                if hasattr(chunk, "choices") and chunk.choices:
                    delta = chunk.choices[0].delta
                    content = getattr(delta, "content", "")
                    if content:
                        collected_chunks.append(content)
                        yield "".join(collected_chunks) + "▌"
            
            # Final yield without cursor
            if collected_chunks:
                yield "".join(collected_chunks)
        else:
            # For Gemini, we'll simulate streaming with 3 chunks
            full_response = self.client.generate(prompt_system, prompt_user)
            chunks = self.preserve_formatting_chunks(full_response)
            
            accumulated = ""
            for chunk in chunks:
                accumulated += chunk
                yield accumulated + "▌"
            
            yield accumulated  # Final yield without cursor
    
    def preserve_formatting_chunks(self, text):
        """Split response while preserving Markdown formatting"""
        # Split by paragraphs first
        paragraphs = text.split('\n\n')
        
        chunks = []
        for para in paragraphs:
            if para.startswith('##') or para.startswith('###') or para.startswith('* '):
                # Preserve headers and lists as whole chunks
                chunks.append(para + '\n\n')
            else:
                # Split long paragraphs into sentences
                sentences = para.split('. ')
                current_chunk = ""
                for sentence in sentences:
                    if not sentence:
                        continue
                    if len(current_chunk) + len(sentence) > 150:
                        if current_chunk:
                            chunks.append(current_chunk.strip() + '. ')
                        current_chunk = sentence
                    else:
                        current_chunk += sentence + '. '
                if current_chunk:
                    chunks.append(current_chunk.strip() + '\n\n')
        
        return chunks


            

this is my base_agent.py


from agents.base_agent import BaseAgent

class TariffTradeAgent(BaseAgent):
    prompt_sys = "Tariff and trade policy analyst for Macy's CEO works for only provided documents"
    
     # Universal formatting enforcement line
    formatting_directive = """Please follow these formatting guidelines:
1. **No Combined Elements**: Always space-separate numbers/words/units (3.3 billion not 3.3billion)
2. **Time Formatting**: Q4 2024 (never Q42024 or 4th quarter)
3. **Number Rules**: 
   - 3.3B → 3.3 billion
   - 150.2M → 150.2 million
   - 0.33 → keep exact decimal
4. **Text Integrity**: 
   - "net income" never "netincome"
   - "year-over-year" never "YOY" or "yearoveryear"
5. **Style Prohibition**: Do not make any word in Italic or any other format always make it in one format
6. **Bad Example**: 3.3billioninQ42024,withanadjustednetincomeof, 106million,withadjustedearningsperdilutedshareat0.95 → REJECTED
7. **ALWAYS Required Format**: 3.3 billion in Q4 2024, with an adjusted net income of → ACCEPTED

APPLY THESE RULES TO ALL NUMERICAL MENTIONS AND SENTENCE STRUCTURES."""
    
    prompt_analyze = """
You are a senior tariff and international trade policy analyst assisting a research team working for the CEO of Macy's.  
You have received a transcript/document from another company.  

Carefully identify all significant tariff, trade, and related government policy topics and detailed briefing in the text of all files that could affect Macy's business operations, including supply chain, procurement, retail sales, and technology.

For each topic, provide:  
- A clear and concise topic name (e.g., "Vietnam Production Impact", "US-China Tariffs").  
- A brief describing in 200 words including its operational or strategic impact on Macy's retail business, considering the external company's context also include A clear overview of the topic, Key insights and any relevant direct excerpts from the document, Important figures, dates, or timelines if available, Detailed analysis on how this topic could impact Macy's retail operations, supply chain, procurement, and consumer behavior.  
- A relevance score from 1 (minor) to 10 (critical).  
* For every topic, ALWAYS provide verbatim source excerpts under the heading "Source Truth" as follows:
        - For each document where the topic appears, extract the exact, unmodified sentence(s) or paragraph(s) from the original document. 
        - Format each excerpt as: **Source Truth:** "Exact text from the document..." (Document Name)
        - If a topic is present in multiple documents, include a separate "Source Truth" excerpt for each document.
        - Do NOT paraphrase, summarize, or alter the original text in any way. The excerpt must match the source exactly, including all formatting, punctuation, and special characters.
        - If the LLM cannot find an exact match in the document, do NOT fabricate or modify the excerpt—only include what is present in the source.

Format your response as one topic per line in the format from all files:  
- Topic Name: Summary [Relevance Score]

Example:  
- Vietnam Factory Shutdown: Supply chain delays expected due to production halt in Vietnam [9]  
- Tariff Changes on Apparel: Increased costs on imports from China may raise prices [8]

Analyze the following external company document for all relevant tariff and trade topics. Text:""" + formatting_directive 

    prompt_summary = """
You are a senior tariff and trade analyst preparing a consolidated tariff and trade policy report for Macy's executive team from all document provided.

You have reviewed tariff and trade topics extracted from multiple external company documents. These topics include their names, summaries, and relevance scores. Based on their content, please:

1. **OverView**: Identify and describe from all documents all their impactful tariff, trade, and related government policy topics that could affect Macy's business operations, including supply chain, procurement, retail sales, and technology.
2. For each topic:
   * Provide a concise summary from combining all the documents.
   * Include relevant examples, numerical data, or timelines from the documents also provide from which document it is taken.
   * Explain operational and strategic impacts—positive, negative, or neutral—specifically tailored to Macy's retail business.
   * Provide 3-5 actionable strategic recommendations for Macy's leadership.
   * For every topic, ALWAYS provide each verbatim source excerpts under the heading "Ground Truth" as follows:
        - For each document where the topic appears, extract the exact, unmodified sentence(s) or paragraph(s) from the original document. 
        - Format each excerpt as: **Ground Truth:** "Exact text from the document..." (Document Name)
        - If a topic is present in multiple documents, include a separate "Ground Truth" excerpt for each document with proper line breaks.
        - Do NOT paraphrase, summarize, or alter the original text in any way. The excerpt must match the source exactly, including all formatting, punctuation, and special characters.
        - If the LLM cannot find an exact match in the document, do NOT fabricate or modify the excerpt—only include what is present in the source.
  
3. Format in clear markdown with sections in black text with proper headings:
    * Executive Summary
    * Key Themes
    * Strategic Recommendations
    * Risk Assessment
4. Avoid jargon and focus on practical operational impacts and strategy insights.

Format your response in markdown with clear headings for each topic.

Use the following Documents Analysis Data to combine similar topics from different documents and provide a comprehensive summary:
{topics_block}

Deliver a detailed, synthesized, and actionable consolidated tariff and trade policy report for Macy's.""" + formatting_directive 

    prompt_detail = """
You are preparing a detailed briefing for Macy's CEO on the tariff and trade policy topic '{topic}', based on the provided external company document.

Provide:
1. A clear overview of the topic.
2. Allways Provide Key insights and relevant excerpts.- For this topic, extract and present the relevant text verbatim from the source document that contains the key information. Ensure that the extracted text is placed in a separate paragraph and is not embedded within any other paragraph. Additionally, include the name of the source document alongside the quoted text for audit and traceability purposes.
3. Important figures, dates, or timelines if available.
4. Detailed analysis on how this topic could impact Macy's retail operations, supply chain, procurement, and consumer behavior.
5. 3-5 actionable strategic recommendations for Macy's leadership.
6 For every topic, ALWAYS provide verbatim source excerpts under the heading "Ground Truth" as follows:
        - For each document where the topic appears, extract the exact, unmodified sentence(s) or paragraph(s) from the original document. 
        - Format each excerpt as: **Ground Truth:** "Exact text from the document..." (Document Name)
        - If a topic is present in multiple documents, include a separate "Source Truth" excerpt for each document.
        - Do NOT paraphrase, summarize, or alter the original text in any way. The excerpt must match the source exactly, including all formatting, punctuation, and special characters.
        - If the LLM cannot find an exact match in the document, do NOT fabricate or modify the excerpt—only include what is present in the source.


Document:
{text}

Topic: {topic}

Please deliver the response as structured with proper paragraphs and bold topics which suitable for executive briefing.""" + formatting_directive 

    def analyze_document(self, text, custom_prompt=None):
        prompt_analyze = custom_prompt if custom_prompt else self.prompt_analyze
        return super().analyze_document(self.prompt_sys, prompt_analyze, text)

    def generate_consolidated_summary_from_topics(self, processed_files, custom_prompt=None):
        prompt_summary = custom_prompt if custom_prompt else self.prompt_summary
        return super().generate_consolidated_summary_from_topics(self.prompt_sys, prompt_summary, processed_files)

    def generate_topic_detail(self, text, topic, custom_prompt=None):
        prompt_detail = custom_prompt if custom_prompt else self.prompt_detail
        return super().generate_topic_detail(self.prompt_sys, prompt_detail, text, topic)

this is my tariff agent



what i want each transcript have some question and answer i need a seprtae tab same like summarise or tariff which are the question asked make it formal from each transript with good views from all file display them