from django.shortcuts import render, get_object_or_404, redirect, reverse
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib import messages
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, TemplateView
from django.urls import reverse_lazy
from django.utils import timezone
from django.db.models import Q, Sum, Count
from django.http import HttpResponse, Http404
from django.contrib.auth import get_user_model
from django.core.paginator import Paginator
from django.template.loader import render_to_string
from weasyprint import HTML, CSS
from weasyprint.text.fonts import FontConfiguration
import tempfile
import os
from .models import Employee, Department, Bonus, Deduction, Payslip, EmployeeInvitation, EmployeeDocument, Attendance
from .forms import EmployeeForm, DepartmentForm, BonusForm, DeductionForm, EmployeeAccountSetupForm, EmployeeDocumentForm, CreateUserAccountForm, AttendanceForm, BulkAttendanceForm
# Service import removed - using customers app for service management
from decimal import Decimal
from datetime import date, timedelta
from dateutil.relativedelta import relativedelta
import uuid
from settings.utils import send_invitation_email
from django.core.exceptions import PermissionDenied
from accounts.permissions import (
    AdminRequiredMixin, 
    EmployeeRequiredMixin,
    has_admin_access,
    permission_required,
    has_permission,
    get_user_permissions
)

User = get_user_model()

# Import admin check function
# from accounts.permissions import is_admin # This import is now redundant with dynamic permissions

# Define a mixin for superuser access
class SuperuserRequiredMixin(UserPassesTestMixin):
    def test_func(self):
        # Use has_permission for dynamic checking
        return has_permission(self.request.user, 'is_superuser') # Assuming 'is_superuser' is a valid permission key

class HRDashboardView(LoginRequiredMixin, TemplateView):
    template_name = 'hr/dashboard.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = 'HR Dashboard'

        from datetime import date, timedelta

        user = self.request.user
        # Use dynamic permission check for admin/management
        is_admin = has_permission(user, 'hr_admin') or \
                   (hasattr(user, 'employee_profile') and
                    user.employee_profile.department and
                    user.employee_profile.department.name == 'Management')
        context['is_admin'] = is_admin

        if is_admin:
            # Admin dashboard data
            context['total_employees'] = Employee.objects.filter(employment_status='active').count()
            context['total_departments'] = Department.objects.filter(is_active=True).count()
            context['pending_payslips'] = Payslip.objects.filter(is_generated=True, is_paid=False).count()
            context['recent_employees'] = Employee.objects.filter(employment_status='active').order_by('-created_at')[:5]

            # Attendance metrics
            today = date.today()
            context['todays_attendance'] = Attendance.objects.filter(date=today).count()
            context['present_today'] = Attendance.objects.filter(date=today, status='present').count()
            context['absent_today'] = Attendance.objects.filter(date=today, status='absent').count()
            context['late_today'] = Attendance.objects.filter(date=today, status='late').count()

            # Recent attendance records
            context['recent_attendance'] = Attendance.objects.select_related('employee').order_by('-date', '-created_at')[:8]

        # Employee personal data
        if hasattr(user, 'employee_profile'):
            context['employee_profile'] = user.employee_profile
            context['total_documents'] = user.employee_profile.documents.filter(is_active=True).count()
            context['recent_payslips'] = user.employee_profile.payslips.order_by('-pay_period_start')[:3]

            # Employee's recent attendance
            context['my_recent_attendance'] = user.employee_profile.attendance_records.order_by('-date')[:5]

        return context

@login_required
@user_passes_test(lambda u: has_permission(u, 'hr_dashboard_access')) # Example dynamic permission
def hr_dashboard(request):
    """HR Dashboard view"""
    # Get metrics
    total_employees = Employee.objects.filter(employment_status='active').count()
    total_departments = Department.objects.filter(is_active=True).count()
    employees_on_leave = Employee.objects.filter(employment_status='on_leave').count()
    pending_payslips = Payslip.objects.filter(is_generated=True, is_paid=False).count()

    # Recent employees (last 10)
    recent_employees = Employee.objects.filter(employment_status='active').order_by('-created_at')[:5]

    # Recent payslips
    recent_payslips = Payslip.objects.filter(is_generated=True).order_by('-created_at')[:5]

    context = {
        'total_employees': total_employees,
        'total_departments': total_departments,
        'employees_on_leave': employees_on_leave,
        'pending_payslips': pending_payslips,
        'recent_employees': recent_employees,
        'recent_payslips': recent_payslips,
    }
    return render(request, 'hr/dashboard.html', context)

