"""
Feedback views - Server-rendered templates for feedback management
"""
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.db.models import Q, Count, Avg
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.views.decorators.http import require_http_methods

from apps.accounts.models import User
from apps.core.services import AuditService
from apps.organizations.models import Department, Hospital, Patient, Staff

from .models import (
    Feedback,
    FeedbackAttachment,
    FeedbackResponse,
    FeedbackStatus,
    FeedbackType,
    FeedbackCategory,
)
from .forms import (
    FeedbackForm,
    FeedbackResponseForm,
    FeedbackStatusChangeForm,
)


@login_required
def feedback_list(request):
    """
    Feedback list view with advanced filters and pagination.

    Features:
    - Server-side pagination
    - Advanced filters (status, type, sentiment, category, hospital, etc.)
    - Search by title, message, patient name
    - Statistics dashboard
    - Export capability
    """
    # Base queryset with optimizations
    queryset = Feedback.objects.select_related(
        'patient', 'hospital', 'department', 'staff',
        'assigned_to', 'reviewed_by', 'acknowledged_by', 'closed_by'
    ).filter(is_deleted=False)

    # Apply RBAC filters
    user = request.user
    if user.is_px_admin():
        pass  # See all
    elif user.is_hospital_admin() and user.hospital:
        queryset = queryset.filter(hospital=user.hospital)
    elif user.is_department_manager() and user.department:
        queryset = queryset.filter(department=user.department)
    elif user.hospital:
        queryset = queryset.filter(hospital=user.hospital)
    else:
        queryset = queryset.none()

    # Apply filters from request
    feedback_type_filter = request.GET.get('feedback_type')
    if feedback_type_filter:
        queryset = queryset.filter(feedback_type=feedback_type_filter)

    status_filter = request.GET.get('status')
    if status_filter:
        queryset = queryset.filter(status=status_filter)

    category_filter = request.GET.get('category')
    if category_filter:
        queryset = queryset.filter(category=category_filter)

    sentiment_filter = request.GET.get('sentiment')
    if sentiment_filter:
        queryset = queryset.filter(sentiment=sentiment_filter)

    priority_filter = request.GET.get('priority')
    if priority_filter:
        queryset = queryset.filter(priority=priority_filter)

    hospital_filter = request.GET.get('hospital')
    if hospital_filter:
        queryset = queryset.filter(hospital_id=hospital_filter)

    department_filter = request.GET.get('department')
    if department_filter:
        queryset = queryset.filter(department_id=department_filter)

    staff_filter = request.GET.get('staff')
    if staff_filter:
        queryset = queryset.filter(staff_id=staff_filter)

    assigned_to_filter = request.GET.get('assigned_to')
    if assigned_to_filter:
        queryset = queryset.filter(assigned_to_id=assigned_to_filter)

    rating_min = request.GET.get('rating_min')
    if rating_min:
        queryset = queryset.filter(rating__gte=rating_min)

    rating_max = request.GET.get('rating_max')
    if rating_max:
        queryset = queryset.filter(rating__lte=rating_max)

    is_featured = request.GET.get('is_featured')
    if is_featured == 'true':
        queryset = queryset.filter(is_featured=True)

    requires_follow_up = request.GET.get('requires_follow_up')
    if requires_follow_up == 'true':
        queryset = queryset.filter(requires_follow_up=True)

    # Search
    search_query = request.GET.get('search')
    if search_query:
        queryset = queryset.filter(
            Q(title__icontains=search_query) |
            Q(message__icontains=search_query) |
            Q(patient__mrn__icontains=search_query) |
            Q(patient__first_name__icontains=search_query) |
            Q(patient__last_name__icontains=search_query) |
            Q(contact_name__icontains=search_query)
        )

    # Date range filters
    date_from = request.GET.get('date_from')
    if date_from:
        queryset = queryset.filter(created_at__gte=date_from)

    date_to = request.GET.get('date_to')
    if date_to:
        queryset = queryset.filter(created_at__lte=date_to)

    # Ordering
    order_by = request.GET.get('order_by', '-created_at')
    queryset = queryset.order_by(order_by)

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

    # Get filter options
    hospitals = Hospital.objects.filter(status='active')
    if not user.is_px_admin() and user.hospital:
        hospitals = hospitals.filter(id=user.hospital.id)

    departments = Department.objects.filter(status='active')
    if not user.is_px_admin() and user.hospital:
        departments = departments.filter(hospital=user.hospital)

    # Get assignable users
    assignable_users = User.objects.filter(is_active=True)
    if user.hospital:
        assignable_users = assignable_users.filter(hospital=user.hospital)

    # Statistics
    stats = {
        'total': queryset.count(),
        'submitted': queryset.filter(status=FeedbackStatus.SUBMITTED).count(),
        'reviewed': queryset.filter(status=FeedbackStatus.REVIEWED).count(),
        'acknowledged': queryset.filter(status=FeedbackStatus.ACKNOWLEDGED).count(),
        'compliments': queryset.filter(feedback_type=FeedbackType.COMPLIMENT).count(),
        'suggestions': queryset.filter(feedback_type=FeedbackType.SUGGESTION).count(),
        'avg_rating': queryset.aggregate(Avg('rating'))['rating__avg'] or 0,
        'positive': queryset.filter(sentiment='positive').count(),
        'negative': queryset.filter(sentiment='negative').count(),
    }

    context = {
        'page_obj': page_obj,
        'feedbacks': page_obj.object_list,
        'stats': stats,
        'hospitals': hospitals,
        'departments': departments,
        'assignable_users': assignable_users,
        'status_choices': FeedbackStatus.choices,
        'type_choices': FeedbackType.choices,
        'category_choices': FeedbackCategory.choices,
        'filters': request.GET,
    }

    return render(request, 'feedback/feedback_list.html', context)


