"""
References UI views - Server-rendered templates for Reference Section
"""
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.core.paginator import Paginator
from django.db.models import Q
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, render, redirect
from django.views.decorators.http import require_http_methods

from apps.references.models import ReferenceFolder, ReferenceDocument
from apps.references.forms import ReferenceFolderForm, ReferenceDocumentForm, ReferenceDocumentSearchForm


@login_required
def reference_dashboard(request):
    """
    Reference dashboard - Main entry point for Reference Section.

    Shows:
    - Root folders
    - Recent documents
    - Quick search
    - Statistics
    """
    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        return render(request, 'core/no_hospital_assigned.html')

    # Get root folders (no parent)
    folders = ReferenceFolder.objects.filter(
        hospital=hospital,
        parent=None,
        is_active=True,
        is_deleted=False
    ).order_by('order', 'name')

    # Filter by access
    folders = [f for f in folders if f.has_access(request.user)]

    # Get recent documents (last 10)
    recent_documents = ReferenceDocument.objects.filter(
        hospital=hospital,
        is_published=True,
        is_deleted=False
    ).select_related('folder').order_by('-created_at')[:10]

    # Filter by access
    recent_documents = [d for d in recent_documents if d.has_access(request.user)]

    # Statistics
    total_folders = ReferenceFolder.objects.filter(
        hospital=hospital,
        is_active=True,
        is_deleted=False
    ).count()

    total_documents = ReferenceDocument.objects.filter(
        hospital=hospital,
        is_published=True,
        is_deleted=False
    ).count()

    context = {
        'folders': folders,
        'recent_documents': recent_documents,
        'total_folders': total_folders,
        'total_documents': total_documents,
    }

    return render(request, 'references/dashboard.html', context)


@login_required
def folder_view(request, pk=None):
    """
    Folder view - Browse folders and documents.

    If pk is provided, shows contents of that folder.
    Otherwise, shows root level folders.
    """
    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        return render(request, 'core/no_hospital_assigned.html')

    current_folder = None
    breadcrumb = []
    subfolders = []
    documents = []

    if pk:
        current_folder = get_object_or_404(
            ReferenceFolder,
            pk=pk,
            hospital=hospital,
            is_deleted=False
        )

        # Check access
        if not current_folder.has_access(request.user):
            messages.error(request, "You don't have permission to access this folder.")
            return redirect('references:dashboard')

        # Build breadcrumb
        breadcrumb = []
        folder = current_folder
        while folder:
            breadcrumb.insert(0, folder)
            folder = folder.parent

        # Get subfolders
        subfolders = current_folder.get_subfolders()
        subfolders = [f for f in subfolders if f.has_access(request.user)]

        # Get documents
        documents = current_folder.get_documents()
        documents = [d for d in documents if d.has_access(request.user)]
    else:
        # Root level - show root folders
        subfolders = ReferenceFolder.objects.filter(
            hospital=hospital,
            parent=None,
            is_active=True,
            is_deleted=False
        ).order_by('order', 'name')

        subfolders = [f for f in subfolders if f.has_access(request.user)]

    context = {
        'current_folder': current_folder,
        'breadcrumb': breadcrumb,
        'subfolders': subfolders,
        'documents': documents,
    }

    return render(request, 'references/folder_view.html', context)


@login_required
@require_http_methods(["GET", "POST"])
def folder_create(request, parent_pk=None):
    """Create a new folder"""
    if request.user.is_px_employee() and not (request.user.is_px_admin() or request.user.is_hospital_admin() or request.user.is_department_manager()):
        messages.error(request, "You do not have permission to create folders. View-only access.")
        return redirect('references:dashboard')

    if request.user.is_px_management() and not (request.user.is_px_admin() or request.user.is_hospital_admin() or request.user.is_department_manager()):
        messages.error(request, "You do not have permission to create folders. View-only access.")
        return redirect('references:dashboard')

    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        messages.error(request, "No hospital assigned.")
        return redirect('references:dashboard')

    parent = None
    if parent_pk:
        parent = get_object_or_404(ReferenceFolder, pk=parent_pk, hospital=hospital, is_deleted=False)
        if not parent.has_access(request.user):
            messages.error(request, "You don't have permission to access this folder.")
            return redirect('references:dashboard')

    if request.method == 'POST':
        form = ReferenceFolderForm(request.POST, hospital=hospital)
        if form.is_valid():
            folder = form.save(commit=False)
            folder.hospital = hospital
            folder.parent = parent
            folder.save()
            form.save_m2m()

            messages.success(request, f"Folder '{folder.name}' created successfully.")
            if parent:
                return redirect('references:folder_view', pk=parent_pk)
            return redirect('references:dashboard')
    else:
        form = ReferenceFolderForm(hospital=hospital)
        if parent:
            form.fields['parent'].initial = parent

    # Get all folders for parent dropdown with level info
    all_folders = []
    for f in ReferenceFolder.objects.filter(hospital=hospital, is_deleted=False):
        level = 0
        temp = f
        while temp.parent:
            level += 1
            temp = temp.parent
        # Create a display string with appropriate number of dashes
        f.level_display = '—' * level
        all_folders.append(f)

    context = {
        'form': form,
        'folder': None,
        'parent': parent,
        'all_folders': all_folders,
    }

    return render(request, 'references/folder_form.html', context)