# Employee Views
class EmployeeListView(LoginRequiredMixin, ListView):
    model = Employee
    template_name = 'hr/employee_list.html'
    context_object_name = 'employees'
    paginate_by = 20

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_employee'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        queryset = Employee.objects.all().select_related('department')

        # Search functionality
        search_query = self.request.GET.get('search')
        if search_query:
            queryset = queryset.filter(
                Q(first_name__icontains=search_query) |
                Q(last_name__icontains=search_query) |
                Q(employee_id__icontains=search_query) |
                Q(email__icontains=search_query)
            )

        # Department filter
        department = self.request.GET.get('department')
        if department:
            queryset = queryset.filter(department_id=department)

        # Status filter
        status = self.request.GET.get('status')
        if status:
            queryset = queryset.filter(employment_status=status)

        return queryset.order_by('-created_at')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['departments'] = Department.objects.filter(is_active=True)
        context['search_query'] = self.request.GET.get('search', '')
        context['selected_department'] = self.request.GET.get('department', '')
        context['selected_status'] = self.request.GET.get('status', '')
        return context

class EmployeeDetailView(LoginRequiredMixin, DetailView):
    model = Employee
    template_name = 'hr/employee_detail.html'
    context_object_name = 'employee'
    slug_field = 'employee_id'
    slug_url_kwarg = 'employee_id'

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_employee'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        employee = self.get_object()

        # Recent payslips
        context['recent_payslips'] = employee.payslips.order_by('-pay_period_start')[:5]

        # Recent deductions (last 5)
        context['recent_deductions'] = employee.deductions.filter(is_active=True).order_by('-created_at')[:5]

        # Recent bonuses (last 5)
        context['recent_bonuses'] = employee.bonuses.filter(is_active=True).order_by('-created_at')[:5]

        # Employee documents
        context['documents'] = employee.documents.filter(is_active=True).order_by('-uploaded_at')[:5]

        # Add form for creating user account if employee doesn't have one
        if not employee.user and has_permission(self.request.user, 'create_user_account'): # Dynamic check
            context['create_user_form'] = CreateUserAccountForm()
        # Add form for resetting password if employee has a user account
        elif employee.user and has_permission(self.request.user, 'reset_employee_password'): # Dynamic check
            context['reset_password_form'] = EmployeeAccountSetupForm() # Reusing the same form for password reset fields

        return context

    def post(self, request, *args, **kwargs):
        employee = self.get_object()

        # Handle user account creation
        if 'create_user_account' in request.POST:
            if not has_permission(request.user, 'create_user_account'): # Dynamic check
                messages.error(request, "You do not have permission to create user accounts.")
                return redirect('hr:employee_detail', employee_id=employee.employee_id)
            form = CreateUserAccountForm(request.POST)
            if form.is_valid():
                return self.create_user_account(employee, form)
            else:
                messages.error(request, 'Please correct the errors below.')
                context = self.get_context_data()
                context['create_user_form'] = form
                return self.render_to_response(context)
        # Handle password reset
        elif 'reset_password' in request.POST:
            if not has_permission(request.user, 'reset_employee_password'): # Dynamic check
                messages.error(request, "You do not have permission to reset employee passwords.")
                return redirect('hr:employee_detail', employee_id=employee.employee_id)
            return self.reset_user_password(employee, request.POST)

        return super().get(request, *args, **kwargs)

    def create_user_account(self, employee, form):
        """Create a user account for the employee"""
        try:
            # Generate or use custom password
            if form.cleaned_data['generate_password']:
                import secrets
                import string
                characters = string.ascii_letters + string.digits + "!@#$%^&*"
                password = ''.join(secrets.choice(characters) for _ in range(12))
            else:
                password = form.cleaned_data['custom_password']

            # Check if username (employee_id) is already taken
            username = employee.employee_id
            if User.objects.filter(username=username).exists():
                messages.error(self.request, f'Username {username} is already taken.')
                return redirect('hr:employee_detail', employee_id=employee.employee_id)

            # Determine role based on department
            role = 'technician'  # Default role
            is_superuser = False

            if employee.department:
                if employee.department.name.lower() in ['management', 'admin']:
                    role = 'admin'
                    is_superuser = True

            # Create user account
            user = User.objects.create_user(
                username=username,
                email=employee.email,
                password=password,
                first_name=employee.first_name,
                last_name=employee.last_name,
                role=role,
                is_staff=True,  # All employees are staff
                is_superuser=is_superuser,
                first_login_required=True  # Require password change on first login
            )

            # Link employee to user
            employee.user = user
            employee.save()

            # Assign to department group if available
            if employee.department and employee.department.user_group:
                user.groups.add(employee.department.user_group)

            # Send email with credentials if requested
            if form.cleaned_data['send_email']:
                try:
                    from notifications.email_service import EmailService
                    email_service = EmailService()

                    # Send account creation email
                    success, error_msg = email_service.send_email(
                        subject=f'Your OptiNet Account has been Created',
                        message=f'''
                        Dear {employee.full_name},

                        Your employee account has been created successfully.

                        Login Details:
                        - Username: {username}
                        - Temporary Password: {password}
                        - Login URL: {self.request.build_absolute_uri('/accounts/login/')}

                        Please log in and change your password on your first login.

                        Best regards,
                        OptiNet HR Team
                        ''',
                        recipient_list=[employee.email],
                        email_type='account_creation'
                    )

                    if success:
                        messages.success(self.request, f'User account created successfully! Login credentials have been sent to {employee.email}')
                    else:
                        messages.warning(self.request, f'User account created successfully, but email could not be sent: {error_msg}')
                        messages.info(self.request, f'Temporary password: {password}')

                except Exception as e:
                    messages.warning(self.request, f'User account created successfully, but email could not be sent: {str(e)}')
                    messages.info(self.request, f'Temporary password: {password}')
            else:
                messages.success(self.request, f'User account created successfully!')
                messages.info(self.request, f'Temporary password: {password}')

        except Exception as e:
            messages.error(self.request, f'Error creating user account: {str(e)}')

        return redirect('hr:employee_detail', employee_id=employee.employee_id)

    def reset_user_password(self, employee, post_data):
        """Reset password for existing employee user account"""
        if not employee.user:
            messages.error(self.request, 'No user account exists for this employee.')
            return redirect('hr:employee_detail', employee_id=employee.employee_id)

        try:
            # Get password preference
            generate_new_password = post_data.get('generate_new_password') == 'on'
            custom_reset_password = post_data.get('custom_password', '').strip()

            # Generate or use custom password
            if generate_new_password:
                import secrets
                import string
                characters = string.ascii_letters + string.digits + "!@#$%^&*"
                password = ''.join(secrets.choice(characters) for _ in range(12))
            else:
                password = custom_reset_password
                if not password:
                    messages.error(self.request, 'Please provide a custom password or enable auto-generation.')
                    return redirect('hr:employee_detail', employee_id=employee.employee_id)
                if len(password) < 8:
                    messages.error(self.request, 'Password must be at least 8 characters long.')
                    return redirect('hr:employee_detail', employee_id=employee.employee_id)

            # Reset the password
            employee.user.set_password(password)
            employee.user.first_login_required = True  # Force password change on next login
            employee.user.save()

            # Send email if requested
            send_reset_email = post_data.get('send_email') == 'on'
            if send_reset_email:
                try:
                    from notifications.email_service import EmailService
                    email_service = EmailService()

                    # Send password reset email
                    success, error_msg = email_service.send_email(
                        subject=f'Your OptiNet Password has been Reset',
                        message=f'''
                        Dear {employee.full_name},

                        Your password has been reset by HR staff.

                        Login Details:
                        - Username: {employee.employee_id}
                        - New Password: {password}
                        - Login URL: {self.request.build_absolute_uri('/accounts/login/')}

                        Please log in and change your password on your next login.

                        Best regards,
                        OptiNet HR Team
                        ''',
                        recipient_list=[employee.email],
                        email_type='password_reset'
                    )

                    if success:
                        messages.success(self.request, f'Password reset successfully! New credentials have been sent to {employee.email}')
                    else:
                        messages.warning(self.request, f'Password reset successfully, but email could not be sent: {error_msg}')
                        messages.info(self.request, f'New password: {password}')

                except Exception as e:
                    messages.warning(self.request, f'Password reset successfully, but email could not be sent: {str(e)}')
                    messages.info(self.request, f'New password: {password}')
            else:
                messages.success(self.request, f'Password reset successfully!')
                messages.info(self.request, f'New password: {password}')

        except Exception as e:
            messages.error(self.request, f'Error resetting password: {str(e)}')

        return redirect('hr:employee_detail', employee_id=employee.employee_id)


