# assistant_routes.py
from flask import Blueprint, request, jsonify, session, render_template
from models import (db, User, Case, CaseDocument, AnalysisJob, AnalysisResult,
                   SummarizationJob, SummarizationResult, AssistantConversation,
                   AssistantMessage)
from auth_routes import login_required, log_activity
import uuid
import openai
import os
import re
import logging
from datetime import datetime
from sqlalchemy import or_, and_, desc

# Configure logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

assistant_bp = Blueprint('assistant', __name__, url_prefix='/assistant')

# OpenAI will be initialized from app.config in parse_user_intent

def extract_context(text, search_term, context_chars=150):
    """Extract a snippet of text around the search term for context"""
    if not text or not search_term:
        return ""

    # Case-insensitive search
    text_lower = text.lower()
    term_lower = search_term.lower()

    # Find the position of the search term
    pos = text_lower.find(term_lower)
    if pos == -1:
        return ""

    # Calculate start and end positions for context
    start = max(0, pos - context_chars)
    end = min(len(text), pos + len(search_term) + context_chars)

    # Extract the snippet
    snippet = text[start:end]

    # Add ellipsis if we're not at the beginning or end
    if start > 0:
        snippet = "..." + snippet
    if end < len(text):
        snippet = snippet + "..."

    # Replace newlines with spaces for cleaner display
    snippet = ' '.join(snippet.split())

    return snippet

def extract_case_number(text):
    """Extract case number from text - handles various formats"""
    # Look for "case 1234", "case #1234", "case number 1234", etc.
    patterns = [
        r'case\s*#?\s*(\d+)',
        r'case\s*number\s*#?\s*(\d+)',
        r'#(\d+)',
        r'\b(\d{3,})\b'  # Any 3+ digit number as fallback
    ]

    for pattern in patterns:
        match = re.search(pattern, text.lower())
        if match:
            return match.group(1)
    return None

def extract_document_id(text):
    """Extract document ID from text"""
    patterns = [
        r'document\s*#?\s*(\d+)',
        r'doc\s*#?\s*(\d+)',
        r'file\s*#?\s*(\d+)',
    ]

    for pattern in patterns:
        match = re.search(pattern, text.lower())
        if match:
            return match.group(1)
    return None

def extract_filename(text):
    """Extract filename from text - looks for image/document filenames"""
    # Pattern for common file extensions - supports underscores, hyphens, dots, numbers
    # Matches: filename.pdf, my_file.docx, image-2024.jpg, etc.
    pattern = r'([a-zA-Z0-9_\-\.]+\.(jpg|jpeg|png|gif|pdf|docx|doc|txt|tif|tiff|bmp|webp))'

    # Find all matches
    matches = re.findall(pattern, text, re.IGNORECASE)

    if matches:
        # Filter out matches that are too short or are just the extension
        valid_matches = []
        for match in matches:
            filename = match[0]
            # Get the base name (without extension)
            base_name = filename.rsplit('.', 1)[0]

            # Skip if base name is too short or is a generic word
            if len(base_name) > 1 and not re.match(r'^(document|file|doc|image|picture|photo|img)$', base_name, re.IGNORECASE):
                valid_matches.append(filename)

        if valid_matches:
            # Return the longest match (most specific)
            return max(valid_matches, key=len)

        # If no valid matches, return first one anyway
        if matches:
            return matches[0][0]

    return None

def find_document_by_filename(user, filename, case_id=None):
    """Find a document by filename, optionally within a specific case"""
    print(f"DEBUG: Searching for filename='{filename}' for user_id={user.id}, company_id={user.company_id}")

    query = CaseDocument.query.join(Case)

    # Apply access control (admins see all)
    if not user.is_admin():
        if user.is_company_admin():
            query = query.filter(Case.company_id == user.company_id)
        else:
            query = query.filter(
                or_(
                    Case.created_by_id == user.id,
                    Case.lead_attorney_id == user.id,
                    Case.team_members.any(User.id == user.id),
                    and_(Case.company_id == user.company_id, Case.is_confidential == False)
                )
            )

    # Search by original filename (case insensitive)
    query = query.filter(CaseDocument.original_filename.ilike(f'%{filename}%'))

    if case_id:
        query = query.filter(CaseDocument.case_id == case_id)

    result = query.first()
    print(f"DEBUG: Found document: {result.original_filename if result else 'None'}")

    return result

def find_case_by_number_or_id(user, identifier):
    """Find a case by case_number (user-facing) or id (internal database ID)"""
    logger.info(f"find_case_by_number_or_id called with identifier='{identifier}' for user_id={user.id}, role={user.role}")

    # Build base query with access control
    if user.is_admin():
        base_query = Case.query
        logger.info(f"User is admin - searching all cases")
    elif user.is_company_admin():
        base_query = Case.query.filter_by(company_id=user.company_id)
        logger.info(f"User is company_admin - searching company_id={user.company_id}")
    else:
        base_query = Case.query.filter(
            or_(
                Case.created_by_id == user.id,
                Case.lead_attorney_id == user.id,
                and_(Case.company_id == user.company_id, Case.is_confidential == False),
                Case.team_members.any(User.id == user.id)
            )
        )
        logger.info(f"User is regular user - searching with access control for user_id={user.id}, company_id={user.company_id}")

    # Try to find by case_number first (what users see in the UI)
    case = base_query.filter_by(case_number=str(identifier)).first()
    logger.info(f"Search by case_number='{identifier}': {'Found' if case else 'Not found'}")

    # If not found, try by internal ID as fallback
    if not case:
        try:
            id_val = int(identifier)
            case = base_query.filter_by(id=id_val).first()
            logger.info(f"Search by id={id_val}: {'Found' if case else 'Not found'}")
        except (ValueError, TypeError):
            logger.warning(f"Could not convert identifier '{identifier}' to int")
            pass

    if case:
        logger.info(f"Returning case: id={case.id}, case_number={case.case_number}, case_name={case.case_name}")
    else:
        logger.warning(f"No case found for identifier '{identifier}'")

    return case


def find_case_by_any_identifier(user, identifier):
    """
    Enhanced case finder with fuzzy matching
    Searches by: case_number, id, case_name (fuzzy), client_name (fuzzy)

    Examples:
    - "5" -> Finds case with id=5 or case_number="5"
    - "duccini" -> Fuzzy matches case_name="Duccini v. Johnson Corp"
    - "Smith" -> Fuzzy matches client_name="John Smith" or case_name="Smith Contract"
    """
    from difflib import SequenceMatcher

    logger.info(f"find_case_by_any_identifier: identifier='{identifier}' user_id={user.id}")

    # Build base query with access control (same as find_case_by_number_or_id)
    if user.is_admin():
        base_query = Case.query
    elif user.is_company_admin():
        base_query = Case.query.filter_by(company_id=user.company_id)
    else:
        base_query = Case.query.filter(
            or_(
                Case.created_by_id == user.id,
                Case.lead_attorney_id == user.id,
                and_(Case.company_id == user.company_id, Case.is_confidential == False),
                Case.team_members.any(User.id == user.id)
            )
        )

    # 1. Try exact case_number match
    case = base_query.filter_by(case_number=str(identifier)).first()
    if case:
        logger.info(f"✅ Found by exact case_number: {case.case_number}")
        return case

    # 2. Try exact database ID
    try:
        id_val = int(identifier)
        case = base_query.filter_by(id=id_val).first()
        if case:
            logger.info(f"✅ Found by database ID: {case.id}")
            return case
    except (ValueError, TypeError):
        pass

    # 3. Fuzzy match on case_name and client_name
    identifier_lower = str(identifier).lower().strip()

    # Get all accessible cases for fuzzy matching
    all_cases = base_query.all()

    best_match = None
    best_score = 0.0
    threshold = 0.6  # 60% similarity required

    for case in all_cases:
        # Check case_name
        if case.case_name:
            case_name_lower = case.case_name.lower()

            # Exact substring match gets highest priority
            if identifier_lower in case_name_lower:
                logger.info(f"✅ Found by substring in case_name: '{identifier}' in '{case.case_name}'")
                return case

            # Fuzzy match score
            score = SequenceMatcher(None, identifier_lower, case_name_lower).ratio()
            if score > best_score:
                best_score = score
                best_match = case

        # Check client_name
        if case.client_name:
            client_name_lower = case.client_name.lower()

            # Exact substring match
            if identifier_lower in client_name_lower:
                logger.info(f"✅ Found by substring in client_name: '{identifier}' in '{case.client_name}'")
                return case

            # Fuzzy match score
            score = SequenceMatcher(None, identifier_lower, client_name_lower).ratio()
            if score > best_score:
                best_score = score
                best_match = case

    # Return best fuzzy match if above threshold
    if best_match and best_score >= threshold:
        logger.info(f"✅ Found by fuzzy match (score={best_score:.2f}): case_id={best_match.id}, case_name='{best_match.case_name}'")
        return best_match

    logger.warning(f"❌ No case found for identifier '{identifier}' (best score: {best_score:.2f})")
    return None


def get_conversation_context(conversation_id, limit=5):
    """Get recent context from conversation history"""
    try:
        # Get last N assistant messages with entity info
        recent_messages = AssistantMessage.query.filter_by(
            conversation_id=conversation_id,
            message_type='assistant'
        ).filter(
            AssistantMessage.entity_type.isnot(None)
        ).order_by(
            AssistantMessage.created_at.desc()
        ).limit(limit).all()

        context = {
            'last_case_id': None,
            'last_document_id': None,
            'last_case_number': None,
            'recent_entities': []
        }

        for msg in reversed(recent_messages):  # Most recent last
            entity_info = {
                'type': msg.entity_type,
                'id': msg.entity_id,
                'action': msg.action_type
            }
            context['recent_entities'].append(entity_info)

            # Track most recent case and document
            if msg.entity_type == 'case' and not context['last_case_id']:
                context['last_case_id'] = msg.entity_id
                # Try to get case number from metadata or query
                if msg.msg_metadata and msg.msg_metadata.get('case_number'):
                    context['last_case_number'] = msg.msg_metadata.get('case_number')
            elif msg.entity_type == 'document' and not context['last_document_id']:
                context['last_document_id'] = msg.entity_id

        # NEW: Add user's cases to context for better matching
        try:
            conversation = AssistantConversation.query.get(conversation_id)
            if conversation and conversation.user:
                user = conversation.user

                # Get user's accessible cases (limited to 20 most recent)
                if user.is_admin():
                    cases = Case.query.order_by(Case.updated_at.desc()).limit(20).all()
                elif user.is_company_admin():
                    cases = Case.query.filter_by(company_id=user.company_id).order_by(Case.updated_at.desc()).limit(20).all()
                else:
                    cases = Case.query.filter(
                        or_(
                            Case.created_by_id == user.id,
                            Case.lead_attorney_id == user.id,
                            and_(Case.company_id == user.company_id, Case.is_confidential == False),
                            Case.team_members.any(User.id == user.id)
                        )
                    ).order_by(Case.updated_at.desc()).limit(20).all()

                context['user_cases'] = [
                    {
                        'case_number': c.case_number,
                        'case_name': c.case_name,
                        'client_name': c.client_name or 'Unknown'
                    }
                    for c in cases
                ]
        except Exception as e:
            logger.warning(f"Could not load user cases for context: {e}")
            context['user_cases'] = []

        return context

    except Exception as e:
        logger.error(f"Error getting conversation context: {e}")
        return {'last_case_id': None, 'last_document_id': None, 'recent_entities': [], 'user_cases': []}

