from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_exempt
from django.http import JsonResponse
from django.db.models import Count, Q
from django.utils import timezone
from datetime import datetime
import json

from apps.standards.models import (
    StandardSource,
    StandardCategory,
    Standard,
    StandardCompliance,
    StandardAttachment
)
from apps.organizations.models import Department
from apps.standards.forms import (
    StandardSourceForm,
    StandardCategoryForm,
    StandardForm,
    StandardComplianceForm,
    StandardAttachmentForm
)


# ==================== API ViewSets ====================

class StandardSourceViewSet(viewsets.ModelViewSet):
    queryset = StandardSource.objects.all()
    filterset_fields = ['is_active']
    search_fields = ['name', 'name_ar', 'code']
    ordering = ['name']

    def get_serializer_class(self):
        from apps.standards.serializers import StandardSourceSerializer
        return StandardSourceSerializer


class StandardCategoryViewSet(viewsets.ModelViewSet):
    queryset = StandardCategory.objects.all()
    filterset_fields = ['is_active']
    search_fields = ['name', 'name_ar']
    ordering = ['order', 'name']

    def get_serializer_class(self):
        from apps.standards.serializers import StandardCategorySerializer
        return StandardCategorySerializer


class StandardViewSet(viewsets.ModelViewSet):
    queryset = Standard.objects.all()
    filterset_fields = ['source', 'category', 'department', 'is_active']
    search_fields = ['code', 'title', 'title_ar', 'description']
    ordering = ['source', 'category', 'code']

    def get_serializer_class(self):
        from apps.standards.serializers import StandardSerializer
        return StandardSerializer


class StandardComplianceViewSet(viewsets.ModelViewSet):
    queryset = StandardCompliance.objects.all()
    filterset_fields = ['department', 'standard', 'status']
    search_fields = ['department__name', 'standard__code', 'notes']
    ordering = ['-created_at']

    def get_serializer_class(self):
        from apps.standards.serializers import StandardComplianceSerializer
        return StandardComplianceSerializer


class StandardAttachmentViewSet(viewsets.ModelViewSet):
    queryset = StandardAttachment.objects.all()
    filterset_fields = ['compliance']
    search_fields = ['filename', 'description']
    ordering = ['-uploaded_at']

    def get_serializer_class(self):
        from apps.standards.serializers import StandardAttachmentSerializer
        return StandardAttachmentSerializer


# ==================== UI Views ====================

@login_required
def standards_dashboard(request):
    """Standards dashboard with statistics"""
    # Get current hospital from tenant_hospital (set by middleware)
    hospital = getattr(request, 'tenant_hospital', None)
    if not hospital:
        return render(request, 'core/no_hospital_assigned.html')

    departments = hospital.departments.filter(status='active')

    # Get compliance statistics
    compliance_records = StandardCompliance.objects.filter(
        department__hospital=hospital
    )

    stats = {
        'total_standards': Standard.objects.filter(is_active=True).count(),
        'total_departments': departments.count(),
        'met': compliance_records.filter(status='met').count(),
        'partially_met': compliance_records.filter(status='partially_met').count(),
        'not_met': compliance_records.filter(status='not_met').count(),
        'not_assessed': compliance_records.filter(status='not_assessed').count(),
    }

    # Recent compliance updates
    recent_updates = compliance_records.order_by('-updated_at')[:10]

    context = {
        'hospital': hospital,
        'departments': departments,
        'stats': stats,
        'recent_updates': recent_updates,
    }

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