@login_required
@require_http_methods(["GET", "POST"])
def folder_edit(request, pk):
    """Edit a folder"""
    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        messages.error(request, "No hospital assigned.")
        return redirect('references:dashboard')

    folder = get_object_or_404(ReferenceFolder, pk=pk, hospital=hospital, is_deleted=False)

    # Check access
    if not folder.has_access(request.user):
        messages.error(request, "You don't have permission to edit this folder.")
        return redirect('references:dashboard')

    if request.method == 'POST':
        form = ReferenceFolderForm(request.POST, instance=folder, hospital=hospital)
        if form.is_valid():
            form.save()
            messages.success(request, f"Folder '{folder.name}' updated successfully.")
            if folder.parent:
                return redirect('references:folder_view', pk=folder.parent.id)
            return redirect('references:dashboard')
    else:
        form = ReferenceFolderForm(instance=folder, hospital=hospital)

    # Get all folders for parent dropdown with level info
    all_folders = []
    for f in ReferenceFolder.objects.filter(hospital=hospital, is_deleted=False):
        level = 0
        temp = f
        while temp.parent:
            level += 1
            temp = temp.parent
        # Create a display string with appropriate number of dashes
        f.level_display = '—' * level
        all_folders.append(f)

    context = {
        'form': form,
        'folder': folder,
        'all_folders': all_folders,
    }

    return render(request, 'references/folder_form.html', context)


@login_required
@require_http_methods(["POST"])
def folder_delete(request, pk):
    """Soft delete a folder"""
    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        return JsonResponse({'success': False, 'error': 'No hospital assigned'}, status=400)

    folder = get_object_or_404(ReferenceFolder, pk=pk, hospital=hospital, is_deleted=False)

    # Check access
    if not folder.has_access(request.user):
        return JsonResponse({'success': False, 'error': 'Permission denied'}, status=403)

    # Soft delete
    folder.is_deleted = True
    folder.save()

    return JsonResponse({'success': True})


@login_required
def document_view(request, pk):
    """Document detail view"""
    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        return render(request, 'core/no_hospital_assigned.html')

    document = get_object_or_404(
        ReferenceDocument.objects.select_related('folder', 'uploaded_by'),
        pk=pk,
        hospital=hospital,
        is_deleted=False
    )

    # Check access
    if not document.has_access(request.user):
        messages.error(request, "You don't have permission to access this document.")
        return redirect('references:dashboard')

    # Get version history
    versions = document.get_version_history()

    # Get related documents (same folder)
    related_documents = []
    if document.folder:
        related_documents = ReferenceDocument.objects.filter(
            folder=document.folder,
            is_published=True,
            is_deleted=False
        ).exclude(pk=document.pk)[:5]
        related_documents = [d for d in related_documents if d.has_access(request.user)]

    context = {
        'document': document,
        'versions': versions,
        'related_documents': related_documents,
    }

    return render(request, 'references/document_view.html', context)


@login_required
@require_http_methods(["GET", "POST"])
def document_create(request, folder_pk=None):
    """Upload a new document"""
    if request.user.is_px_employee() and not (request.user.is_px_admin() or request.user.is_hospital_admin() or request.user.is_department_manager()):
        messages.error(request, "You do not have permission to upload documents. View-only access.")
        return redirect('references:dashboard')

    if request.user.is_px_management() and not (request.user.is_px_admin() or request.user.is_hospital_admin() or request.user.is_department_manager()):
        messages.error(request, "You do not have permission to upload documents. View-only access.")
        return redirect('references:dashboard')

    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        messages.error(request, "No hospital assigned.")
        return redirect('references:dashboard')

    folder = None
    if folder_pk:
        folder = get_object_or_404(ReferenceFolder, pk=folder_pk, hospital=hospital, is_deleted=False)
        if not folder.has_access(request.user):
            messages.error(request, "You don't have permission to access this folder.")
            return redirect('references:dashboard')

    if request.method == 'POST':
        form = ReferenceDocumentForm(request.POST, request.FILES, hospital=hospital, folder=folder)
        if 'file' in request.FILES and request.FILES['file'].size > 100 * 1024 * 1024:
            messages.error(request, "File size exceeds the 100MB limit.")
        elif form.is_valid():
            document = form.save(commit=False)
            document.hospital = hospital
            document.folder = form.cleaned_data.get('folder') or folder
            document.uploaded_by = request.user
            if 'file' in request.FILES:
                document.filename = request.FILES['file'].name
            document.save()
            form.save_m2m()

            messages.success(request, f"Document '{document.title}' uploaded successfully.")
            if document.folder:
                return redirect('references:folder_view', pk=document.folder.id)
            return redirect('references:dashboard')
        else:
            messages.error(request, "Please fix the errors below to upload the document.")
    else:
        form = ReferenceDocumentForm(hospital=hospital, folder=folder)

    # Get all folders for dropdown with level info
    all_folders = []
    for f in ReferenceFolder.objects.filter(hospital=hospital, is_deleted=False):
        level = 0
        temp = f
        while temp.parent:
            level += 1
            temp = temp.parent
        # Create a display string with appropriate number of dashes
        f.level_display = '—' * level
        all_folders.append(f)

    context = {
        'form': form,
        'folder': folder,
        'all_folders': all_folders,
    }

    return render(request, 'references/document_form.html', context)