@login_required
def feedback_detail(request, pk):
    """
    Feedback detail view with timeline, attachments, and actions.

    Features:
    - Full feedback details
    - Timeline of all responses
    - Attachments management
    - Workflow actions (assign, status change, add response)
    """
    feedback = get_object_or_404(
        Feedback.objects.select_related(
            'patient', 'hospital', 'department', 'staff',
            'assigned_to', 'reviewed_by', 'acknowledged_by', 'closed_by'
        ).prefetch_related(
            'attachments',
            'responses__created_by'
        ),
        pk=pk,
        is_deleted=False
    )

    # Check access
    user = request.user
    if not user.is_px_admin():
        if user.is_hospital_admin() and feedback.hospital != user.hospital:
            messages.error(request, "You don't have permission to view this feedback.")
            return redirect('feedback:feedback_list')
        elif user.is_department_manager() and feedback.department != user.department:
            messages.error(request, "You don't have permission to view this feedback.")
            return redirect('feedback:feedback_list')
        elif user.hospital and feedback.hospital != user.hospital:
            messages.error(request, "You don't have permission to view this feedback.")
            return redirect('feedback:feedback_list')

    # Get timeline (responses)
    timeline = feedback.responses.all().order_by('-created_at')

    # Get attachments
    attachments = feedback.attachments.all().order_by('-created_at')

    # Get assignable users
    assignable_users = User.objects.filter(is_active=True)
    if feedback.hospital:
        assignable_users = assignable_users.filter(hospital=feedback.hospital)

    context = {
        'feedback': feedback,
        'timeline': timeline,
        'attachments': attachments,
        'assignable_users': assignable_users,
        'status_choices': FeedbackStatus.choices,
        'can_edit': user.is_px_admin() or user.is_hospital_admin(),
    }

    return render(request, 'feedback/feedback_detail.html', context)


@login_required
@require_http_methods(["GET", "POST"])
def feedback_create(request):
    """Create new feedback"""
    if request.method == 'POST':
        form = FeedbackForm(request.POST, user=request.user)
        if form.is_valid():
            try:
                feedback = form.save(commit=False)

                # Set default sentiment if not set
                if not feedback.sentiment:
                    feedback.sentiment = 'neutral'

                feedback.save()

                # Create initial response
                FeedbackResponse.objects.create(
                    feedback=feedback,
                    response_type='note',
                    message=f"Feedback submitted by {request.user.get_full_name()}",
                    created_by=request.user,
                    is_internal=True
                )

                # Log audit
                AuditService.log_event(
                    event_type='feedback_created',
                    description=f"Feedback created: {feedback.title}",
                    user=request.user,
                    content_object=feedback,
                    metadata={
                        'feedback_type': feedback.feedback_type,
                        'category': feedback.category,
                        'rating': feedback.rating
                    }
                )

                messages.success(request, f"Feedback #{feedback.id} created successfully.")
                return redirect('feedback:feedback_detail', pk=feedback.id)

            except Exception as e:
                messages.error(request, f"Error creating feedback: {str(e)}")
        else:
            messages.error(request, "Please correct the errors below.")
    else:
        form = FeedbackForm(user=request.user)

    # Get patients for selection
    patients = Patient.objects.filter(status='active')
    if request.user.hospital:
        patients = patients.filter(primary_hospital=request.user.hospital)

    context = {
        'form': form,
        'patients': patients,
        'is_create': True,
    }

    return render(request, 'feedback/feedback_form.html', context)


