File size: 12,427 Bytes
41dbcc2
0bff4c5
 
f6673c4
b8aec8c
0bff4c5
 
476a797
b8aec8c
476a797
 
0bff4c5
476a797
7c2e67d
6ba91d3
41dbcc2
0bff4c5
476a797
 
 
 
b8aec8c
41dbcc2
 
b8aec8c
7c2e67d
0bff4c5
476a797
0bff4c5
 
476a797
0bff4c5
476a797
 
b8aec8c
476a797
 
b8aec8c
7c2e67d
476a797
 
 
 
 
 
 
 
 
 
b8aec8c
476a797
 
 
 
b8aec8c
476a797
7c2e67d
476a797
 
b8aec8c
0bff4c5
476a797
b8aec8c
0bff4c5
b8aec8c
476a797
b8aec8c
0bff4c5
476a797
 
 
 
 
 
 
 
b8aec8c
41dbcc2
476a797
 
 
 
 
0bff4c5
 
476a797
41dbcc2
476a797
 
7c2e67d
476a797
 
 
 
7c2e67d
476a797
b8aec8c
476a797
 
 
 
 
 
 
 
 
 
 
6ba91d3
476a797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0bff4c5
476a797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f6673c4
476a797
b8aec8c
0bff4c5
476a797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6ba91d3
476a797
 
6ba91d3
476a797
f6673c4
476a797
 
 
0bff4c5
476a797
 
 
 
 
 
 
 
0bff4c5
476a797
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# /home/user/app/pages/3_Reports.py
import streamlit as st
from datetime import datetime
from typing import List, Dict, Any
from sqlmodel import select

from config.settings import settings
from models import ChatMessage, ChatSession # SQLModel classes for DB query
from models.db import get_session_context
# Import generate_pdf_report AND MockChatMessage from services.pdf_report
from services.pdf_report import generate_pdf_report, MockChatMessage
from services.logger import app_logger
from services.metrics import log_report_generated # Assuming this function exists

# --- Authentication Check ---
if not st.session_state.get("authenticated_user_id"):
    st.warning("Please log in to access reports.")
    try:
        st.switch_page("app.py")
    except st.errors.StreamlitAPIException:
        st.info("Please navigate to the main login page manually.")
    st.stop()

authenticated_user_id = st.session_state.get("authenticated_user_id")
authenticated_username = st.session_state.get("authenticated_username", "User")
app_logger.info(f"User '{authenticated_username}' (ID: {authenticated_user_id}) accessed Reports page.")

# --- Page Title and Info ---
st.title("Consultation Reports")
st.markdown("View and download your past consultation sessions.")
st.info(f"{settings.MAIN_DISCLAIMER_SHORT} PDFs are summaries for review.")

# --- Helper Function to Load User's Chat Session Display Data ---
# @st.cache_data(ttl=300, show_spinner=False) # Consider caching if fetching is slow and data doesn't change too rapidly
def get_user_chat_session_display_data(user_id: int) -> List[Dict[str, Any]]:
    """Fetches essential data for chat sessions (ID, title, start_time, context) as dictionaries."""
    app_logger.debug(f"ReportsPage: Fetching session display data for user_id: {user_id}")
    session_data_list: List[Dict[str, Any]] = []
    try:
        with get_session_context() as db_session:
            statement = select(
                ChatSession.id,
                ChatSession.title,
                ChatSession.start_time,
                ChatSession.patient_context_summary # Fetch this as well
            ).where(ChatSession.user_id == user_id).order_by(ChatSession.start_time.desc())
            
            results = db_session.exec(statement).all() # List of Row objects
            for row_item in results:
                session_data_list.append({
                    "id": row_item.id,
                    "title": row_item.title,
                    "start_time": row_item.start_time, # datetime object
                    "patient_context_summary": row_item.patient_context_summary
                })
        app_logger.debug(f"ReportsPage: Found {len(session_data_list)} session display entries for user {user_id}")
    except Exception as e:
        app_logger.error(f"ReportsPage: Error fetching session display data for user {user_id}: {e}", exc_info=True)
        st.error("Could not load your chat sessions. Please try again later.")
    return session_data_list