def parse_user_intent(user_message, context=None):
    """Use OpenAI to parse user intent and extract entities"""
    try:
        from flask import current_app

        # Get OpenAI API key from app config
        api_key = current_app.config.get('OPENAI_API_KEY')
        if not api_key:
            logger.error("OpenAI API key not configured")
            raise ValueError("OpenAI API key not configured")

        # Build context hint for the AI
        context_hint = ""
        if context and (context.get('last_case_id') or context.get('last_document_id')):
            context_hint = "\n\nContext from conversation:"
            if context.get('last_case_id'):
                context_hint += f"\n- User was just discussing case ID: {context['last_case_id']}"
                if context.get('last_case_number'):
                    context_hint += f" (case #{context['last_case_number']})"
            if context.get('last_document_id'):
                context_hint += f"\n- User was just discussing document ID: {context['last_document_id']}"
            context_hint += "\n\nIf user says 'it', 'this case', 'that', 'add note', etc. without specifying a case number, use the last case ID from context."

        # Build case list hint for better name matching
        case_list_hint = ""
        if context and context.get('user_cases') and len(context['user_cases']) > 0:
            case_list_hint = "\n\n**User's Available Cases:**"
            for idx, case_info in enumerate(context['user_cases'][:10], 1):  # Show first 10
                case_list_hint += f"\n{idx}. Case #{case_info['case_number']}: \"{case_info['case_name']}\" (Client: {case_info['client_name']})"
            case_list_hint += "\n\n**IMPORTANT:** When user mentions a case by NAME, CLIENT NAME, or KEYWORD (not just a number), extract that name/keyword as the case_id. The system will fuzzy-match it to the correct case from the list above."
            case_list_hint += "\nExamples:"
            if len(context['user_cases']) > 0:
                first_case = context['user_cases'][0]
                # Extract a keyword from the case name for example
                case_name_words = first_case['case_name'].split()
                if len(case_name_words) > 0:
                    keyword = case_name_words[0].strip('\"').strip()
                    case_list_hint += f"\n- \"summarize my {keyword} case\" → {{\"intent\": \"summarize_case\", \"case_id\": \"{keyword}\", \"confidence\": 90}}"
                if first_case['client_name'] and first_case['client_name'] != 'Unknown':
                    client_name = first_case['client_name'].split()[0]  # First name
                    case_list_hint += f"\n- \"what's happening with {client_name}?\" → {{\"intent\": \"get_case_info\", \"case_id\": \"{client_name}\", \"confidence\": 85}}"

        # Build the system message
        system_message = """You are an intent classifier for a legal AI assistant. Analyze the user's message and return a JSON object with:
{
    "intent": "<one of: summarize_case, analyze_document, analyze_image, summarize_document, find_case, list_cases, list_cases_by_type, list_documents, list_summaries, list_analyses, get_case_info, search_documents, search_case_documents, add_case_note, update_case_status, batch_analyze, batch_summarize, show_timeline, legal_research, general_help, unknown>",
    "case_id": "<extracted case number or database ID or null>",
    "document_id": "<extracted document ID or null>",
    "filename": "<extracted filename if present or null>",
    "query": "<search query if applicable or null>",
    "note_text": "<note text for add_case_note intent or null>",
    "status": "<new status for update_case_status intent or null>",
    "case_type": "<case type filter: litigation, criminal, contract, civil, family, business, personal_injury, or null>",
    "confidence": <0-100>
}

Intent meanings:
- analyze_document: User wants to analyze a PDF/document (or view existing analysis)
- analyze_image: User wants to analyze an image file (JPG, PNG, etc.)
- summarize_document: User wants to summarize a document
- summarize_case: User wants a summary of an entire case
- get_case_info: User wants information about a case
- list_documents: User wants to see all their documents across all cases
- list_summaries: User wants to see all their document summaries
- list_analyses: User wants to see all their document/image analyses
- add_case_note: User wants to add a note to a case
- update_case_status: User wants to change a case status
- list_cases_by_type: User wants to see cases filtered by case type (litigation, criminal, contract, etc.)
- search_case_documents: User wants to search for a term across all documents in a specific case
- batch_analyze: User wants to analyze multiple documents in a case at once
- batch_summarize: User wants to summarize multiple documents in a case at once
- show_timeline: User wants to see the timeline of events for a case
- legal_research: User is asking a general legal question (not about a specific case or document in the system)

Examples:
- "summarize case 1234" -> {"intent": "summarize_case", "case_id": "1234", "confidence": 95}
- "tell me about case 1" -> {"intent": "get_case_info", "case_id": "1", "confidence": 95}
- "show me case 5" -> {"intent": "get_case_info", "case_id": "5", "confidence": 95}
- "list my cases" -> {"intent": "list_cases", "confidence": 100}
- "show my cases" -> {"intent": "list_cases", "confidence": 100}
- "show all cases" -> {"intent": "list_cases", "confidence": 100}
- "what cases do I have" -> {"intent": "list_cases", "confidence": 100}
- "analyze IMG_123.jpg" -> {"intent": "analyze_image", "filename": "IMG_123.jpg", "confidence": 90}
- "summarize tank_warranty.pdf" -> {"intent": "summarize_document", "filename": "tank_warranty.pdf", "confidence": 95}
- "add note to case 123: Client called today" -> {"intent": "add_case_note", "case_id": "123", "note_text": "Client called today", "confidence": 95}
- "add note: Client approved" (with context) -> {"intent": "add_case_note", "case_id": "<from context>", "note_text": "Client approved", "confidence": 90}
- "add another note: Meeting scheduled" (with context) -> {"intent": "add_case_note", "case_id": "<from context>", "note_text": "Meeting scheduled", "confidence": 90}
- "note: Client responded" (with context) -> {"intent": "add_case_note", "case_id": "<from context>", "note_text": "Client responded", "confidence": 85}
- "update status to settled" (with context) -> {"intent": "update_case_status", "case_id": "<from context>", "status": "settled", "confidence": 85}
- "mark as closed" (with context) -> {"intent": "update_case_status", "case_id": "<from context>", "status": "closed", "confidence": 85}
- "show my documents" -> {"intent": "list_documents", "confidence": 100}
- "list all documents" -> {"intent": "list_documents", "confidence": 100}
- "show my summaries" -> {"intent": "list_summaries", "confidence": 100}
- "list all summaries" -> {"intent": "list_summaries", "confidence": 100}
- "show document summaries" -> {"intent": "list_summaries", "confidence": 100}
- "show my analyses" -> {"intent": "list_analyses", "confidence": 100}
- "list all analyses" -> {"intent": "list_analyses", "confidence": 100}
- "show document analyses" -> {"intent": "list_analyses", "confidence": 100}
- "show criminal cases" -> {"intent": "list_cases_by_type", "case_type": "criminal", "confidence": 95}
- "list litigation cases" -> {"intent": "list_cases_by_type", "case_type": "litigation", "confidence": 95}
- "show contract cases" -> {"intent": "list_cases_by_type", "case_type": "contract", "confidence": 95}
- "find civil cases" -> {"intent": "list_cases_by_type", "case_type": "civil", "confidence": 95}
- "list family law cases" -> {"intent": "list_cases_by_type", "case_type": "family", "confidence": 95}
- "show personal injury cases" -> {"intent": "list_cases_by_type", "case_type": "personal_injury", "confidence": 95}
- "list PI cases" -> {"intent": "list_cases_by_type", "case_type": "personal_injury", "confidence": 90}
- "find negligence in case 123" -> {"intent": "search_case_documents", "case_id": "123", "query": "negligence", "confidence": 95}
- "search case 1 for evidence" -> {"intent": "search_case_documents", "case_id": "1", "query": "evidence", "confidence": 95}
- "find mentions of contract in case 456" -> {"intent": "search_case_documents", "case_id": "456", "query": "contract", "confidence": 95}
- "show documents with negligence" -> {"intent": "search_case_documents", "query": "negligence", "confidence": 90}
- "documents with evidence" -> {"intent": "search_case_documents", "query": "evidence", "confidence": 90}
- "show docs with contract" -> {"intent": "search_case_documents", "query": "contract", "confidence": 90}
- "analyze all documents in case 123" -> {"intent": "batch_analyze", "case_id": "123", "confidence": 95}
- "analyze all PDFs in case 1" -> {"intent": "batch_analyze", "case_id": "1", "confidence": 95}
- "summarize all documents in case 456" -> {"intent": "batch_summarize", "case_id": "456", "confidence": 95}
- "summarize everything in case 5" -> {"intent": "batch_summarize", "case_id": "5", "confidence": 90}
- "show timeline for case 444" -> {"intent": "show_timeline", "case_id": "444", "confidence": 95}
- "timeline for case 123" -> {"intent": "show_timeline", "case_id": "123", "confidence": 95}
- "show me the timeline" (with context) -> {"intent": "show_timeline", "case_id": "<from context>", "confidence": 90}
- "case timeline" (with context) -> {"intent": "show_timeline", "case_id": "<from context>", "confidence": 85}
- "what is the statute of limitations for personal injury in Nevada?" -> {"intent": "legal_research", "query": "statute of limitations for personal injury in Nevada", "confidence": 95}
- "can I sue for breach of contract?" -> {"intent": "legal_research", "query": "can I sue for breach of contract", "confidence": 90}
- "what are the elements of negligence?" -> {"intent": "legal_research", "query": "elements of negligence", "confidence": 95}
- "explain Miranda rights" -> {"intent": "legal_research", "query": "Miranda rights", "confidence": 90}
- "help" -> {"intent": "general_help", "confidence": 100}""" + context_hint + case_list_hint + "\n\nReturn ONLY valid JSON, no explanation."

        logger.info(f"Calling OpenAI with message: {user_message[:50]}")
        logger.debug(f"System message length: {len(system_message)}")

        client = openai.OpenAI(api_key=api_key)
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=[
                {"role": "system", "content": system_message},
                {"role": "user", "content": user_message}
            ],
            temperature=0.3,
            max_tokens=200
        )

        logger.info(f"OpenAI call completed")

        import json

        if not response or not response.choices or len(response.choices) == 0:
            logger.error("No choices in OpenAI response")
            raise ValueError("No choices in OpenAI response")

        response_content = response.choices[0].message.content

        if not response_content:
            logger.error(f"Empty content in OpenAI response. Response: {response}")
            raise ValueError("Empty content in OpenAI response")

        logger.debug(f"OpenAI response content: {response_content[:500]}")
        result = json.loads(response_content)
        logger.info(f"Intent parsed: {result}")
        return result
    except json.JSONDecodeError as e:
        logger.error(f"JSON decode error: {e}")
        logger.error(f"OpenAI returned: {response_content if 'response_content' in locals() else 'No response'}")
        logger.error(f"User message was: {user_message}")
        logger.error(f"Context was: {context}")
        # Fallback to simple pattern matching
        return {
            "intent": "unknown",
            "case_id": extract_case_number(user_message),
            "document_id": extract_document_id(user_message),
            "query": None,
            "confidence": 0
        }
    except Exception as e:
        logger.error(f"Intent parsing error: {e}")
        logger.error(f"User message was: {user_message}")
        logger.error(f"Context was: {context}")
        # Fallback to simple pattern matching
        return {
            "intent": "unknown",
            "case_id": extract_case_number(user_message),
            "document_id": extract_document_id(user_message),
            "query": None,
            "confidence": 0
        }