@ensure_csrf_cookie
@login_required
def department_standards_view(request, pk):
    """View all standards for a department"""
    department = get_object_or_404(Department, pk=pk)

    # Check if user is PX admin
    hospital = getattr(request, 'tenant_hospital', None)
    is_px_admin = request.user.is_superuser or (
        hasattr(request.user, 'hospital_user') and
        request.user.hospital_user.hospital == hospital and
        request.user.hospital_user.role == 'px_admin'
    ) if hospital else False

    # Get all active standards (both department-specific and general)
    department_standards = Standard.objects.filter(is_active=True).filter(
        Q(department=department) | Q(department__isnull=True)
    ).order_by('source', 'category', 'code')

    # Get compliance status for each standard
    standards_data = []
    for standard in department_standards:
        compliance = StandardCompliance.objects.filter(
            department=department,
            standard=standard
        ).first()

        standards_data.append({
            'standard': standard,
            'compliance': compliance,
            'attachment_count': compliance.attachments.count() if compliance else 0,
        })

    context = {
        'department': department,
        'standards_data': standards_data,
        'is_px_admin': is_px_admin,
    }

    return render(request, 'standards/department_standards.html', context)


@login_required
def standard_detail(request, pk):
    """View standard details and compliance history"""
    standard = get_object_or_404(Standard, pk=pk)

    # Get compliance records for all departments
    compliance_records = StandardCompliance.objects.filter(
        standard=standard
    ).select_related('department', 'assessor').order_by('-created_at')

    context = {
        'standard': standard,
        'compliance_records': compliance_records,
    }

    return render(request, 'standards/standard_detail.html', context)


@login_required
def standard_compliance_update(request, compliance_id):
    """Update compliance status"""
    compliance = get_object_or_404(StandardCompliance, pk=compliance_id)

    if request.method == 'POST':
        form = StandardComplianceForm(request.POST, instance=compliance)
        if form.is_valid():
            form.save()
            return redirect('standards:department_standards', pk=compliance.department.pk)
    else:
        form = StandardComplianceForm(instance=compliance)

    context = {
        'compliance': compliance,
        'form': form,
    }

    return render(request, 'standards/compliance_form.html', context)


@login_required
def standard_attachment_upload(request, compliance_id):
    """Upload attachment for compliance"""
    compliance = get_object_or_404(StandardCompliance, pk=compliance_id)

    if request.method == 'POST':
        form = StandardAttachmentForm(request.POST, request.FILES)
        if form.is_valid():
            attachment = form.save(commit=False)
            attachment.compliance = compliance
            attachment.uploaded_by = request.user
            attachment.filename = request.FILES['file'].name
            attachment.save()
            return redirect('standards:standard_compliance_update', compliance_id=compliance.pk)
    else:
        form = StandardAttachmentForm()

    context = {
        'compliance': compliance,
        'form': form,
    }

    return render(request, 'standards/attachment_upload.html', context)


@login_required
def standards_search(request):
    """Search standards"""
    query = request.GET.get('q', '')
    source_filter = request.GET.get('source', '')
    category_filter = request.GET.get('category', '')
    status_filter = request.GET.get('status', '')

    # Get current hospital from tenant_hospital (set by middleware)
    hospital = getattr(request, 'tenant_hospital', None)
    if not hospital:
        return render(request, 'core/no_hospital_assigned.html')

    # Build queryset
    standards = Standard.objects.filter(is_active=True)

    if query:
        standards = standards.filter(
            Q(code__icontains=query) |
            Q(title__icontains=query) |
            Q(title_ar__icontains=query) |
            Q(description__icontains=query)
        )

    if source_filter:
        standards = standards.filter(source_id=source_filter)

    if category_filter:
        standards = standards.filter(category_id=category_filter)

    standards = standards.select_related('source', 'category').order_by('source', 'category', 'code')

    # Get filters
    sources = StandardSource.objects.filter(is_active=True)
    categories = StandardCategory.objects.filter(is_active=True)

    context = {
        'hospital': hospital,
        'standards': standards,
        'query': query,
        'source_filter': source_filter,
        'category_filter': category_filter,
        'sources': sources,
        'categories': categories,
    }

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