class EmployeeCreateView(LoginRequiredMixin, CreateView):
    model = Employee
    form_class = EmployeeForm
    template_name = 'hr/employee_form.html'

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'add_employee'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = 'Add New Employee'
        return context

    def get_success_url(self):
        return reverse_lazy('hr:employee_detail', kwargs={'employee_id': self.object.employee_id})

class EmployeeUpdateView(LoginRequiredMixin, UpdateView):
    model = Employee
    form_class = EmployeeForm
    template_name = 'hr/employee_form.html'
    slug_field = 'employee_id'
    slug_url_kwarg = 'employee_id'

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'change_employee'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = f'Edit Employee - {self.object.full_name}'
        return context

    def get_success_url(self):
        return reverse_lazy('hr:employee_detail', kwargs={'employee_id': self.object.employee_id})

class EmployeeDeleteView(LoginRequiredMixin, DeleteView):
    model = Employee
    template_name = 'hr/employee_confirm_delete.html'
    slug_field = 'employee_id'
    slug_url_kwarg = 'employee_id'
    success_url = reverse_lazy('hr:employee_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'delete_employee'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

# Department Views
class DepartmentListView(LoginRequiredMixin, ListView):
    model = Department
    template_name = 'hr/department_list.html'
    context_object_name = 'departments'

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_department'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        return Department.objects.annotate(
            employee_count=Count('employees', filter=Q(employees__employment_status='active'))
        ).order_by('name')

