from functools import wraps
from datetime import date
from django.shortcuts import redirect, get_object_or_404
from django.http import HttpResponseNotFound, HttpResponseForbidden
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import AccessMixin
from django.core.exceptions import PermissionDenied
from django.contrib import messages

def job_not_expired(view_func):
    @wraps(view_func)
    def _wrapped_view(request, job_id, *args, **kwargs):

        from .models import JobPosting
        job = get_object_or_404(JobPosting, pk=job_id)

        if job.expiration_date and job.application_deadline< date.today():
            return redirect('expired_job_page')

        return view_func(request, job_id, *args, **kwargs)
    return _wrapped_view


def user_type_required(allowed_types=None, login_url=None):
    """
    Decorator to restrict view access based on user type.

    Args:
        allowed_types (list): List of allowed user types ['staff', 'agency', 'candidate']
        login_url (str): URL to redirect to if user is not authenticated
    """
    if allowed_types is None:
        allowed_types = ['staff']

    def decorator(view_func):
        @wraps(view_func)
        @login_required(login_url=login_url)
        def _wrapped_view(request, *args, **kwargs):
            user = request.user

            # Check if user has user_type attribute
            if not hasattr(user, 'user_type') or not user.user_type:
                messages.error(request, "User type not specified. Please contact administrator.")
                return redirect('account_login')

            # Check if user type is allowed
            if user.user_type not in allowed_types:
                # Log unauthorized access attempt
                messages.error(
                    request,
                    f"Access denied. This page is restricted to {', '.join(allowed_types)} users."
                )

                # Redirect based on user type
                if user.user_type == 'agency':
                    return redirect('agency_portal_dashboard')
                elif user.user_type == 'candidate':
                    return redirect('candidate_portal_dashboard')
                else:
                    return redirect('dashboard')

            return view_func(request, *args, **kwargs)
        return _wrapped_view
    return decorator


class UserTypeRequiredMixin(AccessMixin):
    """
    Mixin for class-based views to restrict access based on user type.
    """
    allowed_user_types = ['staff']  # Default to staff only
    login_url = '/accounts/login/'

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return self.handle_no_permission()

        # Check if user has user_type attribute
        if not hasattr(request.user, 'user_type') or not request.user.user_type:
            messages.error(request, "User type not specified. Please contact administrator.")
            return redirect('account_login')

        # Check if user type is allowed
        if request.user.user_type not in self.allowed_user_types:
            # Log unauthorized access attempt
            messages.error(
                request,
                f"Access denied. This page is restricted to {', '.join(self.allowed_user_types)} users."
            )

            # Redirect based on user type
            if request.user.user_type == 'agency':
                return redirect('agency_portal_dashboard')
            elif request.user.user_type == 'candidate':
                return redirect('candidate_portal_dashboard')
            else:
                return redirect('dashboard')

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

    def handle_no_permission(self):
        if self.request.user.is_authenticated:
            # User is authenticated but doesn't have permission
            messages.error(
                self.request,
                f"Access denied. This page is restricted to {', '.join(self.allowed_user_types)} users."
            )
            return redirect('dashboard')
        else:
            # User is not authenticated
            return super().handle_no_permission()


class StaffRequiredMixin(UserTypeRequiredMixin):
    """Mixin to restrict access to staff users only."""
    allowed_user_types = ['staff']


class AgencyRequiredMixin(UserTypeRequiredMixin):
    """Mixin to restrict access to agency users only."""
    allowed_user_types = ['agency']
    login_url = '/accounts/login/'


class CandidateRequiredMixin(UserTypeRequiredMixin):
    """Mixin to restrict access to candidate users only."""
    allowed_user_types = ['candidate']
    login_url = '/accounts/login/'


class StaffOrAgencyRequiredMixin(UserTypeRequiredMixin):
    """Mixin to restrict access to staff and agency users."""
    allowed_user_types = ['staff', 'agency']


class StaffOrCandidateRequiredMixin(UserTypeRequiredMixin):
    """Mixin to restrict access to staff and candidate users."""
    allowed_user_types = ['staff', 'candidate']


def agency_user_required(view_func):
    """Decorator to restrict view to agency users only."""
    return user_type_required(['agency'], login_url='/accounts/login/')(view_func)


def candidate_user_required(view_func):
    """Decorator to restrict view to candidate users only."""
    return user_type_required(['candidate'], login_url='/accounts/login/')(view_func)


def staff_user_required(view_func):
   
    """Decorator to restrict view to staff users only."""
    return user_type_required(['staff'])(view_func)


def staff_or_agency_required(view_func):
    """Decorator to restrict view to staff and agency users."""
    return user_type_required(['staff', 'agency'], login_url='/accounts/login/')(view_func)


def staff_or_candidate_required(view_func):
    """Decorator to restrict view to staff and candidate users."""
    return user_type_required(['staff', 'candidate'], login_url='/accounts/login/')(view_func)
