"""
Simple Acknowledgement Views
Simplified views for employee acknowledgement system.
"""
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.http import HttpResponse
from django.db.models import Count, Q
from django.core.paginator import Paginator

from apps.accounts.models import User, SimpleAcknowledgement, EmployeeAcknowledgement


# ============================================================================
# EMPLOYEE VIEWS
# ============================================================================

@login_required
def simple_acknowledgement_list(request):
    """
    Employee view: List all acknowledgements with sign status.
    Shows acknowledgements that were sent to the employee OR are active and required.
    """
    employee = request.user

    # Get acknowledgements that were specifically sent to this employee
    sent_ack_ids = EmployeeAcknowledgement.objects.filter(
        employee=employee
    ).values_list('acknowledgement_id', flat=True)

    # Get all active required acknowledgements that haven't been sent yet
    active_required_ids = SimpleAcknowledgement.objects.filter(
        is_active=True,
        is_required=True
    ).exclude(
        id__in=sent_ack_ids
    ).values_list('id', flat=True)

    # Combine all acknowledgement IDs the employee needs to see
    all_ack_ids = list(sent_ack_ids) + list(active_required_ids)

    # Get all acknowledgements
    acknowledgements = SimpleAcknowledgement.objects.filter(
        id__in=all_ack_ids
    ).order_by('order', 'title')

    # Get or create employee acknowledgements for each
    employee_acks = []
    for ack in acknowledgements:
        emp_ack, created = EmployeeAcknowledgement.objects.get_or_create(
            employee=employee,
            acknowledgement=ack,
            defaults={'is_signed': False}
        )
        employee_acks.append({
            'acknowledgement': ack,
            'signature': emp_ack,
            'is_signed': emp_ack.is_signed,
            'signed_at': emp_ack.signed_at,
            'has_pdf': bool(emp_ack.signed_pdf),
            'sent_at': emp_ack.sent_at,
            'sent_by': emp_ack.sent_by,
        })

    # Separate pending and signed
    pending_acks = [e for e in employee_acks if not e['is_signed']]
    signed_acks = [e for e in employee_acks if e['is_signed']]

    # Calculate stats
    total = len(employee_acks)
    signed = len(signed_acks)
    pending = len(pending_acks)

    context = {
        'employee_acks': employee_acks,
        'pending_acks': pending_acks,
        'signed_acks': signed_acks,
        'total': total,
        'signed': signed,
        'pending': pending,
        'progress': int((signed / total * 100)) if total > 0 else 0,
    }
    return render(request, 'accounts/simple_acknowledgements/list.html', context)