def get_case_summary(case, user):
    """Generate a comprehensive case summary with all documents and data"""

    # Get all documents for this case
    documents = CaseDocument.query.filter_by(case_id=case.id).order_by(
        CaseDocument.uploaded_at.desc()
    ).all()

    # Get notes
    notes = case.notes.order_by(desc('created_at')).limit(5).all()

    # Build comprehensive summary
    summary_parts = []

    case_url = f"/cases/{case.id}"
    summary_parts.append(f"**Case Summary: [{case.case_name}]({case_url})**\n")
    summary_parts.append(f"**Case Number:** {case.case_number}")
    summary_parts.append(f"**Status:** {case.status.title()}")
    summary_parts.append(f"**Client:** {case.client_name or 'Not specified'}")

    if case.opposing_party:
        summary_parts.append(f"**Opposing Party:** {case.opposing_party}")

    if case.lead_attorney:
        summary_parts.append(f"**Lead Attorney:** {case.lead_attorney.get_full_name()}")

    summary_parts.append(f"**Practice Area:** {case.practice_area.replace('_', ' ').title() if case.practice_area else 'General'}")
    summary_parts.append(f"**Type:** {case.case_type.title() if case.case_type else 'Not specified'}")

    if case.description:
        summary_parts.append(f"\n**Description:**\n{case.description}")

    # Documents section
    summary_parts.append(f"\n**Documents ({len(documents)}):**")
    if documents:
        for i, doc in enumerate(documents, 1):
            doc_info = f"{i}. **{doc.original_filename}** (ID: {doc.id})"
            if doc.document_type:
                doc_info += f" - {doc.document_type.title()}"
            if doc.has_analysis():
                doc_info += " ✓ Analyzed"
            if doc.has_summarization():
                doc_info += " ✓ Summarized"
            summary_parts.append(doc_info)
    else:
        summary_parts.append("No documents uploaded yet.")

    # Recent notes
    if notes:
        summary_parts.append(f"\n**Recent Notes ({len(notes)}):**")
        for note in notes:
            summary_parts.append(f"- {note.note_text[:100]}{'...' if len(note.note_text) > 100 else ''}")

    # Team members
    if case.team_members:
        summary_parts.append(f"\n**Team Members ({len(case.team_members)}):**")
        for member in case.team_members:
            summary_parts.append(f"- {member.get_full_name()}")

    return "\n".join(summary_parts)

def list_user_cases(user, limit=10):
    """List user's accessible cases
    Returns: (response_string, cases_list) tuple
    """
    if user.is_admin():
        cases = Case.query.order_by(Case.updated_at.desc()).limit(limit).all()
    elif user.is_company_admin():
        cases = Case.query.filter_by(company_id=user.company_id).order_by(
            Case.updated_at.desc()
        ).limit(limit).all()
    else:
        cases = Case.query.filter(
            or_(
                Case.created_by_id == user.id,
                Case.lead_attorney_id == user.id,
                and_(Case.company_id == user.company_id, Case.is_confidential == False),
                Case.team_members.any(User.id == user.id)
            )
        ).order_by(Case.updated_at.desc()).limit(limit).all()

    if not cases:
        return ("You don't have any cases yet. Create a new case to get started!", [])

    result = [f"**Your Cases ({len(cases)} most recent):**\n"]
    for i, case in enumerate(cases, 1):
        case_url = f"/cases/{case.id}"
        result.append(
            f"{i}. [**{case.case_name}**]({case_url}) (Case #{case.case_number}) - {case.status.title()}\n"
            f"   Client: {case.client_name or 'N/A'} | Documents: {case.get_document_count()} | ID: {case.id}"
        )

    return ("\n".join(result), cases)

def list_cases_by_type(user, case_type, limit=50):
    """List user's accessible cases filtered by case type
    Returns: (response_string, cases_list) tuple
    """
    # Normalize case type (handle various input formats)
    case_type_normalized = case_type.lower().replace(' ', '_')

    # Build base query with access control
    if user.is_admin():
        base_query = Case.query
    elif user.is_company_admin():
        base_query = Case.query.filter_by(company_id=user.company_id)
    else:
        base_query = Case.query.filter(
            or_(
                Case.created_by_id == user.id,
                Case.lead_attorney_id == user.id,
                and_(Case.company_id == user.company_id, Case.is_confidential == False),
                Case.team_members.any(User.id == user.id)
            )
        )

    # Filter by case type
    cases = base_query.filter(
        Case.case_type.ilike(f'%{case_type_normalized}%')
    ).order_by(Case.updated_at.desc()).limit(limit).all()

    if not cases:
        return (f"You don't have any **{case_type.title()}** cases yet.", [])

    result = [f"**Your {case_type.title()} Cases ({len(cases)} found):**\n"]
    for i, case in enumerate(cases, 1):
        case_url = f"/cases/{case.id}"
        result.append(
            f"{i}. [**{case.case_name}**]({case_url}) (Case #{case.case_number})\n"
            f"   Status: {case.status.title()} | Client: {case.client_name or 'N/A'} | Documents: {case.get_document_count()}"
        )

    return ("\n".join(result), cases)

def search_all_documents(user, search_term, limit=50):
    """Search for a term across all documents in all accessible cases"""
    try:
        # Get all accessible cases
        if user.is_admin():
            cases = Case.query.all()
        elif user.is_company_admin():
            cases = Case.query.filter_by(company_id=user.company_id).all()
        else:
            cases = Case.query.filter(
                or_(
                    Case.created_by_id == user.id,
                    Case.lead_attorney_id == user.id,
                    and_(Case.company_id == user.company_id, Case.is_confidential == False),
                    Case.team_members.any(User.id == user.id)
                )
            ).all()

        if not cases:
            return "You don't have any cases yet."

        # Search across all cases
        all_results = []
        total_mentions = 0
        cases_with_results = 0

        for case in cases:
            documents = CaseDocument.query.filter_by(case_id=case.id).all()

            for doc in documents:
                doc_mentions = 0
                snippets = []

                # Search in summarization results
                if doc.has_summarization():
                    summ_job = SummarizationJob.query.filter_by(job_uuid=doc.summarization_job_id).first()
                    if summ_job and summ_job.results:
                        text = summ_job.results.summary
                        count = text.lower().count(search_term.lower())
                        if count > 0:
                            doc_mentions += count
                            snippet = extract_context(text, search_term, context_chars=150)
                            if snippet:
                                snippets.append({
                                    'type': 'Summary',
                                    'text': snippet
                                })

                # Search in analysis results
                if doc.has_analysis():
                    analysis_job = AnalysisJob.query.filter_by(job_uuid=doc.analysis_job_id).first()
                    if analysis_job and analysis_job.results:
                        text = analysis_job.results.final_analysis
                        count = text.lower().count(search_term.lower())
                        if count > 0:
                            doc_mentions += count
                            snippet = extract_context(text, search_term, context_chars=150)
                            if snippet:
                                snippets.append({
                                    'type': 'Analysis',
                                    'text': snippet
                                })

                # Search in extracted document content (raw text)
                if doc.content_text and not snippets:  # Only if no analysis/summary found
                    text = doc.content_text
                    count = text.lower().count(search_term.lower())
                    if count > 0:
                        doc_mentions += count
                        snippet = extract_context(text, search_term, context_chars=150)
                        if snippet:
                            snippets.append({
                                'type': 'Document Text',
                                'text': snippet
                            })

                # If we found mentions in this document
                if doc_mentions > 0:
                    total_mentions += doc_mentions
                    doc_url = f"/cases/{case.id}/documents/{doc.id}/view"
                    case_url = f"/cases/{case.id}"
                    all_results.append({
                        'case': case,
                        'document': doc,
                        'mentions': doc_mentions,
                        'snippets': snippets,
                        'doc_url': doc_url,
                        'case_url': case_url
                    })

        # Check if we have results
        if not all_results:
            return f"""No mentions of \"{search_term}\" found in any of your documents.

💡 **Tip:** Make sure documents are analyzed or summarized first. Only processed documents are searchable."""

        # Count unique cases
        unique_cases = len(set([r['case'].id for r in all_results]))

        # Build response
        response = [f"**Search Results for \"{search_term}\" Across All Cases**\n"]
        response.append(f"Found **{total_mentions}** mention(s) in **{len(all_results)}** document(s) across **{unique_cases}** case(s):\n")

        # Group by case for better organization
        current_case_id = None
        for result in all_results[:limit]:  # Limit results
            # Add case header when switching cases
            if result['case'].id != current_case_id:
                current_case_id = result['case'].id
                response.append(f"\n**Case: [{result['case'].case_name}]({result['case_url']})** (#{result['case'].case_number})")

            # Document info
            doc = result['document']
            response.append(f"  • **[{doc.original_filename}]({result['doc_url']})** - {result['mentions']} mention(s)")

            # Add first snippet
            if result['snippets']:
                snippet = result['snippets'][0]
                response.append(f"    *{snippet['type']}:* {snippet['text']}")

        if len(all_results) > limit:
            response.append(f"\n*Showing first {limit} results. Refine your search or specify a case for more.*")

        response.append(f"\n💡 **Tip:** To search within a specific case, say 'find {search_term} in case NUMBER'")

        return "\n".join(response)

    except Exception as e:
        logger.error(f"Error searching all documents: {e}")
        return f"❌ Error searching documents: {str(e)}"

