"""
Law Library Routes - Document repository for firm knowledge management
"""
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, send_file, abort, current_app, session
from werkzeug.utils import secure_filename
from sqlalchemy import or_, and_, func, text
from models import db, LawLibraryDocument, User, Subscription, SubscriptionPlan
from datetime import datetime
import os
import PyPDF2
import docx

law_library_bp = Blueprint('law_library', __name__, url_prefix='/law-library')

# Allowed file extensions
ALLOWED_EXTENSIONS = {'pdf', 'doc', 'docx', 'txt', 'rtf'}

def check_law_library_access():
    """Check if current user has access to Law Library"""
    user_id = session.get('user_id')
    if not user_id:
        return False, "Please log in to access the Law Library"

    user = User.query.get(user_id)
    if not user:
        return False, "User not found"

    # Get user's active subscription
    subscription = Subscription.query.filter_by(
        user_id=user_id,
        status='active'
    ).first()

    # Check plan features
    if subscription:
        plan = subscription.plan
        # Check if plan has law_library_access set to False
        if plan.features.get('law_library_access', False) == False:
            if plan.name == 'pro':
                return False, "Law Library access is not available with your Pro plan. Please upgrade to Enterprise for full access."
            else:
                return False, "Law Library access is not available with your Free plan. Please upgrade to Enterprise for full access."
    else:
        # Free users without subscription record
        return False, "Law Library access is only available with an Enterprise subscription. Please upgrade to access this feature."

    # Only Enterprise plans have access
    return True, None

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def extract_text_from_file(file_path, file_extension):
    """
    Extract text from uploaded document for full-text search indexing

    IMPORTANT: This text is stored in the database and indexed with company_id
    to ensure search results are isolated per company.
    """
    text = ""
    try:
        if file_extension == 'pdf':
            with open(file_path, 'rb') as file:
                pdf_reader = PyPDF2.PdfReader(file)
                for page in pdf_reader.pages:
                    page_text = page.extract_text()
                    if page_text:
                        text += page_text + "\n"
        elif file_extension == 'txt':
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as file:
                text = file.read()
        elif file_extension in ['doc', 'docx']:
            doc = docx.Document(file_path)
            for paragraph in doc.paragraphs:
                if paragraph.text:
                    text += paragraph.text + "\n"
            # Also extract text from tables
            for table in doc.tables:
                for row in table.rows:
                    for cell in row.cells:
                        if cell.text:
                            text += cell.text + " "
                text += "\n"
        elif file_extension == 'rtf':
            # RTF files - read as text (basic extraction)
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as file:
                text = file.read()
    except Exception as e:
        current_app.logger.error(f"Error extracting text from {file_path}: {e}")
        print(f"Error extracting text: {e}")

    # Limit to 1 million characters for storage (~1MB of text)
    # Database uses MEDIUMTEXT which supports up to 16MB
    return text[:1000000].strip()

@law_library_bp.route('/')
def library_home():
    """Main law library page with search and browse"""
    # Check Law Library access
    has_access, error_msg = check_law_library_access()
    if not has_access:
        flash(error_msg, 'warning')
        return redirect(url_for('dashboard' if session.get('user_id') else 'auth.login'))

    user_id = session.get('user_id')
    user = User.query.get(user_id)
    
    # Get search parameters
    search_query = request.args.get('q', '')
    doc_type = request.args.get('type', '')
    practice_area = request.args.get('practice', '')
    court = request.args.get('court', '')
    
    # Base query - only documents from user's company (CRITICAL: ensures data isolation)
    query = LawLibraryDocument.query.filter_by(company_id=user.company_id)

    # Apply search filter with FULLTEXT search for better performance
    if search_query:
        # Use MySQL FULLTEXT search for better performance and relevance ranking
        # IMPORTANT: company_id filter is applied FIRST to ensure data isolation
        query = query.filter(
            text("MATCH(title, description, keywords, content_text, case_name) AGAINST(:search_term IN NATURAL LANGUAGE MODE)")
        ).params(search_term=search_query)
        # Order by relevance score
        query = query.order_by(
            text("MATCH(title, description, keywords, content_text, case_name) AGAINST(:search_term IN NATURAL LANGUAGE MODE) DESC")
        ).params(search_term=search_query)
    
    if doc_type:
        query = query.filter_by(document_type=doc_type)
    
    if practice_area:
        query = query.filter_by(practice_area=practice_area)
    
    if court:
        query = query.filter(LawLibraryDocument.court.ilike(f"%{court}%"))

    # Order by relevance (if searching) or most recent
    if not search_query:
        # No search query - order by most recent
        query = query.order_by(LawLibraryDocument.uploaded_at.desc())

    # Execute query with limit
    documents = query.limit(100).all()
    
    # Get unique values for filter dropdowns
    doc_types = db.session.query(LawLibraryDocument.document_type).filter_by(
        company_id=user.company_id
    ).distinct().all()
    doc_types = [t[0] for t in doc_types if t[0]]
    
    practice_areas = db.session.query(LawLibraryDocument.practice_area).filter_by(
        company_id=user.company_id
    ).distinct().all()
    practice_areas = [p[0] for p in practice_areas if p[0]]
    
    courts = db.session.query(LawLibraryDocument.court).filter_by(
        company_id=user.company_id
    ).distinct().all()
    courts = [c[0] for c in courts if c[0]]
    
    # Get statistics
    total_docs = LawLibraryDocument.query.filter_by(company_id=user.company_id).count()
    
    return render_template('law_library/home.html',
                         documents=documents,
                         search_query=search_query,
                         doc_types=doc_types,
                         practice_areas=practice_areas,
                         courts=courts,
                         selected_type=doc_type,
                         selected_practice=practice_area,
                         selected_court=court,
                         total_docs=total_docs)

@law_library_bp.route('/upload', methods=['GET', 'POST'])
def upload_document():
    """Upload a document to the law library"""
    # Check Law Library access
    has_access, error_msg = check_law_library_access()
    if not has_access:
        flash(error_msg, 'warning')
        return redirect(url_for('dashboard' if session.get('user_id') else 'auth.login'))

    user_id = session.get('user_id')
    user = User.query.get(user_id)
    
    if request.method == 'POST':
        # Check if file is provided
        if 'file' not in request.files:
            flash('No file provided', 'danger')
            return redirect(request.url)
        
        file = request.files['file']
        if file.filename == '':
            flash('No file selected', 'danger')
            return redirect(request.url)
        
        if file and allowed_file(file.filename):
            # Create secure filename
            filename = secure_filename(file.filename)
            timestamp = datetime.utcnow().timestamp()
            unique_filename = f"lawlib_{user.company_id}_{timestamp}_{filename}"
            
            # Ensure upload directory exists
            upload_dir = os.path.join(current_app.config.get('UPLOAD_FOLDER', 'uploads'), 'law_library')
            if not os.path.exists(upload_dir):
                os.makedirs(upload_dir)
            
            file_path = os.path.join(upload_dir, unique_filename)
            file.save(file_path)
            
            # Get file extension
            file_extension = filename.rsplit('.', 1)[1].lower()
            
            # Extract text for searching
            content_text = extract_text_from_file(file_path, file_extension)
            
            # Parse date if provided
            date_filed = None
            if request.form.get('date_filed'):
                try:
                    date_filed = datetime.strptime(request.form.get('date_filed'), '%Y-%m-%d').date()
                except:
                    pass
            
            # Create document record
            document = LawLibraryDocument(
                company_id=user.company_id,
                title=request.form.get('title', filename),
                document_type=request.form.get('document_type'),
                description=request.form.get('description'),
                filename=unique_filename,
                original_filename=filename,
                file_path=file_path,
                file_size=os.path.getsize(file_path),
                case_name=request.form.get('case_name'),
                case_number=request.form.get('case_number'),
                court=request.form.get('court'),
                judge=request.form.get('judge'),
                date_filed=date_filed,
                practice_area=request.form.get('practice_area'),
                outcome=request.form.get('outcome'),
                opposing_party=request.form.get('opposing_party'),
                opposing_counsel=request.form.get('opposing_counsel'),
                keywords=request.form.get('keywords'),
                content_text=content_text,
                uploaded_by_id=user_id,
                uploaded_at=datetime.utcnow()
            )
            
            # Parse and save tags if provided
            tags_input = request.form.get('tags', '')
            if tags_input:
                tags = [tag.strip() for tag in tags_input.split(',') if tag.strip()]
                document.tags = tags
            
            db.session.add(document)
            db.session.commit()
            
            flash(f'Document "{document.title}" uploaded successfully to the law library', 'success')
            return redirect(url_for('law_library.library_home'))
        else:
            flash('Invalid file type. Allowed types: PDF, DOC, DOCX, TXT, RTF', 'danger')
    
    return render_template('law_library/upload.html')