@login_required
@require_http_methods(["GET", "POST"])
def document_edit(request, pk):
    """Edit a document"""
    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        messages.error(request, "No hospital assigned.")
        return redirect('references:dashboard')

    document = get_object_or_404(ReferenceDocument, pk=pk, hospital=hospital, is_deleted=False)

    # Check access
    if not document.has_access(request.user):
        messages.error(request, "You don't have permission to edit this document.")
        return redirect('references:dashboard')

    if request.method == 'POST':
        form = ReferenceDocumentForm(request.POST, request.FILES, instance=document, hospital=hospital)
        file = request.FILES.get('file')
        if file and file.size > 100 * 1024 * 1024:
            messages.error(request, "File size exceeds the 100MB limit.")
        elif form.is_valid():
            new_version = form.cleaned_data.get('new_version')

            if new_version and file:
                # Create new version
                old_document = document
                document.pk = None  # Create new instance
                document.parent_document = old_document
                document.uploaded_by = request.user
                document.filename = file.name
                document.save()
                form.save_m2m()

                # Mark old version as not latest
                old_document.is_latest_version = False
                old_document.save()

                messages.success(request, f"New version '{document.title}' created successfully.")
            else:
                # Just update metadata
                if file:
                    document.filename = file.name
                form.save()
                messages.success(request, f"Document '{document.title}' updated successfully.")

            return redirect('references:document_view', pk=document.id)
    else:
        form = ReferenceDocumentForm(instance=document, hospital=hospital)

    # Get all folders for dropdown with level info
    all_folders = []
    for f in ReferenceFolder.objects.filter(hospital=hospital, is_deleted=False):
        level = 0
        temp = f
        while temp.parent:
            level += 1
            temp = temp.parent
        # Create a display string with appropriate number of dashes
        f.level_display = '—' * level
        all_folders.append(f)

    context = {
        'form': form,
        'document': document,
        'all_folders': all_folders,
    }

    return render(request, 'references/document_form.html', context)


@login_required
@require_http_methods(["POST"])
def document_delete(request, pk):
    """Soft delete a document"""
    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        return JsonResponse({'success': False, 'error': 'No hospital assigned'}, status=400)

    document = get_object_or_404(ReferenceDocument, pk=pk, hospital=hospital, is_deleted=False)

    # Check access
    if not document.has_access(request.user):
        return JsonResponse({'success': False, 'error': 'Permission denied'}, status=403)

    # Soft delete
    document.is_deleted = True
    document.save()

    return JsonResponse({'success': True})


@login_required
def search(request):
    """
    Search documents across all folders.
    """
    # Get current hospital - use tenant_hospital for PX admins, user.hospital for regular users
    hospital = getattr(request, 'tenant_hospital', None) or request.user.hospital
    if not hospital:
        return render(request, 'core/no_hospital_assigned.html')

    form = ReferenceDocumentSearchForm(request.GET or None, hospital=hospital)
    documents = []

    if form.is_valid():
        documents = ReferenceDocument.objects.filter(
            hospital=hospital,
            is_published=True,
            is_deleted=False
        ).select_related('folder')

        # Apply filters
        search = form.cleaned_data.get('search')
        if search:
            documents = documents.filter(
                Q(title__icontains=search) |
                Q(title_ar__icontains=search) |
                Q(description__icontains=search) |
                Q(description_ar__icontains=search) |
                Q(tags__icontains=search)
            )

        folder = form.cleaned_data.get('folder')
        if folder:
            documents = documents.filter(folder=folder)

        file_type = form.cleaned_data.get('file_type')
        if file_type:
            documents = documents.filter(file_type__iexact=file_type)

        tags = form.cleaned_data.get('tags')
        if tags:
            tag_list = [tag.strip() for tag in tags.split(',')]
            for tag in tag_list:
                documents = documents.filter(tags__icontains=tag)

        # Filter by access
        documents = [d for d in documents if d.has_access(request.user)]

    # Pagination
    page_size = int(request.GET.get('page_size', 20))
    paginator = Paginator(documents, page_size)
    page_number = request.GET.get('page', 1)
    page_obj = paginator.get_page(page_number)

    context = {
        'form': form,
        'page_obj': page_obj,
        'documents': page_obj.object_list,
    }

    return render(request, 'references/search.html', context)