def search_documents_in_case(user, case, search_term):
    """Search for a term across all documents in a case"""
    try:
        # Get all documents in the case
        documents = CaseDocument.query.filter_by(case_id=case.id).all()

        if not documents:
            return f"Case **{case.case_name}** has no documents to search."

        results = []
        total_mentions = 0

        for doc in documents:
            doc_mentions = 0
            snippets = []

            # Search in summarization results
            if doc.has_summarization():
                summ_job = SummarizationJob.query.filter_by(job_uuid=doc.summarization_job_id).first()
                if summ_job and summ_job.results:
                    text = summ_job.results.summary
                    # Count occurrences (case-insensitive)
                    count = text.lower().count(search_term.lower())
                    if count > 0:
                        doc_mentions += count
                        # Get first occurrence snippet
                        snippet = extract_context(text, search_term, context_chars=200)
                        if snippet:
                            snippets.append({
                                'type': 'Summary',
                                'text': snippet
                            })

            # Search in analysis results
            if doc.has_analysis():
                analysis_job = AnalysisJob.query.filter_by(job_uuid=doc.analysis_job_id).first()
                if analysis_job and analysis_job.results:
                    text = analysis_job.results.final_analysis
                    count = text.lower().count(search_term.lower())
                    if count > 0:
                        doc_mentions += count
                        # Get first occurrence snippet
                        snippet = extract_context(text, search_term, context_chars=200)
                        if snippet:
                            snippets.append({
                                'type': 'Analysis',
                                'text': snippet
                            })

            # Search in extracted document content (raw text)
            if doc.content_text and not snippets:  # Only if no analysis/summary found
                text = doc.content_text
                count = text.lower().count(search_term.lower())
                if count > 0:
                    doc_mentions += count
                    snippet = extract_context(text, search_term, context_chars=200)
                    if snippet:
                        snippets.append({
                            'type': 'Document Text',
                            'text': snippet
                        })

            # If we found mentions in this document, add to results
            if doc_mentions > 0:
                total_mentions += doc_mentions
                doc_url = f"/cases/{case.id}/documents/{doc.id}/view"
                results.append({
                    'document': doc,
                    'mentions': doc_mentions,
                    'snippets': snippets,
                    'url': doc_url
                })

        # Format the response
        if not results:
            case_url = f"/cases/{case.id}"
            return f"""No mentions of \"{search_term}\" found in [{case.case_name}]({case_url}).

💡 **Tip:** Make sure documents are analyzed or summarized first. Only processed documents are searchable."""

        # Build response with results
        case_url = f"/cases/{case.id}"
        response = [f"**Search Results for \"{search_term}\" in [{case.case_name}]({case_url})**\n"]
        response.append(f"Found **{total_mentions}** mention(s) across **{len(results)}** document(s):\n")

        for i, result in enumerate(results, 1):
            doc = result['document']
            response.append(f"\n{i}. **[{doc.original_filename}]({result['url']})** - {result['mentions']} mention(s)")

            # Add snippets
            for snippet in result['snippets'][:2]:  # Limit to 2 snippets per document
                response.append(f"   *{snippet['type']}:* {snippet['text']}")

        response.append(f"\n💡 **Tip:** Click document names to view full content.")

        return "\n".join(response)

    except Exception as e:
        logger.error(f"Error searching documents in case: {e}")
        return f"❌ Error searching documents: {str(e)}"

def batch_analyze_documents(user, case):
    """Queue analysis for all unanalyzed documents in a case"""
    try:
        import uuid
        import time
        from datetime import datetime

        # Get all documents in the case
        documents = CaseDocument.query.filter_by(case_id=case.id).all()

        if not documents:
            return f"Case **{case.case_name}** has no documents to analyze."

        # Filter for documents that haven't been analyzed
        unanalyzed = [doc for doc in documents if not doc.has_analysis()]

        if not unanalyzed:
            case_url = f"/cases/{case.id}"
            return f"All documents in [{case.case_name}]({case_url}) have already been analyzed! ✅"

        # Check user's subscription limits
        from app import ensure_user_subscription
        subscription = ensure_user_subscription(user)

        if subscription and subscription.plan.name == 'free':
            # Free plan - check limits
            limit = subscription.plan.get_monthly_analysis_limit()
            used = subscription.monthly_analyses_used
            remaining = max(0, limit - used)

            if remaining < len(unanalyzed):
                return f"""❌ **Insufficient analyses remaining**

You have **{remaining}** analyses left this month, but need **{len(unanalyzed)}** to analyze all documents.

**Options:**
1. Upgrade to Pro or Enterprise for unlimited analyses
2. Analyze documents individually: [View Case]({f"/cases/{case.id}"})
3. Purchase additional single analyses"""

        # Create analysis jobs for each document
        from models import AnalysisJob
        jobs_created = []

        for doc in unanalyzed:
            # Check if file exists
            if not doc.file_path or not os.path.exists(doc.file_path):
                logger.warning(f"File not found for document {doc.id}: {doc.file_path}")
                continue

            # Determine analysis type
            is_image = doc.original_filename and any(
                doc.original_filename.lower().endswith(ext)
                for ext in ['.jpg', '.jpeg', '.png', '.gif', '.tif', '.tiff', '.bmp']
            )
            analysis_type = "image" if is_image else "document"

            # Create analysis job with neutral perspective
            job_uuid = str(uuid.uuid4())
            job = AnalysisJob(
                job_uuid=job_uuid,
                user_id=user.id,
                company_id=user.company_id,
                case_id=case.id,
                filename=doc.filename,
                original_filename=doc.original_filename,
                file_path=doc.file_path,
                perspective='neutral',
                practice_area='general',
                analysis_type=analysis_type,
                status='pending',
                created_at=datetime.utcnow()
            )
            db.session.add(job)

            # Link to document
            doc.analysis_job_id = job_uuid

            # Start background processing
            from app import process_document_analysis
            import threading
            threading.Thread(
                target=process_document_analysis,
                args=(job_uuid, doc.file_path, doc.original_filename, 'neutral', '', 'general', analysis_type)
            ).start()

            jobs_created.append({
                'filename': doc.original_filename,
                'job_id': job_uuid
            })

        db.session.commit()

        # Increment usage counter (both analysis and summarization use the same counter)
        if subscription:
            for _ in range(len(jobs_created)):
                subscription.increment_usage()

        # Build response
        case_url = f"/cases/{case.id}"
        response = [f"**✅ Batch Analysis Started for [{case.case_name}]({case_url})**\n"]
        response.append(f"Queued **{len(jobs_created)}** document(s) for analysis:\n")

        for i, job_info in enumerate(jobs_created, 1):
            response.append(f"{i}. {job_info['filename']}")

        response.append(f"\n**Status:** Processing in background...")
        response.append(f"**Perspective:** Neutral (default for batch)")
        response.append(f"\n💡 **Tip:** Refresh the case page in a few minutes to see results!")

        # Log activity
        from case_routes import log_case_activity
        log_case_activity(
            case.id,
            user.id,
            'batch_analysis_started',
            f'Batch analysis started for {len(jobs_created)} documents via AI Assistant',
            'case',
            case.id
        )

        return "\n".join(response)

    except Exception as e:
        logger.error(f"Error in batch_analyze_documents: {e}")
        import traceback
        traceback.print_exc()
        return f"❌ Error starting batch analysis: {str(e)}"