class DepartmentDetailView(LoginRequiredMixin, DetailView):
    model = Department
    template_name = 'hr/department_detail.html'
    context_object_name = 'department'

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_department'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['employees'] = self.object.employees.filter(employment_status='active')
        return context

class DepartmentCreateView(LoginRequiredMixin, CreateView):
    model = Department
    form_class = DepartmentForm
    template_name = 'hr/department_form.html'
    success_url = reverse_lazy('hr:department_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'add_department'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = 'Add New Department'
        return context

class DepartmentUpdateView(LoginRequiredMixin, UpdateView):
    model = Department
    form_class = DepartmentForm
    template_name = 'hr/department_form.html'
    success_url = reverse_lazy('hr:department_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'change_department'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = f'Edit Department - {self.object.name}'
        return context

class DepartmentDeleteView(LoginRequiredMixin, DeleteView):
    model = Department
    template_name = 'hr/department_confirm_delete.html'
    success_url = reverse_lazy('hr:department_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'delete_department'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

# Payslip Views
class PayslipListView(LoginRequiredMixin, ListView):
    model = Payslip
    template_name = 'hr/payslip_list.html'
    context_object_name = 'payslips'
    paginate_by = 20

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_payslip'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        queryset = Payslip.objects.select_related('employee', 'employee__department')

        # Filter by employee
        employee_id = self.request.GET.get('employee')
        if employee_id:
            queryset = queryset.filter(employee__employee_id=employee_id)

        # Filter by pay period
        pay_period = self.request.GET.get('pay_period')
        if pay_period:
            try:
                year, month = map(int, pay_period.split('-'))
                queryset = queryset.filter(
                    pay_period_start__year=year,
                    pay_period_start__month=month
                )
            except ValueError:
                pass

        return queryset.order_by('-pay_period_start')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['employees'] = Employee.objects.filter(employment_status='active').order_by('first_name')
        return context

class PayslipDetailView(LoginRequiredMixin, DetailView):
    model = Payslip
    template_name = 'hr/payslip_detail.html'
    context_object_name = 'payslip'
    slug_field = 'payslip_number'
    slug_url_kwarg = 'payslip_number'

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_payslip'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

@login_required
def payslip_pdf_download(request, payslip_number):
    """Generate and download payslip as PDF"""
    payslip = get_object_or_404(Payslip, payslip_number=payslip_number)
    
    if not has_permission(request.user, 'download_payslip'): # Example dynamic permission
        raise PermissionDenied

    # Render the payslip template as HTML
    html_string = render_to_string('hr/payslip_pdf.html', {
        'payslip': payslip,
        'company_name': 'Optinet Global Links',
        'is_pdf': True
    })

    # Create PDF from HTML
    font_config = FontConfiguration()

    # CSS for PDF styling
    css_string = """
    @page {
        size: A4;
        margin: 1cm;
    }

    body {
        font-family: Arial, sans-serif;
        font-size: 10pt;
        line-height: 1.4;
        color: #333;
    }

    .payslip-header {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        padding: 20px;
        margin-bottom: 20px;
        border-radius: 8px;
    }

    .company-logo {
        font-size: 24px;
        font-weight: bold;
        margin-bottom: 5px;
    }

    .payslip-number {
        font-size: 18px;
        margin-bottom: 10px;
    }

    .info-table {
        width: 100%;
        border-collapse: collapse;
        margin-bottom: 15px;
    }

    .info-table td {
        padding: 6px;
        border-bottom: 1px solid #eee;
    }

    .info-table .label {
        font-weight: bold;
        width: 40%;
    }

    .section-header {
        background-color: #f8f9fa;
        padding: 10px;
        margin: 15px 0 5px 0;
        font-weight: bold;
        border-left: 4px solid #667eea;
    }

    .earnings-section {
        border-left-color: #28a745;
    }

    .deductions-section {
        border-left-color: #dc3545;
    }

    .breakdown-table {
        width: 100%;
        border-collapse: collapse;
        margin-bottom: 15px;
    }

    .breakdown-table th,
    .breakdown-table td {
        padding: 6px 10px;
        text-align: left;
        border-bottom: 1px solid #ddd;
    }

    .breakdown-table th {
        background-color: #f8f9fa;
        font-weight: bold;
    }

    .breakdown-table .amount {
        text-align: right;
        font-weight: bold;
    }

    .breakdown-table .sub-item {
        padding-left: 20px;
        font-size: 9pt;
        color: #666;
    }

    .total-row {
        background-color: #f8f9fa;
        font-weight: bold;
        border-top: 2px solid #333;
    }

    .net-salary {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        padding: 15px;
        text-align: center;
        font-size: 16pt;
        font-weight: bold;
        margin: 20px 0;
        border-radius: 5px;
    }

    .footer-info {
        margin-top: 30px;
        font-size: 8pt;
        color: #666;
        text-align: center;
        border-top: 1px solid #eee;
        padding-top: 10px;
    }
    """

    css = CSS(string=css_string, font_config=font_config)

    # Generate PDF
    html = HTML(string=html_string)
    pdf_file = html.write_pdf(font_config=font_config, stylesheets=[css])

    # Create response
    response = HttpResponse(pdf_file, content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="payslip_{payslip.payslip_number}.pdf"'

    return response

@login_required
def generate_payslips(request):
    """Generate payslips for all active employees"""
    if not has_permission(request.user, 'generate_payslip'): # Example dynamic permission
        raise PermissionDenied

    if request.method == 'POST':
        try:
            month = int(request.POST.get('month', date.today().month))
            year = int(request.POST.get('year', date.today().year))
            employee_id = request.POST.get('employee_id')  # For individual processing
        except (ValueError, TypeError):
            messages.error(request, 'Invalid month or year provided.')
            return redirect('hr:generate_payslips')

        # Get the first and last day of the selected month
        pay_period_start = date(year, month, 1)
        if month == 12:
            pay_period_end = date(year + 1, 1, 1) - timedelta(days=1)
        else:
            pay_period_end = date(year, month + 1, 1) - timedelta(days=1)

        # Get employees to process
        if employee_id:
            # Individual processing
            try:
                active_employees = [Employee.objects.get(employee_id=employee_id)]
            except Employee.DoesNotExist:
                messages.error(request, 'Employee not found.')
                return redirect('hr:generate_payslips')
        else:
            # Bulk processing
            active_employees = Employee.objects.filter(employment_status='active')

        generated_count = 0

        for employee in active_employees:
            # Check if payslip already exists for this period
            existing_payslip = Payslip.objects.filter(
                employee=employee,
                pay_period_start=pay_period_start,
                pay_period_end=pay_period_end
            ).first()

            if not existing_payslip:
                # Calculate bonuses for the month
                monthly_bonuses = Bonus.objects.filter(
                    employee=employee,
                    is_active=True,
                    date_earned__gte=pay_period_start,
                    date_earned__lte=pay_period_end
                ).aggregate(total=Sum('amount'))['total'] or Decimal('0.00')

                # Calculate deductions for the month
                monthly_deductions = Deduction.objects.filter(
                    employee=employee,
                    is_active=True,
                    start_date__lte=pay_period_end
                ).filter(
                    Q(end_date__isnull=True) | Q(end_date__gte=pay_period_start)
                ).aggregate(total=Sum('amount'))['total'] or Decimal('0.00')

                # Calculate basic tax deductions (simplified - you can enhance this)
                gross_salary = employee.basic_salary + monthly_bonuses

                # Simple PAYE calculation (you should implement proper tax brackets)
                paye_tax = Decimal('0.00')
                if gross_salary > Decimal('24000'):  # Basic tax-free amount
                    paye_tax = (gross_salary - Decimal('24000')) * Decimal('0.10')  # 10% above threshold

                # NHIF contribution (simplified)
                nhif_deduction = Decimal('0.00')
                if gross_salary >= Decimal('6000'):
                    nhif_deduction = min(Decimal('1700'), gross_salary * Decimal('0.025'))  # 2.5% capped at 1700

                # NSSF contribution (simplified)
                nssf_deduction = min(Decimal('1080'), gross_salary * Decimal('0.06'))  # 6% capped at 1080

                # Create payslip
                payslip = Payslip.objects.create(
                    employee=employee,
                    pay_period_start=pay_period_start,
                    pay_period_end=pay_period_end,
                    pay_date=pay_period_end + timedelta(days=5),  # Pay 5 days after period end
                    basic_salary=employee.basic_salary,
                    total_bonuses=monthly_bonuses,
                    total_deductions=monthly_deductions,
                    paye_tax=paye_tax,
                    nhif_deduction=nhif_deduction,
                    nssf_deduction=nssf_deduction,
                    is_generated=True,
                    generated_by=request.user
                )
                generated_count += 1

        messages.success(request, f'Successfully generated {generated_count} payslips for {pay_period_start.strftime("%B %Y")}')
        return redirect('hr:payslip_list')

    # For GET request, show the form
    today = date.today()
    context = {
        'current_month': today.month,
        'current_year': today.year,
        'months': [
            (1, 'January'), (2, 'February'), (3, 'March'), (4, 'April'),
            (5, 'May'), (6, 'June'), (7, 'July'), (8, 'August'),
            (9, 'September'), (10, 'October'), (11, 'November'), (12, 'December')
        ],
        'years': range(today.year - 2, today.year + 2),
        'employees': Employee.objects.filter(employment_status__in=['active', 'terminated']).order_by('first_name')
    }
    return render(request, 'hr/generate_payslips.html', context)

@login_required
@user_passes_test(lambda u: has_permission(u, 'send_invitation')) # Example dynamic permission
def send_employee_invitation(request, employee_id):
    """Send invitation email to employee"""
    employee = get_object_or_404(Employee, employee_id=employee_id)

    if employee.user:
        messages.warning(request, f'{employee.full_name} already has an account.')
        return redirect('hr:employee_detail', employee_id=employee.employee_id)

    # Send invitation
    success, message = send_invitation_email('employee', employee, request)

    if success:
        messages.success(request, message)
    else:
        messages.error(request, message)

    return redirect('hr:employee_detail', employee_id=employee.employee_id)

# Deduction Views
class DeductionListView(SuperuserRequiredMixin, ListView):
    model = Deduction
    template_name = 'hr/deduction_list.html'
    context_object_name = 'deductions'
    paginate_by = 20

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_deduction'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        queryset = Deduction.objects.select_related('employee')

        # Filter by employee
        employee_id = self.request.GET.get('employee')
        if employee_id:
            queryset = queryset.filter(employee__employee_id=employee_id)

        # Filter by type
        deduction_type = self.request.GET.get('type')
        if deduction_type:
            queryset = queryset.filter(deduction_type=deduction_type)

        return queryset.order_by('-created_at')

class DeductionCreateView(SuperuserRequiredMixin, CreateView):
    model = Deduction
    form_class = DeductionForm
    template_name = 'hr/deduction_form.html'
    success_url = reverse_lazy('hr:deduction_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'add_deduction'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        return super().form_valid(form)

class DeductionUpdateView(SuperuserRequiredMixin, UpdateView):
    model = Deduction
    form_class = DeductionForm
    template_name = 'hr/deduction_form.html'
    success_url = reverse_lazy('hr:deduction_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'change_deduction'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

class DeductionDeleteView(SuperuserRequiredMixin, DeleteView):
    model = Deduction
    template_name = 'hr/deduction_confirm_delete.html'
    success_url = reverse_lazy('hr:deduction_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'delete_deduction'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

# Bonus Views
class BonusListView(SuperuserRequiredMixin, ListView):
    model = Bonus
    template_name = 'hr/bonus_list.html'
    context_object_name = 'bonuses'
    paginate_by = 20

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_bonus'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        queryset = Bonus.objects.select_related('employee')

        # Filter by employee
        employee_id = self.request.GET.get('employee')
        if employee_id:
            queryset = queryset.filter(employee__employee_id=employee_id)

        # Filter by type
        bonus_type = self.request.GET.get('type')
        if bonus_type:
            queryset = queryset.filter(bonus_type=bonus_type)

        return queryset.order_by('-created_at')

class BonusCreateView(SuperuserRequiredMixin, CreateView):
    model = Bonus
    form_class = BonusForm
    template_name = 'hr/bonus_form.html'
    success_url = reverse_lazy('hr:bonus_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'add_bonus'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        return super().form_valid(form)

class BonusUpdateView(SuperuserRequiredMixin, UpdateView):
    model = Bonus
    form_class = BonusForm
    template_name = 'hr/bonus_form.html'
    success_url = reverse_lazy('hr:bonus_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'change_bonus'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

class BonusDeleteView(SuperuserRequiredMixin, DeleteView):
    model = Bonus
    template_name = 'hr/bonus_confirm_delete.html'
    success_url = reverse_lazy('hr:bonus_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'delete_bonus'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

# Employee Account Setup View
class EmployeeAccountSetupView(DetailView):
    model = EmployeeInvitation
    template_name = 'hr/employee_account_setup.html'
    slug_field = 'token'
    slug_url_kwarg = 'token'

    def get_object(self):
        invitation = get_object_or_404(EmployeeInvitation, token=self.kwargs['token'])
        if not invitation.is_valid:
            messages.error(self.request, 'This invitation link has expired or been used.')
            return None
        return invitation

    def post(self, request, *args, **kwargs):
        invitation = self.get_object()
        if not invitation:
            return redirect('accounts:login')

        # Check if the user has permission to create an account via invitation
        if not has_permission(request.user, 'setup_employee_account'): # Example dynamic permission
            messages.error(request, "You do not have permission to set up an account via this link.")
            return redirect('accounts:login')

        # Create user account for employee using employee_id as username
        employee = invitation.employee
        password = request.POST.get('password')

        # Use employee_id as username
        username = employee.employee_id

        if User.objects.filter(username=username).exists():
            messages.error(request, 'An account already exists for this employee.')
            return self.get(request, *args, **kwargs)

        # Determine role based on department or job title
        role = 'technician'  # Default role
        if employee.department and employee.department.name.lower() in ['admin', 'management', 'hr']:
            role = 'admin'

        user = User.objects.create_user(
            username=username,
            password=password,
            email=employee.email,
            first_name=employee.first_name,
            last_name=employee.last_name,
            role=role
        )

        # Link employee to user
        employee.user = user
        employee.save()

        # Mark invitation as used
        invitation.is_used = True
        invitation.used_at = timezone.now()
        invitation.save()

        messages.success(request, 'Account created successfully! You can now log in.')
        return redirect('accounts:login')

# Document Views
class EmployeeDocumentListView(LoginRequiredMixin, ListView):
    model = EmployeeDocument
    template_name = 'hr/document_list.html'
    context_object_name = 'documents'
    paginate_by = 20

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_document'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        queryset = EmployeeDocument.objects.select_related('employee', 'uploaded_by').filter(is_active=True)

        # Filter by employee
        employee_id = self.request.GET.get('employee')
        if employee_id:
            queryset = queryset.filter(employee__employee_id=employee_id)

        # Filter by document type
        doc_type = self.request.GET.get('type')
        if doc_type:
            queryset = queryset.filter(document_type=doc_type)

        return queryset.order_by('-uploaded_at')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['employees'] = Employee.objects.filter(employment_status='active').order_by('first_name')
        context['document_types'] = EmployeeDocument.DOCUMENT_TYPE_CHOICES
        return context

class EmployeeDocumentCreateView(LoginRequiredMixin, CreateView):
    model = EmployeeDocument
    form_class = EmployeeDocumentForm
    template_name = 'hr/document_form.html'

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'add_document'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        if 'employee_id' in self.kwargs:
            try:
                employee = Employee.objects.get(employee_id=self.kwargs['employee_id'])
                kwargs['employee'] = employee
            except Employee.DoesNotExist:
                pass
        return kwargs

    def form_valid(self, form):
        form.instance.uploaded_by = self.request.user
        messages.success(self.request, 'Document uploaded successfully.')
        return super().form_valid(form)

    def get_success_url(self):
        if 'employee_id' in self.kwargs:
            return reverse_lazy('hr:employee_detail', kwargs={'employee_id': self.kwargs['employee_id']})
        return reverse_lazy('hr:document_list')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = 'Upload Employee Document'
        if 'employee_id' in self.kwargs:
            try:
                context['employee'] = Employee.objects.get(employee_id=self.kwargs['employee_id'])
            except Employee.DoesNotExist:
                pass
        return context

class EmployeeDocumentDeleteView(LoginRequiredMixin, DeleteView):
    model = EmployeeDocument
    template_name = 'hr/document_confirm_delete.html'
    success_url = reverse_lazy('hr:document_list')

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'delete_document'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        # Soft delete - mark as inactive instead of deleting
        self.object.is_active = False
        self.object.save()
        messages.success(request, 'Document deleted successfully.')
        return redirect(self.success_url)

@login_required
def download_employee_document(request, pk):
    """Download employee document"""
    document = get_object_or_404(EmployeeDocument, pk=pk, is_active=True)

    if not has_permission(request.user, 'download_document'): # Example dynamic permission
        raise PermissionDenied

    from django.http import FileResponse
    from django.utils.encoding import smart_str
    import os

    if document.document_file:
        response = FileResponse(
            document.document_file.open('rb'),
            as_attachment=True,
            filename=smart_str(os.path.basename(document.document_file.name))
        )
        return response
    else:
        messages.error(request, 'Document file not found.')
        return redirect('hr:document_list')

# Attendance Views
class AttendanceListView(LoginRequiredMixin, ListView):
    model = Attendance
    template_name = 'hr/attendance_list.html'
    context_object_name = 'attendance_records'
    paginate_by = 25

    def dispatch(self, request, *args, **kwargs):
        if not has_permission(request.user, 'view_attendance'): # Example dynamic permission
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        queryset = Attendance.objects.select_related('employee').order_by('-date', 'employee__first_name')

        # Filter by employee
        employee_id = self.request.GET.get('employee')
        if employee_id:
            queryset = queryset.filter(employee__employee_id=employee_id)

        # Filter by date range
        start_date = self.request.GET.get('start_date')
        end_date = self.request.GET.get('end_date')
        if start_date:
            queryset = queryset.filter(date__gte=start_date)
        if end_date:
            queryset = queryset.filter(date__lte=end_date)

        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['employees'] = Employee.objects.filter(employment_status='active').order_by('first_name')
        return context

@login_required
def attendance_create(request):
    """Create attendance record"""
    if not has_permission(request.user, 'add_attendance'): # Example dynamic permission
        raise PermissionDenied

    if request.method == 'POST':
        form = AttendanceForm(request.POST)
        if form.is_valid():
            attendance = form.save(commit=False)
            attendance.recorded_by = request.user
            attendance.save()
            messages.success(request, f'Attendance record created for {attendance.employee.full_name}')
            return redirect('hr:attendance_list')
    else:
        form = AttendanceForm()

    return render(request, 'hr/attendance_form.html', {'form': form, 'title': 'Record Attendance'})

@login_required
def bulk_attendance_create(request):
    """Create bulk attendance records"""
    if not has_permission(request.user, 'add_attendance_bulk'): # Example dynamic permission
        raise PermissionDenied

    if request.method == 'POST':
        form = BulkAttendanceForm(request.POST)
        if form.is_valid():
            date = form.cleaned_data['date']
            employees = form.cleaned_data['employees']
            status = form.cleaned_data['status']

            if not employees:
                # If no employees selected, mark all active employees
                employees = Employee.objects.filter(employment_status='active')

            created_count = 0
            for employee in employees:
                attendance, created = Attendance.objects.get_or_create(
                    employee=employee,
                    date=date,
                    defaults={
                        'status': status,
                        'recorded_by': request.user
                    }
                )
                if created:
                    created_count += 1

            messages.success(request, f'Created {created_count} attendance records for {date}')
            return redirect('hr:attendance_list')
    else:
        form = BulkAttendanceForm()

    context = {
        'form': form,
        'title': 'Bulk Attendance Recording'
    }
    return render(request, 'hr/bulk_attendance_form.html', context)

# Services Views
# HRServiceListView removed - redirecting to customers:service_list instead