@law_library_bp.route('/document/<int:doc_id>')
def view_document(doc_id):
    """View document details"""
    # Check Law Library access
    has_access, error_msg = check_law_library_access()
    if not has_access:
        flash(error_msg, 'warning')
        return redirect(url_for('dashboard' if session.get('user_id') else 'auth.login'))

    user_id = session.get('user_id')
    user = User.query.get(user_id)
    
    document = LawLibraryDocument.query.get_or_404(doc_id)
    
    # Check access
    if document.company_id != user.company_id:
        abort(403)
    
    # Increment access count
    document.increment_access()
    
    # Get related documents (same case or similar type)
    related = LawLibraryDocument.query.filter(
        LawLibraryDocument.company_id == user.company_id,
        LawLibraryDocument.id != doc_id,
        or_(
            LawLibraryDocument.case_number == document.case_number,
            LawLibraryDocument.document_type == document.document_type
        )
    ).limit(5).all()
    
    return render_template('law_library/view.html', 
                         document=document, 
                         related=related)

@law_library_bp.route('/document/<int:doc_id>/download')
def download_document(doc_id):
    """Download a document from the library"""
    user_id = session.get('user_id')
    if not user_id:
        flash('Please log in to access the Law Library', 'warning')
        return redirect(url_for('auth.login'))
    user = User.query.get(user_id)
    
    document = LawLibraryDocument.query.get_or_404(doc_id)
    
    # Check access
    if document.company_id != user.company_id:
        abort(403)
    
    # Check if file exists
    if not document.file_path or not os.path.exists(document.file_path):
        flash('Document file not found', 'danger')
        return redirect(url_for('law_library.library_home'))
    
    # Increment access count
    document.increment_access()
    
    return send_file(
        document.file_path,
        as_attachment=True,
        download_name=document.original_filename
    )

@law_library_bp.route('/document/<int:doc_id>/delete', methods=['POST'])
def delete_document(doc_id):
    """Delete a document from the library"""
    user_id = session.get('user_id')
    if not user_id:
        flash('Please log in to access the Law Library', 'warning')
        return redirect(url_for('auth.login'))
    user = User.query.get(user_id)
    
    document = LawLibraryDocument.query.get_or_404(doc_id)
    
    # Check access (only uploader or admin can delete)
    if document.company_id != user.company_id:
        abort(403)
    
    if document.uploaded_by_id != user_id and not user.is_company_admin():
        flash('You do not have permission to delete this document', 'danger')
        return redirect(url_for('law_library.view_document', doc_id=doc_id))
    
    # Delete file from filesystem
    if document.file_path and os.path.exists(document.file_path):
        try:
            os.remove(document.file_path)
        except:
            pass
    
    # Delete database record
    db.session.delete(document)
    db.session.commit()
    
    flash(f'Document "{document.title}" deleted successfully', 'success')
    return redirect(url_for('law_library.library_home'))

@law_library_bp.route('/api/search')
def api_search():
    """API endpoint for document search (for AJAX calls)"""
    user_id = session.get('user_id')
    if not user_id:
        return jsonify({'error': 'Authentication required'}), 401
    user = User.query.get(user_id)
    
    search_query = request.args.get('q', '')
    
    if not search_query:
        return jsonify([])
    
    search_term = f"%{search_query}%"
    documents = LawLibraryDocument.query.filter(
        LawLibraryDocument.company_id == user.company_id,
        or_(
            LawLibraryDocument.title.ilike(search_term),
            LawLibraryDocument.case_name.ilike(search_term),
            LawLibraryDocument.keywords.ilike(search_term)
        )
    ).limit(10).all()
    
    results = [{
        'id': doc.id,
        'title': doc.title,
        'type': doc.document_type,
        'case_name': doc.case_name,
        'date': doc.date_filed.strftime('%Y-%m-%d') if doc.date_filed else None
    } for doc in documents]
    
    return jsonify(results)