def batch_summarize_documents(user, case):
    """Queue summarization for all unsummarized documents in a case"""
    try:
        import uuid
        from datetime import datetime

        # Get all documents in the case
        documents = CaseDocument.query.filter_by(case_id=case.id).all()

        if not documents:
            return f"Case **{case.case_name}** has no documents to summarize."

        # Filter for documents that haven't been summarized
        unsummarized = [doc for doc in documents if not doc.has_summarization()]

        if not unsummarized:
            case_url = f"/cases/{case.id}"
            return f"All documents in [{case.case_name}]({case_url}) have already been summarized! ✅"

        # Check user's subscription limits
        from app import ensure_user_subscription
        subscription = ensure_user_subscription(user)

        if subscription and subscription.plan.name == 'free':
            # Free plan - check limits (summaries and analyses share the same counter)
            limit = subscription.plan.get_monthly_analysis_limit()
            used = subscription.monthly_analyses_used
            remaining = max(0, limit - used)

            if remaining < len(unsummarized):
                return f"""❌ **Insufficient operations remaining**

You have **{remaining}** analyses/summaries left this month, but need **{len(unsummarized)}** to summarize all documents.

**Options:**
1. Upgrade to Pro or Enterprise for unlimited operations
2. Summarize documents individually: [View Case]({f"/cases/{case.id}"})
3. Purchase additional single analyses"""

        # Create summarization jobs for each document
        from models import SummarizationJob
        from summarization_routes import process_summarization_job
        import threading

        jobs_created = []

        for doc in unsummarized:
            # Check if file exists
            if not doc.file_path or not os.path.exists(doc.file_path):
                logger.warning(f"File not found for document {doc.id}: {doc.file_path}")
                continue

            # Skip image files (can't summarize images)
            if doc.original_filename and any(
                doc.original_filename.lower().endswith(ext)
                for ext in ['.jpg', '.jpeg', '.png', '.gif', '.tif', '.tiff', '.bmp']
            ):
                continue

            # Create summarization job with default settings
            job_uuid = str(uuid.uuid4())
            job = SummarizationJob(
                job_uuid=job_uuid,
                user_id=user.id,
                company_id=user.company_id,
                case_id=case.id,
                filename=os.path.basename(doc.file_path),
                original_filename=doc.original_filename,
                file_path=doc.file_path,
                summary_type='executive',  # Default to executive summary
                summary_length='medium',   # Default to medium length
                status='pending',
                created_at=datetime.utcnow()
            )
            db.session.add(job)

            # Link to document
            doc.summarization_job_id = job_uuid

            # Start background processing
            threading.Thread(
                target=process_summarization_job,
                args=(job_uuid, doc.file_path, 'executive', 'medium', '', user.id, doc.id)
            ).start()

            jobs_created.append({
                'filename': doc.original_filename,
                'job_id': job_uuid
            })

        db.session.commit()

        # Increment usage counter (both analysis and summarization use the same counter)
        if subscription:
            for _ in range(len(jobs_created)):
                subscription.increment_usage()

        if not jobs_created:
            return f"No eligible documents found to summarize in **{case.case_name}**. (Image files are skipped)"

        # Build response
        case_url = f"/cases/{case.id}"
        response = [f"**✅ Batch Summarization Started for [{case.case_name}]({case_url})**\n"]
        response.append(f"Queued **{len(jobs_created)}** document(s) for summarization:\n")

        for i, job_info in enumerate(jobs_created, 1):
            response.append(f"{i}. {job_info['filename']}")

        response.append(f"\n**Status:** Processing in background...")
        response.append(f"**Type:** Executive Summary (default for batch)")
        response.append(f"**Length:** Medium (default for batch)")
        response.append(f"\n💡 **Tip:** Refresh the case page in a few minutes to see results!")

        # Log activity
        from case_routes import log_case_activity
        log_case_activity(
            case.id,
            user.id,
            'batch_summarization_started',
            f'Batch summarization started for {len(jobs_created)} documents via AI Assistant',
            'case',
            case.id
        )

        return "\n".join(response)

    except Exception as e:
        logger.error(f"Error in batch_summarize_documents: {e}")
        import traceback
        traceback.print_exc()
        return f"❌ Error starting batch summarization: {str(e)}"

def search_cases(user, query):
    """Search for cases matching query
    Returns: (response_string, cases_list) tuple
    """
    base_query = Case.query

    # Apply access control
    if not user.is_admin():
        if user.is_company_admin():
            base_query = base_query.filter_by(company_id=user.company_id)
        else:
            base_query = base_query.filter(
                or_(
                    Case.created_by_id == user.id,
                    Case.lead_attorney_id == user.id,
                    and_(Case.company_id == user.company_id, Case.is_confidential == False),
                    Case.team_members.any(User.id == user.id)
                )
            )

    # Search in case name, client name, description
    search_filter = or_(
        Case.case_name.ilike(f'%{query}%'),
        Case.client_name.ilike(f'%{query}%'),
        Case.description.ilike(f'%{query}%'),
        Case.case_number.ilike(f'%{query}%')
    )

    cases = base_query.filter(search_filter).order_by(Case.updated_at.desc()).limit(10).all()

    if not cases:
        return (f"No cases found matching '{query}'.", [])

    result = [f"**Found {len(cases)} case(s) matching '{query}':**\n"]
    for i, case in enumerate(cases, 1):
        case_url = f"/cases/{case.id}"
        result.append(
            f"{i}. [**{case.case_name}**]({case_url}) (Case #{case.case_number})\n"
            f"   Client: {case.client_name or 'N/A'} | Status: {case.status.title()} | ID: {case.id}"
        )

    return ("\n".join(result), cases)

def list_all_documents(user, limit=50):
    """List all documents the user has access to across all cases"""
    # Build query with proper access control - same as case access
    if user.is_admin():
        # Admins see all documents
        documents = CaseDocument.query.join(Case).order_by(
            CaseDocument.uploaded_at.desc()
        ).limit(limit).all()
    elif user.is_company_admin():
        # Company admins see all company documents
        documents = CaseDocument.query.join(Case).filter(
            Case.company_id == user.company_id
        ).order_by(CaseDocument.uploaded_at.desc()).limit(limit).all()
    else:
        # Regular users see documents from accessible cases only
        documents = CaseDocument.query.join(Case).filter(
            or_(
                Case.created_by_id == user.id,
                Case.lead_attorney_id == user.id,
                and_(Case.company_id == user.company_id, Case.is_confidential == False),
                Case.team_members.any(User.id == user.id)
            )
        ).order_by(CaseDocument.uploaded_at.desc()).limit(limit).all()

    if not documents:
        return "You don't have any documents yet. Upload documents to your cases to get started!"

    # Group by case for better organization
    result = [f"**Your Documents ({len(documents)} most recent):**\n"]

    current_case_id = None
    for doc in documents:
        # Add case header when switching cases
        if doc.case_id != current_case_id:
            current_case_id = doc.case_id
            case_url = f"/cases/{doc.case_id}"
            result.append(f"\n**Case: [{doc.case.case_name}]({case_url})** (#{doc.case.case_number})")

        # Document info with clickable link
        doc_url = f"/cases/{doc.case_id}/documents/{doc.id}/view"
        doc_info = f"  • [**{doc.original_filename}**]({doc_url}) (ID: {doc.id})"

        if doc.document_type:
            doc_info += f" - {doc.document_type.title()}"

        # Add status badges
        status = []
        if doc.has_analysis():
            status.append("✓ Analyzed")
        if doc.has_summarization():
            status.append("✓ Summarized")

        if status:
            doc_info += f" | {', '.join(status)}"

        result.append(doc_info)

        # Add summary snippet if available
        if doc.has_summarization():
            summ_job = SummarizationJob.query.filter_by(job_uuid=doc.summarization_job_id).first()
            if summ_job and summ_job.results:
                snippet = summ_job.results.summary[:200].replace('\n', ' ')
                result.append(f"    **Summary:** {snippet}{'...' if len(summ_job.results.summary) > 200 else ''}")

        # Add analysis snippet if available
        if doc.has_analysis():
            analysis_job = AnalysisJob.query.filter_by(job_uuid=doc.analysis_job_id).first()
            if analysis_job and analysis_job.results:
                snippet = analysis_job.results.final_analysis[:200].replace('\n', ' ')
                result.append(f"    **Analysis:** {snippet}{'...' if len(analysis_job.results.final_analysis) > 200 else ''}")

    result.append(f"\n💡 **Tip:** Click a filename to view it, or type a filename to analyze/summarize it!")

    return "\n".join(result)

def list_all_summaries(user, limit=20):
    """List all document summaries the user has access to"""
    # Build query - filter by user and company, checking completed jobs
    if user.is_admin():
        summ_jobs = SummarizationJob.query.filter_by(
            status='completed'
        ).order_by(SummarizationJob.created_at.desc()).limit(limit).all()
    elif user.is_company_admin():
        summ_jobs = SummarizationJob.query.filter_by(
            company_id=user.company_id,
            status='completed'
        ).order_by(SummarizationJob.created_at.desc()).limit(limit).all()
    else:
        summ_jobs = SummarizationJob.query.filter_by(
            user_id=user.id,
            status='completed'
        ).order_by(SummarizationJob.created_at.desc()).limit(limit).all()

    if not summ_jobs:
        return "You don't have any document summaries yet. Use the Summarization feature to create summaries!"

    result = [f"**Your Document Summaries ({len(summ_jobs)} most recent):**\n"]

    for job in summ_jobs:
        # Get the associated document (if linked)
        doc = CaseDocument.query.filter_by(summarization_job_id=job.job_uuid).first()

        # Document info - correct URL format for HTML view
        doc_url = f"/summarization/summary/{job.job_uuid}"

        if doc:
            case_url = f"/cases/{doc.case_id}"
            result.append(f"\n📄 [**{doc.original_filename}**]({doc_url})")
            result.append(f"   Case: [{doc.case.case_name}]({case_url}) (#{doc.case.case_number})")
        else:
            # For summaries not linked to a case document
            result.append(f"\n📄 [**Summary Job {job.job_uuid[:8]}...**]({doc_url})")
            result.append(f"   (Standalone summary)")

        result.append(f"   Type: **{job.summary_type.replace('_', ' ').title()}** | Length: **{job.summary_length.title()}**")
        result.append(f"   Created: {job.created_at.strftime('%Y-%m-%d %H:%M')}")

        # Add summary snippet if available
        if job.results:
            snippet = job.results.summary[:250].replace('\n', ' ')
            result.append(f"   **Summary:** {snippet}{'...' if len(job.results.summary) > 250 else ''}")

        result.append("")  # Blank line between entries

    result.append(f"💡 **Tip:** Click a document name to view the full summary!")

    return "\n".join(result)