@login_required
def standard_create(request, department_id=None):
    """Create a new standard (PX Admin only)"""
    # Check if user is PX admin
    hospital = getattr(request, 'tenant_hospital', None)
    if not hospital:
        return render(request, 'core/no_hospital_assigned.html')

    is_px_admin = request.user.is_superuser or (
        hasattr(request.user, 'hospital_user') and
        request.user.hospital_user.hospital == hospital and
        request.user.hospital_user.role == 'px_admin'
    )

    if not is_px_admin:
        from django.contrib import messages
        messages.error(request, 'You do not have permission to create standards.')
        if department_id:
            return redirect('standards:department_standards', pk=department_id)
        return redirect('standards:dashboard')

    if request.method == 'POST':
        form = StandardForm(request.POST)
        if form.is_valid():
            standard = form.save(commit=False)
            standard.save()
            from django.contrib import messages
            messages.success(request, 'Standard created successfully.')
            if department_id:
                return redirect('standards:department_standards', pk=department_id)
            return redirect('standards:dashboard')
    else:
        form = StandardForm()
        # If department_id is provided, pre-select that department
        if department_id:
            from apps.organizations.models import Department
            department = Department.objects.filter(pk=department_id).first()
            if department:
                form.fields['department'].initial = department

    # Get all departments for the hospital
    departments = hospital.departments.filter(status='active')

    context = {
        'form': form,
        'department_id': department_id,
        'departments': departments,
        'hospital': hospital,
    }

    return render(request, 'standards/standard_form.html', context)


@csrf_exempt
@login_required
def create_compliance_ajax(request):
    """Create compliance record via AJAX"""
    if not request.user.is_authenticated:
        return JsonResponse({'success': False, 'error': 'Authentication required'}, status=401)
    
    if request.method != 'POST':
        return JsonResponse({'success': False, 'error': 'Invalid request method'})

    # Parse JSON from request body
    try:
        data = json.loads(request.body)
    except json.JSONDecodeError:
        return JsonResponse({'success': False, 'error': 'Invalid JSON'})

    department_id = data.get('department_id')
    standard_id = data.get('standard_id')

    if not department_id or not standard_id:
        return JsonResponse({'success': False, 'error': 'Missing required fields'})

    try:
        department = Department.objects.get(pk=department_id)
        standard = Standard.objects.get(pk=standard_id)

        # Check if compliance already exists
        compliance, created = StandardCompliance.objects.get_or_create(
            department=department,
            standard=standard,
            defaults={
                'assessor': request.user,
                'last_assessed_date': timezone.now().date(),
            }
        )

        return JsonResponse({
            'success': True,
            'compliance_id': compliance.id,
            'status': compliance.status,
            'created': created,
        })
    except Exception as e:
        import traceback
        traceback.print_exc()
        return JsonResponse({'success': False, 'error': str(e)})


@csrf_exempt
@login_required
def update_compliance_ajax(request):
    """Update compliance record via AJAX"""
    if not request.user.is_authenticated:
        return JsonResponse({'success': False, 'error': 'Authentication required'}, status=401)
    
    if request.method != 'POST':
        return JsonResponse({'success': False, 'error': 'Invalid request method'})

    # Parse JSON from request body
    try:
        data = json.loads(request.body)
    except json.JSONDecodeError:
        return JsonResponse({'success': False, 'error': 'Invalid JSON'})

    compliance_id = data.get('compliance_id')
    status = data.get('status')
    notes = data.get('notes', '')
    evidence_summary = data.get('evidence_summary', '')
    last_assessed_date_str = data.get('last_assessed_date')
    assessor_id = data.get('assessor_id')

    if not compliance_id or not status:
        return JsonResponse({'success': False, 'error': 'Missing required fields'})

    try:
        compliance = StandardCompliance.objects.get(pk=compliance_id)
        compliance.status = status
        compliance.notes = notes
        compliance.evidence_summary = evidence_summary
        
        # Set assessor - use logged-in user or provided ID
        if assessor_id:
            from apps.accounts.models import User
            try:
                assessor = User.objects.get(pk=assessor_id)
                compliance.assessor = assessor
            except User.DoesNotExist:
                compliance.assessor = request.user
        else:
            compliance.assessor = request.user
        
        # Set assessment date
        if last_assessed_date_str:
            compliance.last_assessed_date = datetime.strptime(last_assessed_date_str, '%Y-%m-%d').date()
        else:
            compliance.last_assessed_date = timezone.now().date()
        
        compliance.save()

        return JsonResponse({
            'success': True,
            'status': compliance.status,
            'status_display': compliance.get_status_display(),
        })
    except Exception as e:
        import traceback
        traceback.print_exc()
        return JsonResponse({'success': False, 'error': str(e)})