@login_required
@require_http_methods(["GET", "POST"])
def feedback_update(request, pk):
    """Update existing feedback"""
    feedback = get_object_or_404(Feedback, pk=pk, is_deleted=False)

    # Check permission
    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        messages.error(request, "You don't have permission to edit feedback.")
        return redirect('feedback:feedback_detail', pk=pk)

    if request.method == 'POST':
        form = FeedbackForm(request.POST, instance=feedback, user=request.user)
        if form.is_valid():
            try:
                feedback = form.save()

                # Create update response
                FeedbackResponse.objects.create(
                    feedback=feedback,
                    response_type='note',
                    message=f"Feedback updated by {request.user.get_full_name()}",
                    created_by=request.user,
                    is_internal=True
                )

                # Log audit
                AuditService.log_event(
                    event_type='feedback_updated',
                    description=f"Feedback updated: {feedback.title}",
                    user=request.user,
                    content_object=feedback
                )

                messages.success(request, "Feedback updated successfully.")
                return redirect('feedback:feedback_detail', pk=feedback.id)

            except Exception as e:
                messages.error(request, f"Error updating feedback: {str(e)}")
        else:
            messages.error(request, "Please correct the errors below.")
    else:
        form = FeedbackForm(instance=feedback, user=request.user)

    # Get patients for selection
    patients = Patient.objects.filter(status='active')
    if request.user.hospital:
        patients = patients.filter(primary_hospital=request.user.hospital)

    context = {
        'form': form,
        'feedback': feedback,
        'patients': patients,
        'is_create': False,
    }

    return render(request, 'feedback/feedback_form.html', context)


@login_required
@require_http_methods(["GET", "POST"])
def feedback_delete(request, pk):
    """Soft delete feedback"""
    feedback = get_object_or_404(Feedback, pk=pk, is_deleted=False)

    # Check permission
    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        messages.error(request, "You don't have permission to delete feedback.")
        return redirect('feedback:feedback_detail', pk=pk)

    if request.method == 'POST':
        try:
            feedback.soft_delete(user=request.user)

            # Log audit
            AuditService.log_event(
                event_type='feedback_deleted',
                description=f"Feedback deleted: {feedback.title}",
                user=request.user,
                content_object=feedback
            )

            messages.success(request, "Feedback deleted successfully.")
            return redirect('feedback:feedback_list')

        except Exception as e:
            messages.error(request, f"Error deleting feedback: {str(e)}")
            return redirect('feedback:feedback_detail', pk=pk)

    context = {
        'feedback': feedback,
    }

    return render(request, 'feedback/feedback_delete_confirm.html', context)


@login_required
@require_http_methods(["POST"])
def feedback_assign(request, pk):
    """Assign feedback to user"""
    feedback = get_object_or_404(Feedback, pk=pk, is_deleted=False)

    # Check permission
    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        messages.error(request, "You don't have permission to assign feedback.")
        return redirect('feedback:feedback_detail', pk=pk)

    user_id = request.POST.get('user_id')
    note = request.POST.get('note', '')

    if not user_id:
        messages.error(request, "Please select a user to assign.")
        return redirect('feedback:feedback_detail', pk=pk)

    try:
        assignee = User.objects.get(id=user_id)
        feedback.assigned_to = assignee
        feedback.assigned_at = timezone.now()
        feedback.save(update_fields=['assigned_to', 'assigned_at'])

        # Create response
        message = f"Assigned to {assignee.get_full_name()}"
        if note:
            message += f"\nNote: {note}"

        FeedbackResponse.objects.create(
            feedback=feedback,
            response_type='assignment',
            message=message,
            created_by=request.user,
            is_internal=True
        )

        # Log audit
        AuditService.log_event(
            event_type='assignment',
            description=f"Feedback assigned to {assignee.get_full_name()}",
            user=request.user,
            content_object=feedback
        )

        messages.success(request, f"Feedback assigned to {assignee.get_full_name()}.")

    except User.DoesNotExist:
        messages.error(request, "User not found.")

    return redirect('feedback:feedback_detail', pk=pk)