def list_all_analyses(user, limit=20):
    """List all document/image analyses the user has access to"""
    # Build query - filter by user and company, checking completed jobs
    if user.is_admin():
        analysis_jobs = AnalysisJob.query.filter_by(
            status='completed'
        ).order_by(AnalysisJob.created_at.desc()).limit(limit).all()
    elif user.is_company_admin():
        analysis_jobs = AnalysisJob.query.filter_by(
            company_id=user.company_id,
            status='completed'
        ).order_by(AnalysisJob.created_at.desc()).limit(limit).all()
    else:
        analysis_jobs = AnalysisJob.query.filter_by(
            user_id=user.id,
            status='completed'
        ).order_by(AnalysisJob.created_at.desc()).limit(limit).all()

    if not analysis_jobs:
        return "You don't have any document/image analyses yet. Use the Analysis feature to analyze your documents!"

    result = [f"**Your Document & Image Analyses ({len(analysis_jobs)} most recent):**\n"]

    for job in analysis_jobs:
        # Get the associated document (if linked)
        doc = CaseDocument.query.filter_by(analysis_job_id=job.job_uuid).first()

        # Document info - correct URL format for HTML view
        doc_url = f"/analysis/{job.job_uuid}"

        if doc:
            case_url = f"/cases/{doc.case_id}"

            # Determine if it's an image
            is_image = doc.original_filename and any(
                doc.original_filename.lower().endswith(ext)
                for ext in ['.jpg', '.jpeg', '.png', '.gif', '.tif', '.tiff', '.bmp']
            )

            icon = "🖼️" if is_image else "📄"

            result.append(f"\n{icon} [**{doc.original_filename}**]({doc_url})")
            result.append(f"   Case: [{doc.case.case_name}]({case_url}) (#{doc.case.case_number})")
            result.append(f"   Perspective: **{job.perspective.title()}** | Type: **{'Image' if is_image else 'Document'}**")
        else:
            # For analyses not linked to a case document
            result.append(f"\n📄 [**Analysis Job {job.job_uuid[:8]}...**]({doc_url})")
            result.append(f"   (Standalone analysis)")
            result.append(f"   Perspective: **{job.perspective.title()}**")

        result.append(f"   Created: {job.created_at.strftime('%Y-%m-%d %H:%M')}")

        # Add analysis snippet if available
        if job.results:
            snippet = job.results.final_analysis[:250].replace('\n', ' ')
            result.append(f"   **Analysis:** {snippet}{'...' if len(job.results.final_analysis) > 250 else ''}")

        result.append("")  # Blank line between entries

    result.append(f"💡 **Tip:** Click a document name to view the full analysis!")

    return "\n".join(result)

def analyze_image_document(user, document, user_message):
    """Analyze an image document using GPT-4 Vision"""
    try:
        # Import the image analysis function from app
        from app import analyze_image_with_openai

        # Check if already analyzed
        if document.has_analysis():
            analysis_job = AnalysisJob.query.filter_by(job_uuid=document.analysis_job_id).first()
            if analysis_job and analysis_job.results:
                return f"""**Previous Analysis of {document.original_filename}:**

{analysis_job.results.final_analysis[:2000]}{'...' if len(analysis_job.results.final_analysis) > 2000 else ''}

This image was analyzed from a **{analysis_job.perspective}** perspective.
View full analysis at: `/analysis/{analysis_job.job_uuid}`"""

        # Perform new analysis
        file_path = document.file_path
        if not os.path.exists(file_path):
            return f"Image file not found: {document.original_filename}"

        # Use neutral perspective for assistant analysis
        analysis_result = analyze_image_with_openai(
            file_path,
            perspective='neutral',
            additional_instructions=f"User asked: {user_message}"
        )

        return f"""**Analysis of {document.original_filename}:**

{analysis_result}

💡 This is a quick analysis. For a full legal analysis, use the New Analysis feature and select your perspective (prosecutor, defense, or neutral)."""

    except Exception as e:
        print(f"Image analysis error: {e}")
        import traceback
        traceback.print_exc()
        return f"Error analyzing image: {str(e)}"

def add_case_note(user, case, note_text):
    """Add a note to a case via assistant"""
    try:
        from models import CaseNote

        # Create the note
        note = CaseNote(
            case_id=case.id,
            user_id=user.id,
            note_text=note_text.strip()
        )
        db.session.add(note)

        # Update case timestamp
        case.updated_at = datetime.utcnow()

        db.session.commit()

        case_url = f"/cases/{case.id}"
        return f"""✅ **Note added to [{case.case_name}]({case_url})**

**Note:** {note_text}

The note has been saved and is visible on the case dashboard."""

    except Exception as e:
        logger.error(f"Error adding case note: {e}")
        return f"❌ Failed to add note: {str(e)}"

def update_case_status(user, case, new_status):
    """Update case status via assistant"""
    try:
        # Validate status
        valid_statuses = ['active', 'pending', 'closed', 'settled', 'dismissed', 'on_hold']
        status_normalized = new_status.lower().replace(' ', '_')

        if status_normalized not in valid_statuses:
            return f"❌ Invalid status. Valid options: active, pending, closed, settled, dismissed, on_hold"

        old_status = case.status
        case.status = status_normalized
        case.updated_at = datetime.utcnow()

        db.session.commit()

        # Log the activity
        from case_routes import log_case_activity
        log_case_activity(
            case.id,
            user.id,
            'status_updated',
            f'Status changed from {old_status} to {status_normalized} via AI Assistant',
            'case',
            case.id
        )

        case_url = f"/cases/{case.id}"
        return f"""✅ **Case status updated for [{case.case_name}]({case_url})**

**Previous status:** {old_status.replace('_', ' ').title()}
**New status:** {status_normalized.replace('_', ' ').title()}

The status has been updated and is visible on the case dashboard."""

    except Exception as e:
        logger.error(f"Error updating case status: {e}")
        db.session.rollback()
        return f"❌ Failed to update status: {str(e)}"

def get_document_summary(user, document):
    """Get or generate summary for a document"""
    try:
        # Check if already summarized
        if document.has_summarization():
            summ_job = SummarizationJob.query.filter_by(job_uuid=document.summarization_job_id).first()
            if summ_job and summ_job.results:
                return f"""**Summary of {document.original_filename}:**

{summ_job.results.summary[:2000]}{'...' if len(summ_job.results.summary) > 2000 else ''}

Summary type: **{summ_job.summary_type.replace('_', ' ').title()}**
Length: **{summ_job.summary_length.title()}**
View full summary at: `/summarization/{summ_job.job_uuid}`"""

        # Check if it has an analysis we can use
        if document.has_analysis():
            analysis_job = AnalysisJob.query.filter_by(job_uuid=document.analysis_job_id).first()
            if analysis_job and analysis_job.results:
                return f"""**Analysis Summary of {document.original_filename}:**

{analysis_job.results.final_analysis[:2000]}{'...' if len(analysis_job.results.final_analysis) > 2000 else ''}

💡 This document has a full legal analysis. For a dedicated summary, use the Summarization feature."""

        # Provide clickable links to start summarization or analysis
        summ_url = f"/summarization/?case_id={document.case_id}&document_id={document.id}"
        analysis_url = f"/analysis/?case_id={document.case_id}&document_id={document.id}"
        case_url = f"/cases/{document.case_id}"

        return f"""**{document.original_filename}** hasn't been summarized yet.

**Quick Actions:**
- [📝 Create Summary]({summ_url}) - Generate a detailed summary
- [🔍 Analyze Document]({analysis_url}) - Get legal analysis
- [📁 View Case Dashboard]({case_url}) - See all case documents

Click any link above to get started!"""

    except Exception as e:
        print(f"Document summary error: {e}")
        return f"Error retrieving summary: {str(e)}"

def show_case_timeline(user, case, limit=10):
    """Format case timeline for assistant display"""
    try:
        from case_routes import generate_case_timeline

        # Get timeline events
        events = generate_case_timeline(case, limit=limit)

        if not events:
            case_url = f"/cases/{case.id}"
            return f"""**Timeline for [{case.case_name}]({case_url})** (Case #{case.case_number})

No events yet. Timeline will populate as you add documents, notes, and perform actions on this case."""

        # Format timeline for assistant
        case_url = f"/cases/{case.id}"
        response = [f"**📅 Timeline for [{case.case_name}]({case_url})** (Case #{case.case_number})\n"]
        response.append(f"Showing last {len(events)} event(s):\n")

        # Icon map for different event types
        icon_map = {
            'case_created': '📁',
            'document_uploaded': '📤',
            'note_added': '📝',
            'status_changed': '🔄',
            'analysis_completed': '🔬',
            'summary_completed': '📄'
        }

        for event in events:
            icon = icon_map.get(event['type'], '•')
            date_str = event['date'].strftime('%m/%d/%Y')

            response.append(
                f"{icon} **{date_str}** - {event['title']}\n"
                f"   {event['description']}\n"
                f"   *{event['source']}*\n"
            )

        response.append(f"\n💡 **Tip:** Visit the [case dashboard]({case_url}) to see the full visual timeline!")

        return "\n".join(response)

    except Exception as e:
        logger.error(f"Error generating timeline: {e}")
        return f"❌ Error generating timeline: {str(e)}"