@login_required
def simple_acknowledgement_sign(request, ack_id):
    """
    Employee view: Sign an acknowledgement.
    Shows the acknowledgement details and a form to sign with name and employee ID.
    """
    acknowledgement = get_object_or_404(SimpleAcknowledgement, id=ack_id, is_active=True)
    employee = request.user

    # Get or create the employee acknowledgement record
    emp_ack, created = EmployeeAcknowledgement.objects.get_or_create(
        employee=employee,
        acknowledgement=acknowledgement,
        defaults={'is_signed': False}
    )

    # If already signed, redirect to list
    if emp_ack.is_signed:
        messages.info(request, _('You have already signed this acknowledgement.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    if request.method == 'POST':
        signature_name = request.POST.get('signature_name', '').strip()
        signature_employee_id = request.POST.get('signature_employee_id', '').strip()
        confirm = request.POST.get('confirm') == 'on'

        # Validation
        if not signature_name:
            messages.error(request, _('Please enter your name.'))
        elif not signature_employee_id:
            messages.error(request, _('Please enter your employee ID.'))
        elif not confirm:
            messages.error(request, _('Please confirm that you have read and understood the acknowledgement.'))
        else:
            # Save the signature
            emp_ack.is_signed = True
            emp_ack.signed_at = timezone.now()
            emp_ack.signature_name = signature_name
            emp_ack.signature_employee_id = signature_employee_id
            emp_ack.ip_address = get_client_ip(request)
            emp_ack.user_agent = request.META.get('HTTP_USER_AGENT', '')[:500]
            emp_ack.save()

            # Generate simple signed PDF (optional - can be added later)
            # For now, just copy the original PDF if it exists
            if acknowledgement.pdf_document and not emp_ack.signed_pdf:
                emp_ack.signed_pdf = acknowledgement.pdf_document
                emp_ack.save()

            messages.success(request, _('Acknowledgement signed successfully!'))
            return redirect('accounts:simple_acknowledgements:employee_list')

    context = {
        'acknowledgement': acknowledgement,
        'emp_ack': emp_ack,
        'employee': employee,
    }
    return render(request, 'accounts/simple_acknowledgements/sign.html', context)


@login_required
def simple_acknowledgement_download(request, ack_id):
    """
    Employee view: Download the signed PDF.
    """
    emp_ack = get_object_or_404(
        EmployeeAcknowledgement,
        acknowledgement_id=ack_id,
        employee=request.user,
        is_signed=True
    )

    if emp_ack.signed_pdf:
        response = HttpResponse(emp_ack.signed_pdf, content_type='application/pdf')
        response['Content-Disposition'] = f'attachment; filename="{emp_ack.acknowledgement.title}.pdf"'
        return response
    elif emp_ack.acknowledgement.pdf_document:
        response = HttpResponse(emp_ack.acknowledgement.pdf_document, content_type='application/pdf')
        response['Content-Disposition'] = f'attachment; filename="{emp_ack.acknowledgement.title}.pdf"'
        return response
    else:
        messages.error(request, _('No PDF available for this acknowledgement.'))
        return redirect('accounts:simple_acknowledgements:employee_list')


# ============================================================================
# ADMIN VIEWS
# ============================================================================

@login_required
def admin_acknowledgement_list(request):
    """
    Admin view: List all acknowledgements with management options.
    """
    if not request.user.is_staff and not request.user.is_px_admin():
        messages.error(request, _('You do not have permission to access this page.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    acknowledgements = SimpleAcknowledgement.objects.all().order_by('order', 'title')

    context = {
        'acknowledgements': acknowledgements,
    }
    return render(request, 'accounts/simple_acknowledgements/admin_list.html', context)


@login_required
def admin_acknowledgement_create(request):
    """
    Admin view: Create a new acknowledgement.
    """
    if not request.user.is_staff and not request.user.is_px_admin():
        messages.error(request, _('You do not have permission to access this page.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    if request.method == 'POST':
        title = request.POST.get('title', '').strip()
        description = request.POST.get('description', '').strip()
        pdf_document = request.FILES.get('pdf_document')
        is_required = request.POST.get('is_required') == 'on'
        is_active = request.POST.get('is_active') == 'on'
        order = request.POST.get('order', '0')

        if not title:
            messages.error(request, _('Please enter a title.'))
        else:
            acknowledgement = SimpleAcknowledgement.objects.create(
                title=title,
                description=description,
                pdf_document=pdf_document,
                is_required=is_required,
                is_active=is_active,
                order=int(order) if order.isdigit() else 0,
            )
            messages.success(request, _('Acknowledgement created successfully!'))
            return redirect('accounts:simple_acknowledgements:admin_list')

    return render(request, 'accounts/simple_acknowledgements/admin_create.html')


@login_required
def admin_acknowledgement_edit(request, ack_id):
    """
    Admin view: Edit an existing acknowledgement.
    """
    if not request.user.is_staff and not request.user.is_px_admin():
        messages.error(request, _('You do not have permission to access this page.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    acknowledgement = get_object_or_404(SimpleAcknowledgement, id=ack_id)

    if request.method == 'POST':
        title = request.POST.get('title', '').strip()
        description = request.POST.get('description', '').strip()
        pdf_document = request.FILES.get('pdf_document')
        is_required = request.POST.get('is_required') == 'on'
        is_active = request.POST.get('is_active') == 'on'
        order = request.POST.get('order', '0')

        if not title:
            messages.error(request, _('Please enter a title.'))
        else:
            acknowledgement.title = title
            acknowledgement.description = description
            acknowledgement.is_required = is_required
            acknowledgement.is_active = is_active
            acknowledgement.order = int(order) if order.isdigit() else 0

            if pdf_document:
                acknowledgement.pdf_document = pdf_document

            acknowledgement.save()
            messages.success(request, _('Acknowledgement updated successfully!'))
            return redirect('accounts:simple_acknowledgements:admin_list')

    context = {
        'acknowledgement': acknowledgement,
        'action': 'edit',
    }
    return render(request, 'accounts/simple_acknowledgements/admin_form.html', context)


@login_required
def admin_acknowledgement_delete(request, ack_id):
    """
    Admin view: Delete an acknowledgement.
    """
    if not request.user.is_staff and not request.user.is_px_admin():
        messages.error(request, _('You do not have permission to access this page.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    acknowledgement = get_object_or_404(SimpleAcknowledgement, id=ack_id)

    if request.method == 'POST':
        acknowledgement.delete()
        messages.success(request, _('Acknowledgement deleted successfully!'))
        return redirect('accounts:simple_acknowledgements:admin_list')

    context = {
        'acknowledgement': acknowledgement,
    }
    return render(request, 'accounts/simple_acknowledgements/admin_delete.html', context)


@login_required
def admin_employee_signatures(request, ack_id=None):
    """
    Admin view: View all employee signatures.
    Can filter by acknowledgement if ack_id is provided.
    """
    if not request.user.is_staff and not request.user.is_px_admin():
        messages.error(request, _('You do not have permission to access this page.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    signatures = EmployeeAcknowledgement.objects.select_related(
        'employee', 'acknowledgement'
    ).order_by('-signed_at')

    if ack_id:
        acknowledgement = get_object_or_404(SimpleAcknowledgement, id=ack_id)
        signatures = signatures.filter(acknowledgement=acknowledgement)
    else:
        acknowledgement = None

    # Search
    search = request.GET.get('search', '')
    if search:
        signatures = signatures.filter(
            Q(employee__email__icontains=search) |
            Q(employee__first_name__icontains=search) |
            Q(employee__last_name__icontains=search) |
            Q(signature_name__icontains=search) |
            Q(signature_employee_id__icontains=search)
        )

    # Filter by status
    status_filter = request.GET.get('status', '')
    if status_filter == 'signed':
        signatures = signatures.filter(is_signed=True)
    elif status_filter == 'pending':
        signatures = signatures.filter(is_signed=False)

    # Pagination
    paginator = Paginator(signatures, 50)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    context = {
        'signatures': page_obj,
        'acknowledgement': acknowledgement,
        'search': search,
        'status_filter': status_filter,
    }
    return render(request, 'accounts/simple_acknowledgements/admin_signatures.html', context)


@login_required
def admin_export_signatures(request):
    """
    Admin view: Export all signatures to CSV.
    """
    if not request.user.is_staff and not request.user.is_px_admin():
        messages.error(request, _('You do not have permission to access this page.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    import csv

    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="acknowledgement_signatures.csv"'

    writer = csv.writer(response)
    writer.writerow([
        'Employee Email', 'Employee Name', 'Employee ID (at sign)',
        'Acknowledgement', 'Status', 'Signed At', 'IP Address'
    ])

    signatures = EmployeeAcknowledgement.objects.select_related(
        'employee', 'acknowledgement'
    ).order_by('-signed_at')

    for sig in signatures:
        writer.writerow([
            sig.employee.email,
            sig.signature_name or sig.employee.get_full_name(),
            sig.signature_employee_id,
            sig.acknowledgement.title,
            'Signed' if sig.is_signed else 'Pending',
            sig.signed_at.strftime('%Y-%m-%d %H:%M') if sig.signed_at else '',
            sig.ip_address or '',
        ])

    return response


@login_required
def admin_send_acknowledgement(request, ack_id):
    """
    Admin view: Send acknowledgement to specific staff members.
    """
    if not request.user.is_staff and not request.user.is_px_admin():
        messages.error(request, _('You do not have permission to access this page.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    acknowledgement = get_object_or_404(SimpleAcknowledgement, id=ack_id)

    # Get all active staff
    from apps.accounts.models import User
    staff_list = User.objects.filter(
        is_active=True,
        is_provisional=False
    ).exclude(
        id=request.user.id
    ).order_by('first_name', 'last_name')

    # Get already sent employees
    already_sent_ids = EmployeeAcknowledgement.objects.filter(
        acknowledgement=acknowledgement
    ).values_list('employee_id', flat=True)

    if request.method == 'POST':
        employee_ids = request.POST.getlist('employees')
        send_email = request.POST.get('send_email') == 'on'

        if not employee_ids:
            messages.error(request, _('Please select at least one employee.'))
        else:
            sent_count = 0
            for emp_id in employee_ids:
                emp_ack, created = EmployeeAcknowledgement.objects.get_or_create(
                    employee_id=emp_id,
                    acknowledgement=acknowledgement,
                    defaults={
                        'sent_at': timezone.now(),
                        'sent_by': request.user,
                    }
                )
                if created:
                    sent_count += 1
                    # Update sent info if record already existed but wasn't sent
                elif not emp_ack.sent_at:
                    emp_ack.sent_at = timezone.now()
                    emp_ack.sent_by = request.user
                    emp_ack.save()
                    sent_count += 1

            # Send email notifications if requested
            if send_email and sent_count > 0:
                try:
                    from apps.notifications.services import NotificationService

                    employees = User.objects.filter(id__in=employee_ids)
                    for emp in employees:
                        NotificationService.send_email(
                            email=emp.email,
                            subject=f'Action Required: {acknowledgement.title}',
                            message=f'''Dear {emp.get_full_name() or emp.email},

You have been requested to sign the following acknowledgement: {acknowledgement.title}

Please log in to the system to review and sign this document.

Best regards,
HR Department''',
                            related_object=emp_ack,
                        )
                except Exception as e:
                    messages.warning(request, _('Acknowledgements sent but email notification failed.'))

            messages.success(request, _('Acknowledgement sent to {count} employee(s).').format(count=sent_count))
            return redirect('accounts:simple_acknowledgements:admin_list')

    context = {
        'acknowledgement': acknowledgement,
        'staff_list': staff_list,
        'already_sent_ids': list(already_sent_ids),
    }
    return render(request, 'accounts/simple_acknowledgements/admin_send.html', context)


@login_required
def admin_upload_signed_pdf(request, signature_id):
    """
    Admin view: Upload signed PDF on behalf of an employee.
    """
    if not request.user.is_staff and not request.user.is_px_admin():
        messages.error(request, _('You do not have permission to access this page.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    emp_ack = get_object_or_404(
        EmployeeAcknowledgement.objects.select_related('employee', 'acknowledgement'),
        id=signature_id
    )

    if request.method == 'POST':
        signed_pdf = request.FILES.get('signed_pdf')
        signature_name = request.POST.get('signature_name', emp_ack.employee.get_full_name())
        signature_employee_id = request.POST.get('signature_employee_id', '')
        notes = request.POST.get('notes', '')

        if not signed_pdf:
            messages.error(request, _('Please upload a signed PDF.'))
        else:
            emp_ack.signed_pdf = signed_pdf
            emp_ack.is_signed = True
            emp_ack.signed_at = timezone.now()
            emp_ack.signature_name = signature_name
            emp_ack.signature_employee_id = signature_employee_id
            emp_ack.notes = notes
            emp_ack.save()

            messages.success(
                request,
                _('Signed PDF uploaded successfully for {name}.').format(name=emp_ack.employee.get_full_name())
            )
            return redirect('accounts:simple_acknowledgements:admin_signatures')

    context = {
        'emp_ack': emp_ack,
        'employee': emp_ack.employee,
        'acknowledgement': emp_ack.acknowledgement,
    }
    return render(request, 'accounts/simple_acknowledgements/admin_upload_pdf.html', context)


@login_required
def admin_mark_as_sent(request, ack_id):
    """
    Admin view: Mark acknowledgement as sent to all employees (bulk action).
    """
    if not request.user.is_staff and not request.user.is_px_admin():
        messages.error(request, _('You do not have permission to access this page.'))
        return redirect('accounts:simple_acknowledgements:employee_list')

    acknowledgement = get_object_or_404(SimpleAcknowledgement, id=ack_id)

    if request.method == 'POST':
        from apps.accounts.models import User

        # Get all active employees who haven't been sent this yet
        all_employees = User.objects.filter(is_active=True, is_provisional=False)
        already_sent = EmployeeAcknowledgement.objects.filter(
            acknowledgement=acknowledgement
        ).values_list('employee_id', flat=True)

        new_employees = all_employees.exclude(id__in=already_sent)

        created_count = 0
        for emp in new_employees:
            EmployeeAcknowledgement.objects.create(
                employee=emp,
                acknowledgement=acknowledgement,
                sent_at=timezone.now(),
                sent_by=request.user,
            )
            created_count += 1

        messages.success(
            request,
            _('Acknowledgement sent to {count} new employee(s).').format(count=created_count)
        )
        return redirect('accounts:simple_acknowledgements:admin_list')

    return redirect('accounts:simple_acknowledgements:admin_list')


# ============================================================================
# HELPER FUNCTIONS
# ============================================================================

def get_client_ip(request):
    """Get client IP address from request."""
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip
