from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied, ValidationError
from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404, redirect, render

from apps.accounts.permissions import ROLE_HR_ADMIN, ROLE_SUPER_ADMIN, has_role, scope_queryset_by_company
from .forms import FinalSettlementForm, OverrideClearanceForm, SettlementPaymentForm, FinalWorkingDayForm
from .models import ClearanceItem, ExitCase, FinalSettlement
from .services import mark_settlement_paid, override_clearance, prepare_final_settlement, finalize_working_day


def _visible_cases(user):
    qs = ExitCase.objects.select_related("employee", "employee__department").prefetch_related("clearances")
    qs = scope_queryset_by_company(user, qs, "employee__company")
    if user.is_superuser or has_role(user, ROLE_SUPER_ADMIN, ROLE_HR_ADMIN):
        return qs
    employee = getattr(user, "employee_profile", None)
    if not employee:
        return qs.none()
    return qs.filter(employee=employee)

@login_required
def case_list(request):
    page_obj = Paginator(_visible_cases(request.user).order_by("-created_at"), 100).get_page(request.GET.get("page"))
    return render(request, "exits/case_list.html", {"cases": page_obj.object_list, "page_obj": page_obj})

@login_required
def case_detail(request, pk):
    case = get_object_or_404(_visible_cases(request.user), pk=pk)
    settlement = getattr(case, "final_settlement", None)
    return render(request, "exits/case_detail.html", {"case": case, "settlement": settlement})

@login_required
def clearance_override(request, pk):
    if not (request.user.is_superuser or has_role(request.user, ROLE_SUPER_ADMIN, ROLE_HR_ADMIN)):
        raise PermissionDenied("Only HR/Super Admin can override a clearance.")
    item = get_object_or_404(scope_queryset_by_company(request.user, ClearanceItem.objects.select_related("exit_case__employee"), "exit_case__employee__company"), pk=pk)
    form = OverrideClearanceForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        try:
            override_clearance(item, user=request.user, reason=form.cleaned_data["reason"])
            messages.success(request, "Clearance override saved with audit trail.")
            return redirect("exits:detail", pk=item.exit_case_id)
        except ValidationError as exc:
            form.add_error(None, exc)
    return render(request, "exits/simple_form.html", {"form": form, "title": "Override clearance"})

@login_required
def prepare_settlement(request, pk):
    if not (request.user.is_superuser or has_role(request.user, ROLE_SUPER_ADMIN, ROLE_HR_ADMIN)):
        raise PermissionDenied("Only HR/Super Admin can prepare final settlement.")
    case = get_object_or_404(scope_queryset_by_company(request.user, ExitCase.objects.all(), "employee__company"), pk=pk)
    existing = getattr(case, "final_settlement", None)
    initial = {}
    if existing and existing.status in {FinalSettlement.Status.DRAFT, FinalSettlement.Status.RETURNED, FinalSettlement.Status.REJECTED}:
        initial = {
            "leave_encashment": existing.leave_encashment,
            "other_earnings": existing.other_earnings,
            "other_deductions": existing.other_deductions,
        }
    form = FinalSettlementForm(request.POST or None, initial=initial)
    if request.method == "POST" and form.is_valid():
        try:
            prepare_final_settlement(case, user=request.user, **form.cleaned_data)
            messages.success(request, "Final settlement submitted/resubmitted for approval; reviewer history is preserved in audit trail.")
            return redirect("exits:detail", pk=case.pk)
        except ValidationError as exc:
            form.add_error(None, exc)
    return render(request, "exits/simple_form.html", {"form": form, "title": "Prepare final settlement"})

@login_required
def mark_paid(request, pk):
    if not (request.user.is_superuser or has_role(request.user, ROLE_SUPER_ADMIN, ROLE_HR_ADMIN)):
        raise PermissionDenied("Only HR/Super Admin can post final settlement payment.")
    settlement = get_object_or_404(scope_queryset_by_company(request.user, FinalSettlement.objects.select_related("exit_case__employee"), "exit_case__employee__company"), pk=pk)
    form = SettlementPaymentForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        try:
            mark_settlement_paid(settlement, user=request.user, payment_reference=form.cleaned_data["payment_reference"])
            messages.success(request, "Final settlement payment posted; exit case completed.")
            return redirect("exits:detail", pk=settlement.exit_case_id)
        except ValidationError as exc:
            form.add_error(None, exc)
    return render(request, "exits/simple_form.html", {"form": form, "title": "Post final settlement payment"})


@login_required
def set_final_working_day(request, pk):
    if not (request.user.is_superuser or has_role(request.user, ROLE_SUPER_ADMIN, ROLE_HR_ADMIN)):
        raise PermissionDenied("Only HR/Super Admin can finalize the working day.")
    case = get_object_or_404(scope_queryset_by_company(request.user, ExitCase.objects.select_related("employee"), "employee__company"), pk=pk)
    form = FinalWorkingDayForm(request.POST or None, initial={"final_working_day": case.final_working_day or case.proposed_last_working_day})
    if request.method == "POST" and form.is_valid():
        try:
            finalize_working_day(case, final_working_day=form.cleaned_data["final_working_day"], user=request.user, reason=form.cleaned_data.get("reason", ""))
            messages.success(request, "Final Working Day finalized and will be used by attendance/payroll/final settlement.")
            return redirect("exits:detail", pk=case.pk)
        except ValidationError as exc:
            form.add_error(None, exc)
    return render(request, "exits/simple_form.html", {"form": form, "title": "Finalize Working Day"})