@assistant_bp.route('/chat', methods=['POST'])
@login_required
def chat():
    """Main chat endpoint - processes user messages and returns AI responses"""
    user_id = session.get('user_id')
    user = User.query.get(user_id)

    data = request.get_json()
    user_message = data.get('message', '').strip()
    conversation_id = data.get('conversation_id')

    if not user_message:
        return jsonify({'error': 'Message is required'}), 400

    try:
        # Get or create conversation
        if conversation_id:
            conversation = AssistantConversation.query.filter_by(
                conversation_uuid=conversation_id,
                user_id=user.id
            ).first()
            if not conversation:
                return jsonify({'error': 'Conversation not found'}), 404
        else:
            # Create new conversation
            conversation = AssistantConversation(
                conversation_uuid=str(uuid.uuid4()),
                user_id=user.id,
                company_id=user.company_id,
                title=user_message[:100]  # Use first message as title
            )
            db.session.add(conversation)
            db.session.flush()

        # Save user message
        user_msg = AssistantMessage(
            conversation_id=conversation.id,
            message_type='user',
            message_text=user_message
        )
        db.session.add(user_msg)

        # Get conversation context
        context = get_conversation_context(conversation.id)

        # Parse intent with context
        intent_data = parse_user_intent(user_message, context)
        intent = intent_data.get('intent', 'unknown')

        # If case_id or document_id is "<from context>", replace with actual ID
        case_id_raw = intent_data.get('case_id')
        if case_id_raw == '<from context>' and context.get('last_case_id'):
            intent_data['case_id'] = context['last_case_id']
            logger.info(f"Using case from context: {context['last_case_id']}")

        # Process based on intent
        assistant_response = ""
        action_type = intent
        entity_type = None
        entity_id = None
        metadata = {}

        if intent == 'summarize_case' or intent == 'get_case_info':
            case_id = intent_data.get('case_id')
            if case_id:
                case = find_case_by_any_identifier(user, case_id)
                if case:
                    assistant_response = get_case_summary(case, user)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    metadata = {'case_number': case.case_number}
                else:
                    assistant_response = f"Case #{case_id} not found. Use 'list my cases' to see available cases."
            else:
                assistant_response = "Please specify a case number, e.g., 'summarize case 1'"

        elif intent == 'list_cases':
            assistant_response, cases_found = list_user_cases(user)
            # If exactly 1 case found, save to context for follow-up queries
            if len(cases_found) == 1:
                entity_type = 'case'
                entity_id = str(cases_found[0].id)
                metadata = {'case_number': cases_found[0].case_number}

        elif intent == 'list_cases_by_type':
            case_type = intent_data.get('case_type')
            if case_type:
                assistant_response, cases_found = list_cases_by_type(user, case_type)
                # If exactly 1 case found, save to context for follow-up queries
                if len(cases_found) == 1:
                    entity_type = 'case'
                    entity_id = str(cases_found[0].id)
                    metadata = {'case_number': cases_found[0].case_number}
            else:
                assistant_response = "Please specify a case type (e.g., 'show criminal cases' or 'list litigation cases')"

        elif intent == 'list_documents':
            assistant_response = list_all_documents(user)

        elif intent == 'list_summaries':
            assistant_response = list_all_summaries(user)
            action_type = 'list_summaries'

        elif intent == 'list_analyses':
            assistant_response = list_all_analyses(user)
            action_type = 'list_analyses'

        elif intent == 'find_case':
            query = intent_data.get('query')
            if query:
                assistant_response, cases_found = search_cases(user, query)
                # If exactly 1 case found, save to context for follow-up queries
                if len(cases_found) == 1:
                    entity_type = 'case'
                    entity_id = str(cases_found[0].id)
                    metadata = {'case_number': cases_found[0].case_number}
            else:
                assistant_response = "What would you like to search for?"

        elif intent == 'search_case_documents':
            case_id = intent_data.get('case_id')
            search_query = intent_data.get('query')

            if case_id and search_query:
                # Search within specific case
                case = find_case_by_any_identifier(user, case_id)
                if case:
                    assistant_response = search_documents_in_case(user, case, search_query)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    action_type = 'search_documents'
                    metadata = {'case_number': case.case_number, 'search_term': search_query}
                else:
                    assistant_response = f"❌ Case #{case_id} not found. Use 'list my cases' to see available cases."
            elif case_id and not search_query:
                assistant_response = "Please specify what to search for, e.g., 'find negligence in case 123'"
            elif search_query and not case_id:
                # Check if there's context from previous conversation
                if context.get('last_case_id'):
                    case = find_case_by_any_identifier(user, context['last_case_id'])
                    if case:
                        # Search within the context case
                        assistant_response = search_documents_in_case(user, case, search_query)
                        entity_type = 'case'
                        entity_id = str(case.id)
                        action_type = 'search_documents'
                        metadata = {'case_number': case.case_number, 'search_term': search_query}
                    else:
                        # Fall back to global search
                        assistant_response = search_all_documents(user, search_query)
                        action_type = 'search_all_documents'
                        metadata = {'search_term': search_query}
                else:
                    # No context - search across ALL accessible cases
                    assistant_response = search_all_documents(user, search_query)
                    action_type = 'search_all_documents'
                    metadata = {'search_term': search_query}
            else:
                assistant_response = "Please specify a search term, e.g., 'show documents with negligence' or 'find evidence in case 123'"

        elif intent == 'add_case_note':
            case_id = intent_data.get('case_id')
            note_text = intent_data.get('note_text')

            if case_id and note_text:
                case = find_case_by_any_identifier(user, case_id)
                if case:
                    assistant_response = add_case_note(user, case, note_text)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    action_type = 'add_note'
                    metadata = {'case_number': case.case_number, 'note_text': note_text[:100]}
                else:
                    assistant_response = f"❌ Case #{case_id} not found. Use 'list my cases' to see available cases."
            else:
                assistant_response = "Please specify both a case number and note text, e.g., 'add note to case 123: Client called today'"

        elif intent == 'update_case_status':
            case_id = intent_data.get('case_id')
            new_status = intent_data.get('status')

            if case_id and new_status:
                case = find_case_by_any_identifier(user, case_id)
                if case:
                    assistant_response = update_case_status(user, case, new_status)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    action_type = 'update_status'
                    metadata = {'case_number': case.case_number, 'new_status': new_status}
                else:
                    assistant_response = f"❌ Case #{case_id} not found. Use 'list my cases' to see available cases."
            else:
                assistant_response = "Please specify both a case number and new status, e.g., 'update case 123 status to settled'"

        elif intent == 'batch_analyze':
            case_id = intent_data.get('case_id')

            if case_id:
                case = find_case_by_any_identifier(user, case_id)
                if case:
                    assistant_response = batch_analyze_documents(user, case)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    action_type = 'batch_analyze'
                    metadata = {'case_number': case.case_number}
                else:
                    assistant_response = f"❌ Case #{case_id} not found. Use 'list my cases' to see available cases."
            elif context.get('last_case_id'):
                # Use context case
                case = find_case_by_number_or_id(user, context['last_case_id'])
                if case:
                    assistant_response = batch_analyze_documents(user, case)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    action_type = 'batch_analyze'
                    metadata = {'case_number': case.case_number}
                else:
                    assistant_response = "Please specify a case number, e.g., 'analyze all documents in case 123'"
            else:
                assistant_response = "Please specify a case number, e.g., 'analyze all documents in case 123'"

        elif intent == 'batch_summarize':
            case_id = intent_data.get('case_id')

            if case_id:
                case = find_case_by_any_identifier(user, case_id)
                if case:
                    assistant_response = batch_summarize_documents(user, case)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    action_type = 'batch_summarize'
                    metadata = {'case_number': case.case_number}
                else:
                    assistant_response = f"❌ Case #{case_id} not found. Use 'list my cases' to see available cases."
            elif context.get('last_case_id'):
                # Use context case
                case = find_case_by_number_or_id(user, context['last_case_id'])
                if case:
                    assistant_response = batch_summarize_documents(user, case)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    action_type = 'batch_summarize'
                    metadata = {'case_number': case.case_number}
                else:
                    assistant_response = "Please specify a case number, e.g., 'summarize all documents in case 123'"
            else:
                assistant_response = "Please specify a case number, e.g., 'summarize all documents in case 123'"

        elif intent == 'show_timeline':
            case_id = intent_data.get('case_id')

            if case_id:
                case = find_case_by_any_identifier(user, case_id)
                if case:
                    assistant_response = show_case_timeline(user, case, limit=10)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    action_type = 'show_timeline'
                    metadata = {'case_number': case.case_number}
                else:
                    assistant_response = f"❌ Case #{case_id} not found. Use 'list my cases' to see available cases."
            elif context.get('last_case_id'):
                # Use context case
                case = find_case_by_number_or_id(user, context['last_case_id'])
                if case:
                    assistant_response = show_case_timeline(user, case, limit=10)
                    entity_type = 'case'
                    entity_id = str(case.id)
                    action_type = 'show_timeline'
                    metadata = {'case_number': case.case_number}
                else:
                    assistant_response = "Please specify a case number, e.g., 'show timeline for case 123'"
            else:
                assistant_response = "Please specify a case number, e.g., 'show timeline for case 123'"

        elif intent == 'legal_research':
            # User is asking a general legal question
            query = intent_data.get('query') or user_message

            if query:
                try:
                    # Import the AI legal search processor
                    from ai_legal_search_routes import legal_search_processor

                    if not legal_search_processor:
                        assistant_response = "⚠️ AI Legal Research is not currently available. Please try again later or contact support."
                    else:
                        # Process the legal research query
                        logger.info(f"Processing legal research query via assistant: {query}")

                        # Step 1: Analyze the query
                        analysis = legal_search_processor.analyze_query(query)

                        # Step 2: Search legal databases
                        search_results = legal_search_processor.search_legal_databases(analysis)

                        # Step 3: Generate AI response
                        full_response = legal_search_processor.generate_response(query, analysis, search_results)

                        # Step 4: Truncate response to ~150 words for assistant display
                        words = full_response.split()
                        if len(words) > 150:
                            truncated_response = ' '.join(words[:150]) + '...'
                        else:
                            truncated_response = full_response

                        # Generate cache key for sessionStorage
                        import time
                        cache_key = f"legal_research_{int(time.time() * 1000)}"
                        ai_research_url = f"/ai-research?cached={cache_key}"

                        assistant_response = f"""**Legal Research Answer:**

{truncated_response}

{'**[📚 View Full Answer & Sources on AI Research Page](' + ai_research_url + ')**' if len(words) > 150 else ''}

💡 **Tip:** For more detailed legal research with comprehensive sources, visit the [AI Research page]({ai_research_url})."""

                        action_type = 'legal_research'

                        # Ensure sources are JSON serializable (convert objects to dicts if needed)
                        serializable_sources = []
                        if search_results:
                            for source in search_results:
                                if isinstance(source, dict):
                                    serializable_sources.append(source)
                                else:
                                    # Convert object to dict if it's not already
                                    serializable_sources.append({
                                        'title': getattr(source, 'title', ''),
                                        'type': getattr(source, 'type', ''),
                                        'citation': getattr(source, 'citation', ''),
                                        'description': getattr(source, 'description', ''),
                                        'url': getattr(source, 'url', ''),
                                        'court': getattr(source, 'court', ''),
                                        'date': getattr(source, 'date', '')
                                    })

                        metadata = {
                            'query': query,
                            'topic': analysis.get('topic', 'general') if isinstance(analysis, dict) else 'general',
                            'cache_key': cache_key,
                            'full_response': full_response,
                            'sources': serializable_sources,
                            'analysis': analysis if isinstance(analysis, dict) else {}
                        }

                        logger.info(f"Created metadata with cache_key: {cache_key}, sources count: {len(serializable_sources)}")

                except Exception as e:
                    logger.error(f"Error in legal research via assistant: {e}")
                    import traceback
                    traceback.print_exc()
                    assistant_response = f"❌ I encountered an error while researching that legal question. Please try using the [AI Research page](/ai-research) directly."
            else:
                assistant_response = "What legal question would you like me to research?"

        elif intent == 'analyze_document' or intent == 'analyze_image' or intent == 'summarize_document':
            # Try to find document by filename first, then by ID
            filename = intent_data.get('filename') or extract_filename(user_message)
            case_id = intent_data.get('case_id')
            doc_id = intent_data.get('document_id')

            doc = None

            # First try filename search
            if filename:
                doc = find_document_by_filename(user, filename, case_id=int(case_id) if case_id else None)
                if doc:
                    entity_type = 'document'
                    entity_id = str(doc.id)
                    metadata = {'filename': filename, 'case_id': doc.case_id}

                    # Determine if it's an image
                    is_image = doc.original_filename and any(
                        doc.original_filename.lower().endswith(ext)
                        for ext in ['.jpg', '.jpeg', '.png', '.gif', '.tif', '.tiff', '.bmp']
                    )

                    if intent == 'analyze_image' or (intent == 'analyze_document' and is_image):
                        assistant_response = analyze_image_document(user, doc, user_message)
                    elif intent == 'summarize_document':
                        assistant_response = get_document_summary(user, doc)
                    else:
                        # Regular document analysis
                        if doc.has_analysis():
                            analysis_job = AnalysisJob.query.filter_by(job_uuid=doc.analysis_job_id).first()
                            if analysis_job and analysis_job.results:
                                assistant_response = f"**Analysis of {doc.original_filename}:**\n\n{analysis_job.results.final_analysis[:1500]}..."
                            else:
                                assistant_response = f"Analysis exists but results not available."
                        else:
                            analysis_url = f"/analysis/?case_id={doc.case_id}&document_id={doc.id}"
                            assistant_response = f"**{doc.original_filename}** hasn't been analyzed yet.\n\n[🔍 Click here to analyze this document]({analysis_url})"
                else:
                    assistant_response = f"Document '{filename}' not found in your accessible cases."

            # Fallback to ID-based lookup
            elif case_id and doc_id:
                case = find_case_by_any_identifier(user, case_id)
                if case:
                    doc = CaseDocument.query.filter_by(id=int(doc_id), case_id=case.id).first()
                    if doc:
                        entity_type = 'document'
                        entity_id = str(doc.id)

                        if doc.has_analysis():
                            analysis_job = AnalysisJob.query.filter_by(job_uuid=doc.analysis_job_id).first()
                            if analysis_job and analysis_job.results:
                                assistant_response = f"**Analysis of {doc.original_filename}:**\n\n{analysis_job.results.final_analysis[:1500]}..."
                            else:
                                assistant_response = f"Analysis exists but results not available."
                        else:
                            assistant_response = f"Document '{doc.original_filename}' hasn't been analyzed yet."
                    else:
                        assistant_response = f"Document #{doc_id} not found in Case #{case_id}."
                else:
                    assistant_response = f"Case #{case_id} not found or you don't have access."
            else:
                assistant_response = "Please specify a filename or document ID, e.g., 'analyze IMG_123.jpg' or 'analyze document 5 in case 1'"

        elif intent == 'general_help':
            assistant_response = """**EPOLaw AI Assistant - What I Can Do:**

**Case Operations:**
- **Case summaries:** "Summarize case 1234" or "Tell me about case 1"
- **Case timeline:** "Show timeline for case 444" or "Timeline for case 123"
- **List cases:** "What cases do I have?" or "Show my cases"
- **Filter by type:** "Show criminal cases" or "List litigation cases"
- **Search cases:** "Find cases about contracts" or "Search for Smith"
- **Search in case:** "Find negligence in case 123" or "Search case 1 for evidence"
- **Search all docs:** "Show documents with negligence" or "Documents with contract"

**Document Operations:**
- **List all documents:** "Show my documents" or "List all documents"
- **Analyze images:** "Analyze IMG_123.jpg" or "Analyze picture 10"
- **Analyze documents:** "Analyze contract.pdf" or "Analyze document 5 in case 1"
- **Summarize docs:** "Summarize document.pdf"
- **Batch analyze:** "Analyze all documents in case 123"
- **Batch summarize:** "Summarize all documents in case 456"
- **View by filename:** Just type the filename like "IMG_20250713_233516.jpg"

**View Summaries & Analyses:**
- **List summaries:** "Show my summaries" or "List all summaries"
- **List analyses:** "Show my analyses" or "List all analyses"

**Quick Case Edits:**
- **Add notes:** "Add note to case 123: Client called today"
- **Update status:** "Update case 456 status to settled"
- **Mark closed:** "Mark case 789 as closed"

**Legal Research:**
- **Ask legal questions:** "What is the statute of limitations for personal injury?"
- **Research legal topics:** "Explain Miranda rights" or "What are the elements of negligence?"
- **Get quick answers:** I'll provide a summary here with links to full research

**Tips:**
- You can use filenames directly - I'll find them for you!
- I'll show existing analyses if available
- For new analysis, I'll analyze images on the spot
- Document lists respect your permissions (confidential cases, team access)
- Quick edits save directly to the case!

Just ask in natural language and I'll help you navigate your legal work!"""

        else:
            # Unknown intent - check if there's a filename we can work with
            filename = extract_filename(user_message)

            if filename:
                # User mentioned a file but intent unclear - try to find and suggest actions
                doc = find_document_by_filename(user, filename)

                if doc:
                    # Found the document - determine likely action based on keywords
                    user_message_lower = user_message.lower()

                    if 'summarize' in user_message_lower or 'summary' in user_message_lower:
                        # User wants summary
                        assistant_response = get_document_summary(user, doc)
                        entity_type = 'document'
                        entity_id = str(doc.id)
                        action_type = 'summarize_document'
                    elif 'analyze' in user_message_lower or 'analysis' in user_message_lower:
                        # User wants analysis
                        is_image = doc.original_filename and any(
                            doc.original_filename.lower().endswith(ext)
                            for ext in ['.jpg', '.jpeg', '.png', '.gif', '.tif', '.tiff', '.bmp']
                        )
                        if is_image:
                            assistant_response = analyze_image_document(user, doc, user_message)
                        else:
                            if doc.has_analysis():
                                analysis_job = AnalysisJob.query.filter_by(job_uuid=doc.analysis_job_id).first()
                                if analysis_job and analysis_job.results:
                                    assistant_response = f"**Analysis of {doc.original_filename}:**\n\n{analysis_job.results.final_analysis[:1500]}..."
                                else:
                                    assistant_response = f"Analysis exists but results not available."
                            else:
                                analysis_url = f"/analysis/?case_id={doc.case_id}&document_id={doc.id}"
                                assistant_response = f"**{doc.original_filename}** hasn't been analyzed yet.\n\n[🔍 Click here to analyze this document]({analysis_url})"
                        entity_type = 'document'
                        entity_id = str(doc.id)
                        action_type = 'analyze_document'
                    else:
                        # Just show what we can do with this document
                        doc_url = f"/cases/{doc.case_id}/documents/{doc.id}/view"
                        summ_url = f"/summarization/?case_id={doc.case_id}&document_id={doc.id}"
                        analysis_url = f"/analysis/?case_id={doc.case_id}&document_id={doc.id}"

                        assistant_response = f"""Found **[{doc.original_filename}]({doc_url})** in case **{doc.case.case_name}**.

**Quick Actions:**
- [📝 Summarize]({summ_url}) - Create a summary
- [🔍 Analyze]({analysis_url}) - Get legal analysis
- [👁 View Document]({doc_url}) - Open the file

Or just type: "Summarize {filename}" or "Analyze {filename}" """
                        entity_type = 'document'
                        entity_id = str(doc.id)
                else:
                    assistant_response = f"""I couldn't find a document named "{filename}" in your accessible cases.

Try:
- "Show my documents" to see all available files
- Check the spelling of the filename
- Make sure you have access to the case containing this document"""
            else:
                # No filename detected - generic help
                assistant_response = f"""I'm not sure what you're asking for. Here are some things I can help with:

- Get case information: "Tell me about case 1234"
- List your cases: "Show my cases"
- Search cases: "Find cases about {user_message[:30]}"
- Show documents: "List my documents"

What would you like to do?"""

        # Save assistant response
        assistant_msg = AssistantMessage(
            conversation_id=conversation.id,
            message_type='assistant',
            message_text=assistant_response,
            action_type=action_type,
            entity_type=entity_type,
            entity_id=entity_id,
            msg_metadata=metadata
        )
        db.session.add(assistant_msg)

        # Update conversation timestamp
        conversation.updated_at = datetime.utcnow()

        db.session.commit()

        # Log activity
        log_activity(
            user_id=user.id,
            activity_type='assistant_query',
            description=f"Assistant query: {user_message[:100]}",
            entity_type='assistant_conversation',
            entity_id=conversation.id
        )

        return jsonify({
            'success': True,
            'conversation_id': conversation.conversation_uuid,
            'response': assistant_response,
            'intent': intent,
            'metadata': metadata if metadata else {
                'action_type': action_type,
                'entity_type': entity_type,
                'entity_id': entity_id
            }
        })

    except Exception as e:
        db.session.rollback()
        print(f"Assistant chat error: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({
            'error': 'An error occurred processing your request',
            'details': str(e)
        }), 500

