"""
Case Management API for AI Lawyer
Flask Blueprint for case-specific document management
This is a separate module that can be added without affecting the main service
"""

from flask import Blueprint, request, jsonify
from functools import wraps
import os
import traceback
from datetime import datetime
from pathlib import Path

# Import models and processor
try:
    from models import (
        get_session, Case, CaseDocument, DocumentChunk,
        CaseQuery, CaseMetadata, User, init_db
    )
    from case_processor import CaseDocumentProcessor
    MODELS_AVAILABLE = True
except ImportError as e:
    print(f"[Case API] Models not available: {e}")
    MODELS_AVAILABLE = False

# Create Blueprint
case_bp = Blueprint('cases', __name__, url_prefix='/cases')

# Simple API key check (uses same key as main service)
CASE_API_KEY = os.environ.get('FLASK_API_KEY', 'eventheodds-flask-api-key-2025')


def require_case_api_key(f):
    """Decorator to require API key for case endpoints"""
    @wraps(f)
    def decorated(*args, **kwargs):
        api_key = request.headers.get('X-API-Key', '')
        if api_key != CASE_API_KEY:
            return jsonify({'error': 'Invalid API key'}), 401
        return f(*args, **kwargs)
    return decorated


def get_or_create_user_id(session, email: str = None) -> int:
    """Get or create a user and return user ID"""
    email = email or 'default@eventheodds.ai'
    user = session.query(User).filter_by(email=email).first()
    if not user:
        user = User(email=email)
        session.add(user)
        session.commit()
        session.refresh(user)
    return user.id


# ============================================================================
# Case Management Endpoints
# ============================================================================

@case_bp.route('/create', methods=['POST'])
@require_case_api_key
def create_case():
    """Create a new case"""
    if not MODELS_AVAILABLE:
        return jsonify({'error': 'Case management not available'}), 503

    try:
        data = request.get_json(silent=True) or {}
        name = data.get('name')

        if not name:
            return jsonify({'error': 'Case name is required'}), 400

        session = get_session()
        try:
            user_id = get_or_create_user_id(session, data.get('email'))

            case = Case(
                user_id=user_id,
                name=name,
                description=data.get('description'),
                jurisdiction=data.get('jurisdiction'),
                case_number=data.get('case_number'),
                area_of_law=data.get('area_of_law')
            )

            session.add(case)
            session.commit()

            # Create metadata record
            case_meta = CaseMetadata(case_id=case.id)
            session.add(case_meta)
            session.commit()

            return jsonify({
                'success': True,
                'case_id': case.case_uuid,
                'name': case.name,
                'message': 'Case created successfully'
            })
        finally:
            session.close()

    except Exception as e:
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500


@case_bp.route('/list', methods=['GET'])
@require_case_api_key
def list_cases():
    """List all cases for the user"""
    if not MODELS_AVAILABLE:
        return jsonify({'error': 'Case management not available'}), 503

    try:
        session = get_session()
        try:
            user_id = get_or_create_user_id(session)
            cases = session.query(Case).filter_by(user_id=user_id).all()

            return jsonify({
                'success': True,
                'cases': [
                    {
                        'case_id': c.case_uuid,
                        'name': c.name,
                        'jurisdiction': c.jurisdiction,
                        'area_of_law': c.area_of_law,
                        'status': c.status,
                        'document_count': len(c.documents),
                        'created_at': c.created_at.isoformat() if c.created_at else None
                    }
                    for c in cases
                ]
            })
        finally:
            session.close()

    except Exception as e:
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500


@case_bp.route('/<case_uuid>', methods=['GET'])
@require_case_api_key
def get_case(case_uuid):
    """Get case details"""
    if not MODELS_AVAILABLE:
        return jsonify({'error': 'Case management not available'}), 503

    try:
        session = get_session()
        try:
            case = session.query(Case).filter_by(case_uuid=case_uuid).first()
            if not case:
                return jsonify({'error': 'Case not found'}), 404

            # Get metadata
            metadata = {}
            if case.metadata_record:
                metadata = {
                    'parties': case.metadata_record.parties or {},
                    'key_dates': case.metadata_record.key_dates or {},
                    'claims': case.metadata_record.claims or [],
                    'key_issues': case.metadata_record.key_issues or []
                }

            return jsonify({
                'success': True,
                'case': {
                    'case_id': case.case_uuid,
                    'name': case.name,
                    'description': case.description,
                    'jurisdiction': case.jurisdiction,
                    'case_number': case.case_number,
                    'area_of_law': case.area_of_law,
                    'status': case.status,
                    'created_at': case.created_at.isoformat() if case.created_at else None,
                    'document_count': len(case.documents),
                    'metadata': metadata
                }
            })
        finally:
            session.close()

    except Exception as e:
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500