@login_required
def get_compliance_status(request, department_id, standard_id):
    """API endpoint to get compliance status"""
    compliance = StandardCompliance.objects.filter(
        department_id=department_id,
        standard_id=standard_id
    ).first()

    if compliance:
        data = {
            'status': compliance.status,
            'last_assessed_date': compliance.last_assessed_date,
            'assessor': compliance.assessor.get_full_name() if compliance.assessor else None,
            'notes': compliance.notes,
            'attachment_count': compliance.attachments.count(),
        }
    else:
        data = {
            'status': 'not_assessed',
            'last_assessed_date': None,
            'assessor': None,
            'notes': '',
            'attachment_count': 0,
        }

    return JsonResponse(data)


# ==================== Source Management Views ====================

@login_required
def source_list(request):
    """List all standard sources"""
    sources = StandardSource.objects.all().order_by('name')
    context = {'sources': sources}
    return render(request, 'standards/source_list.html', context)


@login_required
def source_create(request):
    """Create a new standard source"""
    if request.method == 'POST':
        form = StandardSourceForm(request.POST)
        if form.is_valid():
            form.save()
            from django.contrib import messages
            messages.success(request, 'Source created successfully.')
            return redirect('standards:source_list')
    else:
        form = StandardSourceForm()

    context = {'form': form}
    return render(request, 'standards/source_form.html', context)


@login_required
def source_update(request, pk):
    """Update a standard source"""
    source = get_object_or_404(StandardSource, pk=pk)
    
    if request.method == 'POST':
        form = StandardSourceForm(request.POST, instance=source)
        if form.is_valid():
            form.save()
            from django.contrib import messages
            messages.success(request, 'Source updated successfully.')
            return redirect('standards:source_list')
    else:
        form = StandardSourceForm(instance=source)

    context = {'form': form, 'source': source}
    return render(request, 'standards/source_form.html', context)


@login_required
def source_delete(request, pk):
    """Delete a standard source"""
    source = get_object_or_404(StandardSource, pk=pk)
    
    if request.method == 'POST':
        source.delete()
        from django.contrib import messages
        messages.success(request, 'Source deleted successfully.')
        return redirect('standards:source_list')
    
    context = {'source': source}
    return render(request, 'standards/source_confirm_delete.html', context)


# ==================== Category Management Views ====================

@login_required
def category_list(request):
    """List all standard categories"""
    categories = StandardCategory.objects.all().order_by('order', 'name')
    context = {'categories': categories}
    return render(request, 'standards/category_list.html', context)


@login_required
def category_create(request):
    """Create a new standard category"""
    if request.method == 'POST':
        form = StandardCategoryForm(request.POST)
        if form.is_valid():
            form.save()
            from django.contrib import messages
            messages.success(request, 'Category created successfully.')
            return redirect('standards:category_list')
    else:
        form = StandardCategoryForm()

    context = {'form': form}
    return render(request, 'standards/category_form.html', context)


@login_required
def category_update(request, pk):
    """Update a standard category"""
    category = get_object_or_404(StandardCategory, pk=pk)
    
    if request.method == 'POST':
        form = StandardCategoryForm(request.POST, instance=category)
        if form.is_valid():
            form.save()
            from django.contrib import messages
            messages.success(request, 'Category updated successfully.')
            return redirect('standards:category_list')
    else:
        form = StandardCategoryForm(instance=category)

    context = {'form': form, 'category': category}
    return render(request, 'standards/category_form.html', context)


@login_required
def category_delete(request, pk):
    """Delete a standard category"""
    category = get_object_or_404(StandardCategory, pk=pk)
    
    if request.method == 'POST':
        category.delete()
        from django.contrib import messages
        messages.success(request, 'Category deleted successfully.')
        return redirect('standards:category_list')
    
    context = {'category': category}
    return render(request, 'standards/category_confirm_delete.html', context)