@assistant_bp.route('/history', methods=['GET'])
@login_required
def get_history():
    """Get conversation history"""
    user_id = session.get('user_id')
    conversation_id = request.args.get('conversation_id')

    if conversation_id:
        conversation = AssistantConversation.query.filter_by(
            conversation_uuid=conversation_id,
            user_id=user_id
        ).first()

        if not conversation:
            return jsonify({'error': 'Conversation not found'}), 404

        messages = AssistantMessage.query.filter_by(
            conversation_id=conversation.id
        ).order_by(AssistantMessage.created_at).all()

        return jsonify({
            'conversation_id': conversation.conversation_uuid,
            'messages': [{
                'type': msg.message_type,
                'text': msg.message_text,
                'timestamp': msg.created_at.isoformat(),
                'action_type': msg.action_type
            } for msg in messages]
        })
    else:
        # List all conversations
        conversations = AssistantConversation.query.filter_by(
            user_id=user_id
        ).order_by(AssistantConversation.updated_at.desc()).limit(10).all()

        return jsonify({
            'conversations': [{
                'id': conv.conversation_uuid,
                'title': conv.title,
                'updated_at': conv.updated_at.isoformat(),
                'message_count': conv.messages.count()
            } for conv in conversations]
        })

@assistant_bp.route('/new', methods=['POST'])
@login_required
def new_conversation():
    """Start a new conversation"""
    return jsonify({'success': True})