@login_required
@require_http_methods(["POST"])
def feedback_change_status(request, pk):
    """Change feedback status"""
    feedback = get_object_or_404(Feedback, pk=pk, is_deleted=False)

    # Check permission
    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        messages.error(request, "You don't have permission to change feedback status.")
        return redirect('feedback:feedback_detail', pk=pk)

    new_status = request.POST.get('status')
    note = request.POST.get('note', '')

    if not new_status:
        messages.error(request, "Please select a status.")
        return redirect('feedback:feedback_detail', pk=pk)

    old_status = feedback.status
    feedback.status = new_status

    # Handle status-specific logic
    if new_status == FeedbackStatus.REVIEWED:
        feedback.reviewed_at = timezone.now()
        feedback.reviewed_by = request.user
    elif new_status == FeedbackStatus.ACKNOWLEDGED:
        feedback.acknowledged_at = timezone.now()
        feedback.acknowledged_by = request.user
    elif new_status == FeedbackStatus.CLOSED:
        feedback.closed_at = timezone.now()
        feedback.closed_by = request.user

    feedback.save()

    # Create response
    message = note or f"Status changed from {old_status} to {new_status}"

    FeedbackResponse.objects.create(
        feedback=feedback,
        response_type='status_change',
        message=message,
        created_by=request.user,
        old_status=old_status,
        new_status=new_status,
        is_internal=True
    )

    # Log audit
    AuditService.log_event(
        event_type='status_change',
        description=f"Feedback status changed from {old_status} to {new_status}",
        user=request.user,
        content_object=feedback,
        metadata={'old_status': old_status, 'new_status': new_status}
    )

    messages.success(request, f"Feedback status changed to {new_status}.")
    return redirect('feedback:feedback_detail', pk=pk)


@login_required
@require_http_methods(["POST"])
def feedback_add_response(request, pk):
    """Add response to feedback"""
    feedback = get_object_or_404(Feedback, pk=pk, is_deleted=False)

    response_type = request.POST.get('response_type', 'response')
    message = request.POST.get('message')
    is_internal = request.POST.get('is_internal') == 'on'

    if not message:
        messages.error(request, "Please enter a response message.")
        return redirect('feedback:feedback_detail', pk=pk)

    # Create response
    FeedbackResponse.objects.create(
        feedback=feedback,
        response_type=response_type,
        message=message,
        created_by=request.user,
        is_internal=is_internal
    )

    messages.success(request, "Response added successfully.")
    return redirect('feedback:feedback_detail', pk=pk)


@login_required
@require_http_methods(["POST"])
def feedback_toggle_featured(request, pk):
    """Toggle featured status"""
    feedback = get_object_or_404(Feedback, pk=pk, is_deleted=False)

    # Check permission
    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        messages.error(request, "You don't have permission to feature feedback.")
        return redirect('feedback:feedback_detail', pk=pk)

    feedback.is_featured = not feedback.is_featured
    feedback.save(update_fields=['is_featured'])

    status = "featured" if feedback.is_featured else "unfeatured"
    messages.success(request, f"Feedback {status} successfully.")

    return redirect('feedback:feedback_detail', pk=pk)


@login_required
@require_http_methods(["POST"])
def feedback_toggle_follow_up(request, pk):
    """Toggle follow-up required status"""
    feedback = get_object_or_404(Feedback, pk=pk, is_deleted=False)

    # Check permission
    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        messages.error(request, "You don't have permission to modify feedback.")
        return redirect('feedback:feedback_detail', pk=pk)

    feedback.requires_follow_up = not feedback.requires_follow_up
    feedback.save(update_fields=['requires_follow_up'])

    status = "marked for follow-up" if feedback.requires_follow_up else "unmarked for follow-up"
    messages.success(request, f"Feedback {status} successfully.")

    return redirect('feedback:feedback_detail', pk=pk)