@case_bp.route('/<case_uuid>/upload', methods=['POST'])
@require_case_api_key
def upload_case_document(case_uuid):
    """Upload a document to a specific case"""
    if not MODELS_AVAILABLE:
        return jsonify({'error': 'Case management not available'}), 503

    try:
        if 'file' not in request.files:
            return jsonify({'error': 'No file provided'}), 400

        file = request.files['file']
        if file.filename == '':
            return jsonify({'error': 'No file selected'}), 400

        session = get_session()
        try:
            case = session.query(Case).filter_by(case_uuid=case_uuid).first()
            if not case:
                return jsonify({'error': 'Case not found'}), 404

            # Get document type from form
            document_type = request.form.get('document_type', 'auto')

            # Read file content
            file_content = file.read()

            # Process document
            processor = CaseDocumentProcessor(
                case_uuid=case_uuid,
                user_id=case.user_id
            )

            result = processor.process_upload(
                file_content=file_content,
                filename=file.filename,
                document_type=document_type if document_type != 'auto' else None
            )

            if not result.get('success'):
                return jsonify({
                    'error': result.get('error', 'Processing failed')
                }), 400

            # Create database record
            case_doc = CaseDocument(
                case_id=case.id,
                filename=result['filename'],
                original_filename=result['original_filename'],
                file_type=result['file_type'],
                file_size=result['file_size'],
                file_hash=result['file_hash'],
                document_type=result['document_type'],
                category=result['category'],
                processing_status='completed',
                chunk_count=result['chunk_count']
            )

            session.add(case_doc)
            session.commit()

            # Store chunks in database
            for chunk_data in result['chunks']:
                chunk = DocumentChunk(
                    document_id=case_doc.id,
                    chunk_index=chunk_data['chunk_index'],
                    content=chunk_data['content'],
                    content_length=chunk_data['content_length'],
                    page_number=chunk_data.get('page'),
                    start_char=chunk_data.get('start_char')
                )
                session.add(chunk)

            session.commit()

            # Update case metadata if parties were extracted
            if result['metadata'].get('parties'):
                if case.metadata_record:
                    existing_parties = case.metadata_record.parties or {}
                    existing_parties.update(result['metadata']['parties'])
                    case.metadata_record.parties = existing_parties
                    session.commit()

            return jsonify({
                'success': True,
                'document_id': case_doc.id,
                'filename': result['original_filename'],
                'document_type': result['document_type'],
                'category': result['category'],
                'chunks_created': result['chunk_count'],
                'metadata_extracted': result['metadata'],
                'message': f"Document processed: {result['chunk_count']} chunks created"
            })

        finally:
            session.close()

    except Exception as e:
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500


@case_bp.route('/<case_uuid>/documents', methods=['GET'])
@require_case_api_key
def get_case_documents(case_uuid):
    """Get all documents for a case"""
    if not MODELS_AVAILABLE:
        return jsonify({'error': 'Case management not available'}), 503

    try:
        session = get_session()
        try:
            case = session.query(Case).filter_by(case_uuid=case_uuid).first()
            if not case:
                return jsonify({'error': 'Case not found'}), 404

            documents = session.query(CaseDocument).filter_by(case_id=case.id).all()

            return jsonify({
                'success': True,
                'case_id': case_uuid,
                'documents': [
                    {
                        'id': doc.id,
                        'filename': doc.original_filename,
                        'document_type': doc.document_type,
                        'category': doc.category,
                        'file_size': doc.file_size,
                        'chunk_count': doc.chunk_count,
                        'processing_status': doc.processing_status,
                        'upload_date': doc.upload_date.isoformat() if doc.upload_date else None
                    }
                    for doc in documents
                ]
            })
        finally:
            session.close()

    except Exception as e:
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500