# Fetch session display data
chat_session_display_items = get_user_chat_session_display_data(authenticated_user_id)

if not chat_session_display_items:
    st.info("You have no past consultation sessions recorded to display.")
    st.stop()

# --- UI: Select a Session ---
session_options_for_selectbox = []
for s_data_item in chat_session_display_items:
    start_time = s_data_item.get("start_time")
    start_time_str = start_time.strftime('%Y-%m-%d %H:%M') if start_time else "Date N/A"
    title_str = s_data_item.get("title") or f"Consultation on {start_time_str}"
    display_text = f"ID: {s_data_item.get('id')} | Started: {start_time_str} | Title: {title_str}"
    session_options_for_selectbox.append((display_text, s_data_item.get('id'))) # (Display, Value)

selected_option_tuple = st.selectbox(
    "Select a Consultation Session:",
    options=session_options_for_selectbox,
    format_func=lambda x_tuple: x_tuple[0], # Show only the display string
    index=0, # Default to the first (most recent) session
    key="report_session_selector"
)

# --- Display Details and PDF Download for Selected Session ---
if selected_option_tuple:
    selected_session_id_val = selected_option_tuple[1] # The actual session ID
    app_logger.info(f"ReportsPage: User '{authenticated_username}' selected session ID: {selected_session_id_val} for viewing.")

    # Find the full data for the selected session from our fetched list of dicts
    selected_session_dict_data = next(
        (s_item for s_item in chat_session_display_items if s_item['id'] == selected_session_id_val), None
    )

    if selected_session_dict_data:
        st.markdown("---")
        st.subheader(f"Report Preview for Session ID: {selected_session_dict_data['id']}")

        session_start_time = selected_session_dict_data.get("start_time")
        start_time_display_detail = session_start_time.strftime('%Y-%m-%d %H:%M:%S UTC') if session_start_time else "Not recorded"
        st.write(f"**Started:** {start_time_display_detail}")
        st.write(f"**Title:** {selected_session_dict_data.get('title') or 'Untitled Session'}")

        patient_context_from_session = selected_session_dict_data.get("patient_context_summary")
        if patient_context_from_session:
            with st.expander("View Patient Context Provided for this Session", expanded=False):
                st.markdown(patient_context_from_session)
        
        # --- Fetch and Display Messages for the Selected Session ---
        # Store fetched messages in session_state to avoid re-fetching on every interaction within the page
        MESSAGES_DATA_SESS_KEY = f"report_page_messages_for_session_{selected_session_id_val}"

        if MESSAGES_DATA_SESS_KEY not in st.session_state:
            app_logger.info(f"ReportsPage: Fetching DB messages for session ID: {selected_session_id_val}")
            db_messages_as_dicts: List[Dict[str, Any]] = []
            try:
                with get_session_context() as db:
                    # Fetch specific columns needed for display and PDF
                    stmt = select(
                        ChatMessage.role, ChatMessage.content, ChatMessage.timestamp, ChatMessage.tool_name
                    ).where(ChatMessage.session_id == selected_session_id_val).order_by(ChatMessage.timestamp)
                    
                    message_results = db.exec(stmt).all() # List of Row objects
                    for msg_row in message_results:
                        db_messages_as_dicts.append({
                            "role": msg_row.role, "content": msg_row.content,
                            "timestamp": msg_row.timestamp, # datetime object
                            "tool_name": getattr(msg_row, 'tool_name', None)
                        })
                st.session_state[MESSAGES_DATA_SESS_KEY] = db_messages_as_dicts
                app_logger.info(f"ReportsPage: Fetched and stored {len(db_messages_as_dicts)} messages for session {selected_session_id_val} in st.session_state.")
            except Exception as e_msg_fetch:
                app_logger.error(f"ReportsPage: Error fetching DB messages for session {selected_session_id_val}: {e_msg_fetch}", exc_info=True)
                st.error("Could not load messages for this session's transcript.")
                st.session_state[MESSAGES_DATA_SESS_KEY] = [] # Store empty list on error
        else:
            app_logger.debug(f"ReportsPage: Using cached messages from st.session_state for session ID: {selected_session_id_val}")
        
        messages_to_display_and_pdf = st.session_state[MESSAGES_DATA_SESS_KEY]

        if messages_to_display_and_pdf:
            with st.expander("View Chat Transcript", expanded=False):
                for msg_idx, msg_dict_item in enumerate(messages_to_display_and_pdf):
                    msg_role = str(msg_dict_item.get("role", "N/A"))
                    msg_content = str(msg_dict_item.get("content", ""))
                    msg_timestamp_obj = msg_dict_item.get("timestamp")
                    
                    # Skip verbose system messages about context in transcript view
                    if msg_role == "system" and "Initial Patient Context Set:" in msg_content:
                        continue

                    icon_char = "πŸ§‘β€βš•οΈ" if msg_role == "assistant" else "πŸ‘€"
                    if msg_role == "tool": icon_char = "πŸ› οΈ"
                    if msg_role == "system": icon_char = "βš™οΈ"
                    
                    timestamp_str_display = msg_timestamp_obj.strftime('%Y-%m-%d %H:%M:%S') if msg_timestamp_obj else "N/A"
                    
                    st.markdown(f"**{icon_char} {msg_role.capitalize()}** ({timestamp_str_display})")
                    st.markdown(f"> ```\n{msg_content}\n```") # Using markdown code block for content
                    if msg_idx < len(messages_to_display_and_pdf) - 1:
                        st.markdown("---")
            
            # --- PDF Download Button ---
            st.markdown("---")
            try:
                # Prepare list of MockChatMessage instances for the PDF generator
                pdf_report_mock_messages: List[MockChatMessage] = []
                for msg_d_item in messages_to_display_and_pdf:
                    pdf_report_mock_messages.append(
                        MockChatMessage( # Use the imported MockChatMessage class
                            role=msg_d_item.get("role"),
                            content=msg_d_item.get("content"),
                            timestamp=msg_d_item.get("timestamp"),
                            tool_name=msg_d_item.get("tool_name")
                        )
                    )

                # Prepare the consolidated data dictionary for generate_pdf_report
                report_data_for_pdf_generation = {
                    "patient_name": authenticated_username, # This is the clinician's username
                    "session_id": selected_session_dict_data['id'],
                    "session_title": selected_session_dict_data.get('title') or 'Untitled Session',
                    "session_start_time": selected_session_dict_data.get('start_time'), # datetime object
                    "patient_context_summary": selected_session_dict_data.get('patient_context_summary', "Not provided."),
                    "messages": pdf_report_mock_messages # List of MockChatMessage instances
                }
                
                app_logger.debug(f"ReportsPage: Data for PDF generation (session {selected_session_id_val}): Keys={list(report_data_for_pdf_generation.keys())}, NumMessages={len(pdf_report_mock_messages)}")

                pdf_bytes_output = generate_pdf_report(report_data_for_pdf_generation)
                
                current_time_filename_str = datetime.now().strftime('%Y%m%d_%H%M%S')
                pdf_report_filename = f"Consultation_Report_S{selected_session_id_val}_{current_time_filename_str}.pdf"

                st.download_button(
                    label="Download Report as PDF",
                    data=pdf_bytes_output,
                    file_name=pdf_report_filename,
                    mime="application/pdf",
                    key=f"download_pdf_button_session_{selected_session_id_val}", # Unique key
                    on_click=log_report_generated,
                    args=(authenticated_user_id, selected_session_id_val), # Example args for metrics
                    help="Click to download a PDF summary of this consultation session."
                )
            except Exception as e_pdf_gen:
                app_logger.error(f"ReportsPage: Error generating PDF for session {selected_session_id_val} (User: '{authenticated_username}'): {e_pdf_gen}", exc_info=True)
                st.error(f"Could not generate PDF report at this time. Error: {type(e_pdf_gen).__name__}")
        else:
            st.info("This session has no messages recorded to include in the report.")
    else:
        app_logger.error(f"ReportsPage: Selected session ID {selected_session_id_val} not found in fetched display data for user '{authenticated_username}'. This is unexpected.")
        st.error("An error occurred: The selected session data could not be retrieved. Please try again or select another session.")
else:
    st.info("Please select a session from the dropdown menu above to view details and generate a report.")