@case_bp.route('/<case_uuid>/query', methods=['POST'])
@require_case_api_key
def query_case(case_uuid):
    """Query a specific case's documents"""
    if not MODELS_AVAILABLE:
        return jsonify({'error': 'Case management not available'}), 503

    try:
        data = request.get_json(silent=True) or {}
        query_text = data.get('query', '').strip()

        if not query_text:
            return jsonify({'error': 'Query is required'}), 400

        query_type = data.get('query_type', 'general')

        session = get_session()
        try:
            case = session.query(Case).filter_by(case_uuid=case_uuid).first()
            if not case:
                return jsonify({'error': 'Case not found'}), 404

            # Get all chunks for this case
            chunks = []
            for doc in case.documents:
                doc_chunks = session.query(DocumentChunk).filter_by(document_id=doc.id).all()
                for chunk in doc_chunks:
                    chunks.append({
                        'content': chunk.content,
                        'document': doc.original_filename,
                        'document_type': doc.document_type,
                        'page': chunk.page_number,
                        'section': chunk.summary if chunk.summary else 'content'
                    })

            if not chunks:
                return jsonify({
                    'success': True,
                    'answer': 'No documents have been uploaded to this case yet. Please upload case documents first.',
                    'sources': [],
                    'chunks_searched': 0
                })

            # Simple keyword search for now (can be enhanced with vector search)
            query_lower = query_text.lower()
            query_words = set(query_lower.split())

            scored_chunks = []
            for chunk in chunks:
                content_lower = chunk['content'].lower()
                score = sum(1 for word in query_words if word in content_lower)
                if score > 0:
                    scored_chunks.append((score, chunk))

            # Sort by score and get top results
            scored_chunks.sort(key=lambda x: x[0], reverse=True)
            top_chunks = [c[1] for c in scored_chunks[:5]]

            # Build context from top chunks
            context = "\n\n---\n\n".join([
                f"[{c['document']} - {c['document_type']} - Page {c['page']}]\n{c['content'][:1500]}"
                for c in top_chunks
            ])

            # Generate response (simplified - in production, call LLM)
            if top_chunks:
                sources = [
                    {
                        'document': c['document'],
                        'document_type': c['document_type'],
                        'page': c['page']
                    }
                    for c in top_chunks
                ]

                # For now, return the relevant chunks as context
                # In production, this would call Grok/DeepSeek for synthesis
                answer = f"Based on the case documents:\n\n"
                for c in top_chunks[:3]:
                    answer += f"**{c['document']}** (Page {c['page']}):\n"
                    answer += f"{c['content'][:500]}...\n\n"
            else:
                answer = "No relevant information found in the case documents for this query."
                sources = []

            # Store query in history
            case_query = CaseQuery(
                case_id=case.id,
                query_text=query_text,
                query_type=query_type,
                response=answer,
                sources=sources,
                chunks_searched=len(chunks)
            )
            session.add(case_query)
            session.commit()

            return jsonify({
                'success': True,
                'answer': answer,
                'sources': sources,
                'query_type': query_type,
                'chunks_searched': len(chunks),
                'relevant_chunks': len(top_chunks)
            })

        finally:
            session.close()

    except Exception as e:
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500


@case_bp.route('/<case_uuid>/delete', methods=['DELETE', 'POST'])
@require_case_api_key
def delete_case(case_uuid):
    """Delete a case and all its documents"""
    if not MODELS_AVAILABLE:
        return jsonify({'error': 'Case management not available'}), 503

    try:
        session = get_session()
        try:
            case = session.query(Case).filter_by(case_uuid=case_uuid).first()
            if not case:
                return jsonify({'error': 'Case not found'}), 404

            case_name = case.name
            session.delete(case)
            session.commit()

            return jsonify({
                'success': True,
                'message': f'Case "{case_name}" deleted successfully'
            })
        finally:
            session.close()

    except Exception as e:
        traceback.print_exc()
        return jsonify({'error': str(e)}), 500


# Initialize database when module loads
if MODELS_AVAILABLE:
    try:
        init_db()
        print("[Case API] Database initialized")
    except Exception as e:
        print(f"[Case API] Database initialization error: {e}")
