"""
HRM API Views - v1.

ویوهای REST API ماژول مدیریت منابع انسانی.
"""
import logging
from datetime import date
from uuid import uuid4

from django.db.models import Q
from rest_framework import viewsets, status, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend

from ...infrastructure.persistence.models import (
    LegalEntityModel,
    LocationModel,
    EmployeeModel,
    EmploymentRecordModel,
    EmployeeDocumentModel,
    JobFamilyModel,
    JobTitleModel,
    PositionModel,
    ReportingLineModel,
)
from ...infrastructure.persistence.models_extended import (
    WorkScheduleModel,
    ShiftPatternModel,
    TimesheetModel,
    AttendanceRecordModel,
    LeavePolicyModel,
    LeaveBalanceModel,
    LeaveRequestModel,
    PayGradeModel,
    CompensationRecordModel,
    BankAccountModel,
    CostAllocationModel,
)
from .serializers import (
    LegalEntitySerializer,
    LegalEntityListSerializer,
    LocationSerializer,
    LocationListSerializer,
    EmployeeSerializer,
    EmployeeListSerializer,
    EmployeeCreateSerializer,
    EmployeeTerminateSerializer,
    EmployeeTransferSerializer,
    EmploymentRecordSerializer,
    EmployeeDocumentSerializer,
    JobFamilySerializer,
    JobTitleSerializer,
    PositionSerializer,
    PositionListSerializer,
    ReportingLineSerializer,
    WorkScheduleSerializer,
    ShiftPatternSerializer,
    TimesheetSerializer,
    TimesheetApproveSerializer,
    AttendanceRecordSerializer,
    AttendanceCheckInSerializer,
    LeavePolicySerializer,
    LeaveBalanceSerializer,
    LeaveRequestSerializer,
    LeaveRequestCreateSerializer,
    LeaveActionSerializer,
    PayGradeSerializer,
    CompensationRecordSerializer,
    SetSalarySerializer,
    BankAccountSerializer,
    CostAllocationSerializer,
)
from .permissions import (
    CanManageOrganization,
    CanManageEmployees,
    CanManagePositions,
    CanManageAttendance,
    CanManageLeave,
    CanManagePayroll,
)


class TenantQuerySetMixin:
    """فیلتر خودکار بر اساس tenant."""

    def get_queryset(self):
        qs = super().get_queryset()
        if hasattr(self.request, "tenant"):
            return qs.filter(tenant=self.request.tenant)
        return qs

    def perform_create(self, serializer):
        kwargs = {"id": uuid4()}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant
        serializer.save(**kwargs)


# ═══════════════════════════════════════════════════
# 1. Organization Structure
# ═══════════════════════════════════════════════════

class LegalEntityViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """
    API مدیریت شخصیت‌های حقوقی.

    list: لیست شخصیت‌های حقوقی
    create: ایجاد شخصیت حقوقی جدید
    retrieve: جزئیات شخصیت حقوقی
    update: بروزرسانی شخصیت حقوقی
    destroy: حذف شخصیت حقوقی
    """

    queryset = LegalEntityModel.objects.all()
    permission_classes = [CanManageOrganization]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ["entity_type", "is_active"]
    search_fields = ["name", "name_en", "national_id", "registration_number"]
    ordering_fields = ["name", "created_at"]
    ordering = ["name"]

    def get_serializer_class(self):
        if self.action == "list":
            return LegalEntityListSerializer
        return LegalEntitySerializer


class LocationViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """
    API مدیریت مکان‌ها.

    list: لیست مکان‌ها
    create: ایجاد مکان جدید
    retrieve: جزئیات مکان
    update: بروزرسانی مکان
    destroy: حذف مکان
    """

    queryset = LocationModel.objects.all()
    permission_classes = [CanManageOrganization]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ["location_type", "legal_entity_id", "is_active", "province"]
    search_fields = ["name", "code", "city"]
    ordering_fields = ["name", "code", "created_at"]
    ordering = ["name"]

    def get_serializer_class(self):
        if self.action == "list":
            return LocationListSerializer
        return LocationSerializer


# ═══════════════════════════════════════════════════
# 2. Employee Master Data
# ═══════════════════════════════════════════════════

class EmployeeViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """
    API مدیریت کارمندان.

    list: لیست کارمندان
    create: استخدام کارمند جدید
    retrieve: جزئیات کارمند
    update: بروزرسانی اطلاعات کارمند
    terminate: خاتمه همکاری
    transfer: انتقال کارمند
    """

    queryset = EmployeeModel.objects.all()
    permission_classes = [CanManageEmployees]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = [
        "employment_status", "employment_type", "gender",
        "org_unit_id", "legal_entity_id", "location_id",
        "is_active",
    ]
    search_fields = [
        "first_name", "last_name", "first_name_en", "last_name_en",
        "employee_code", "national_code", "email",
    ]
    ordering_fields = ["last_name", "employee_code", "hire_date", "created_at"]
    ordering = ["last_name", "first_name"]

    def get_serializer_class(self):
        if self.action == "list":
            return EmployeeListSerializer
        if self.action == "create":
            return EmployeeCreateSerializer
        if self.action == "terminate":
            return EmployeeTerminateSerializer
        if self.action == "transfer":
            return EmployeeTransferSerializer
        return EmployeeSerializer

    def perform_create(self, serializer):
        """ایجاد کارمند + ساخت خودکار حساب کاربری در صورت وجود ایمیل."""
        kwargs = {"id": uuid4()}
        if hasattr(self.request, "tenant"):
            kwargs["tenant"] = self.request.tenant

        employee = serializer.save(**kwargs)

        # Auto-create a User account if employee has email
        email = employee.email
        if email:
            try:
                from apps.core.auth.models import User
                # Don't create if a user with this email already exists
                existing_user = User.objects.filter(email=email).first()
                if existing_user:
                    employee.user = existing_user
                else:
                    import secrets
                    temp_password = secrets.token_urlsafe(12)
                    user = User.objects.create_user(
                        email=email,
                        password=temp_password,
                        first_name=employee.first_name,
                        last_name=employee.last_name,
                        phone=employee.mobile or employee.phone or None,
                        is_active=True,
                    )
                    # Assign tenant to user
                    if hasattr(self.request, "tenant"):
                        user.tenant = self.request.tenant
                        user.save(update_fields=["tenant"])
                    employee.user = user
                employee.save(update_fields=["user"])
            except Exception as e:
                logger = logging.getLogger("apps")
                logger.warning("Failed to auto-create user for employee %s: %s", employee.employee_code, e)

    @action(detail=True, methods=["post"], url_path="terminate")
    def terminate(self, request, pk=None):
        """خاتمه همکاری کارمند."""
        employee = self.get_object()
        serializer = EmployeeTerminateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        employee.employment_status = EmployeeModel.EmploymentStatus.TERMINATED
        employee.termination_date = serializer.validated_data["termination_date"]
        employee.is_active = False
        employee.save()

        return Response(
            EmployeeSerializer(employee).data,
            status=status.HTTP_200_OK,
        )

    @action(detail=True, methods=["post"], url_path="transfer")
    def transfer(self, request, pk=None):
        """انتقال کارمند به واحد سازمانی جدید."""
        employee = self.get_object()
        serializer = EmployeeTransferSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        employee.org_unit_id = serializer.validated_data["new_org_unit_id"]
        if "new_position_id" in serializer.validated_data:
            employee.primary_position_id = serializer.validated_data["new_position_id"]
        if "new_location_id" in serializer.validated_data:
            employee.location_id = serializer.validated_data["new_location_id"]
        employee.save()

        return Response(
            EmployeeSerializer(employee).data,
            status=status.HTTP_200_OK,
        )

    @action(detail=True, methods=["get"], url_path="records")
    def records(self, request, pk=None):
        """سوابق استخدامی کارمند."""
        records = EmploymentRecordModel.objects.filter(
            employee_id=pk
        ).order_by("-start_date")
        serializer = EmploymentRecordSerializer(records, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=["get"], url_path="documents")
    def documents(self, request, pk=None):
        """مدارک کارمند."""
        docs = EmployeeDocumentModel.objects.filter(employee_id=pk)
        serializer = EmployeeDocumentSerializer(docs, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=["get"], url_path="leave-balances")
    def leave_balances(self, request, pk=None):
        """مانده مرخصی کارمند."""
        year = request.query_params.get("year", date.today().year)
        balances = LeaveBalanceModel.objects.filter(
            employee_id=pk, year=year
        )
        serializer = LeaveBalanceSerializer(balances, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=["get"], url_path="compensation")
    def compensation(self, request, pk=None):
        """اطلاعات حقوقی فعلی."""
        try:
            record = CompensationRecordModel.objects.get(
                employee_id=pk, is_current=True
            )
            serializer = CompensationRecordSerializer(record)
            return Response(serializer.data)
        except CompensationRecordModel.DoesNotExist:
            return Response(
                {"detail": "سابقه حقوقی فعلی یافت نشد."},
                status=status.HTTP_404_NOT_FOUND,
            )


class EmploymentRecordViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت سوابق استخدامی."""

    queryset = EmploymentRecordModel.objects.all()
    serializer_class = EmploymentRecordSerializer
    permission_classes = [CanManageEmployees]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ["employee", "contract_type", "is_current"]


class EmployeeDocumentViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت مدارک کارمندان."""

    queryset = EmployeeDocumentModel.objects.all()
    serializer_class = EmployeeDocumentSerializer
    permission_classes = [CanManageEmployees]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ["employee", "document_type"]


# ═══════════════════════════════════════════════════
# 3. Position & Job
# ═══════════════════════════════════════════════════

class JobFamilyViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت خانواده‌های شغلی."""

    queryset = JobFamilyModel.objects.all()
    serializer_class = JobFamilySerializer
    permission_classes = [CanManagePositions]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ["is_active"]
    search_fields = ["name", "code"]
    ordering = ["name"]


class JobTitleViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت عناوین شغلی."""

    queryset = JobTitleModel.objects.all()
    serializer_class = JobTitleSerializer
    permission_classes = [CanManagePositions]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ["job_family", "level", "is_active"]
    search_fields = ["title", "title_en", "code"]
    ordering = ["name"]


class PositionViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """
    API مدیریت پست‌های سازمانی.

    list: لیست پست‌ها
    create: ایجاد پست جدید
    retrieve: جزئیات پست
    update: بروزرسانی پست
    vacant: پست‌های خالی
    fill: تخصیص نیرو به پست
    vacate: خالی کردن پست
    """

    queryset = PositionModel.objects.all()
    permission_classes = [CanManagePositions]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ["status", "org_unit_id", "is_key_position", "job_title"]
    search_fields = ["code", "title"]
    ordering_fields = ["code", "title", "created_at"]
    ordering = ["code"]

    def get_serializer_class(self):
        if self.action == "list":
            return PositionListSerializer
        return PositionSerializer

    @action(detail=False, methods=["get"], url_path="vacant")
    def vacant(self, request):
        """لیست پست‌های خالی."""
        qs = self.get_queryset().filter(
            status="ACTIVE", incumbent__isnull=True
        )
        serializer = PositionListSerializer(qs, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=["post"], url_path="fill")
    def fill(self, request, pk=None):
        """تخصیص نیرو به پست."""
        position = self.get_object()
        employee_id = request.data.get("employee_id")
        if not employee_id:
            return Response(
                {"detail": "شناسه کارمند الزامی است."},
                status=status.HTTP_400_BAD_REQUEST,
            )
        position.incumbent_id = employee_id
        position.save()
        return Response(PositionSerializer(position).data)

    @action(detail=True, methods=["post"], url_path="vacate")
    def vacate(self, request, pk=None):
        """خالی کردن پست."""
        position = self.get_object()
        position.incumbent = None
        position.save()
        return Response(PositionSerializer(position).data)

    @action(detail=False, methods=["get"], url_path="org-chart")
    def org_chart(self, request):
        """
        چارت سازمانی — ساختار درختی بر اساس reports_to.
        پارامتر اختیاری: root=<position_id> برای نمایش زیرمجموعه.
        """
        qs = self.get_queryset().select_related(
            "incumbent", "job_title", "reports_to"
        ).filter(status="ACTIVE")

        root_id = request.query_params.get("root")

        # Build id→position lookup and children map
        positions_by_id = {}
        children_map = {}
        for pos in qs:
            pid = str(pos.id)
            incumbent = pos.incumbent
            positions_by_id[pid] = {
                "id": pid,
                "title": pos.title,
                "code": pos.code,
                "job_title": pos.job_title.title if pos.job_title else "",
                "org_unit_id": str(pos.org_unit_id) if pos.org_unit_id else None,
                "incumbent_id": str(incumbent.id) if incumbent else None,
                "incumbent_name": (
                    f"{incumbent.first_name} {incumbent.last_name}".strip()
                    if incumbent else ""
                ),
                "is_key_position": pos.is_key_position,
                "status": pos.status,
                "parent_id": str(pos.reports_to_id) if pos.reports_to_id else None,
                "children": [],
            }
            parent_key = str(pos.reports_to_id) if pos.reports_to_id else "__root__"
            children_map.setdefault(parent_key, []).append(pid)

        def build_tree(node_id):
            node = positions_by_id.get(node_id)
            if not node:
                return None
            for child_id in children_map.get(node_id, []):
                child = build_tree(child_id)
                if child:
                    node["children"].append(child)
            return node

        if root_id and root_id in positions_by_id:
            tree = [build_tree(root_id)]
        else:
            # Build from root nodes (those with no parent or parent not in active set)
            root_ids = children_map.get("__root__", [])
            # Also add positions whose parent is not in active set
            active_ids = set(positions_by_id.keys())
            for pid, pos in positions_by_id.items():
                if pos["parent_id"] and pos["parent_id"] not in active_ids:
                    root_ids.append(pid)
            tree = [build_tree(rid) for rid in root_ids if build_tree(rid)]

        return Response({"data": tree})

    @action(detail=True, methods=["post"], url_path="move")
    def move_position(self, request, pk=None):
        """جابجایی پست در چارت سازمانی — تغییر reports_to."""
        position = self.get_object()
        new_parent_id = request.data.get("new_parent_id")

        if new_parent_id:
            # بررسی وجود والد جدید
            try:
                new_parent = self.get_queryset().get(pk=new_parent_id)
            except PositionModel.DoesNotExist:
                return Response(
                    {"error": {"code": "PARENT_NOT_FOUND", "message": "پست والد یافت نشد."}},
                    status=status.HTTP_404_NOT_FOUND,
                )
            # بررسی حلقه — نباید والد جدید فرزند مستقیم یا غیرمستقیم خودش باشد
            current = new_parent
            while current.reports_to_id:
                if str(current.reports_to_id) == str(position.id):
                    return Response(
                        {"error": {"code": "CIRCULAR_REFERENCE", "message": "جابجایی باعث ایجاد حلقه در ساختار سازمانی می‌شود."}},
                        status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                    )
                current = self.get_queryset().filter(pk=current.reports_to_id).first()
                if not current:
                    break
            position.reports_to = new_parent
        else:
            position.reports_to = None

        position.save()
        return Response(PositionSerializer(position).data)


class ReportingLineViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت خطوط گزارش‌دهی."""

    queryset = ReportingLineModel.objects.all()
    serializer_class = ReportingLineSerializer
    permission_classes = [CanManagePositions]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ["employee", "manager", "reporting_type", "is_primary"]


# ═══════════════════════════════════════════════════
# 4. Time & Attendance
# ═══════════════════════════════════════════════════

class WorkScheduleViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت برنامه‌های کاری."""

    queryset = WorkScheduleModel.objects.all()
    serializer_class = WorkScheduleSerializer
    permission_classes = [CanManageAttendance]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ["schedule_type", "is_active"]
    search_fields = ["name", "code"]
    ordering = ["name"]


class ShiftPatternViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت الگوهای شیفت."""

    queryset = ShiftPatternModel.objects.all()
    serializer_class = ShiftPatternSerializer
    permission_classes = [CanManageAttendance]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ["is_active"]
    search_fields = ["name", "code"]


class TimesheetViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """
    API مدیریت تایم‌شیت‌ها.

    list: لیست تایم‌شیت‌ها
    retrieve: جزئیات تایم‌شیت
    submit: ارسال تایم‌شیت برای تأیید
    review: تأیید/رد تایم‌شیت
    pending: تایم‌شیت‌های در انتظار تأیید
    """

    queryset = TimesheetModel.objects.all()
    serializer_class = TimesheetSerializer
    permission_classes = [CanManageAttendance]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["employee", "status"]
    ordering_fields = ["period_start", "created_at"]
    ordering = ["-period_start"]

    @action(detail=True, methods=["post"], url_path="submit")
    def submit(self, request, pk=None):
        """ارسال تایم‌شیت برای تأیید."""
        from django.utils import timezone

        timesheet = self.get_object()
        if timesheet.status != TimesheetModel.TimesheetStatus.DRAFT:
            return Response(
                {"detail": "فقط تایم‌شیت‌های پیش‌نویس قابل ارسال هستند."},
                status=status.HTTP_400_BAD_REQUEST,
            )
        timesheet.status = TimesheetModel.TimesheetStatus.SUBMITTED
        timesheet.submitted_at = timezone.now()
        timesheet.save()
        return Response(TimesheetSerializer(timesheet).data)

    @action(detail=True, methods=["post"], url_path="review")
    def review(self, request, pk=None):
        """تأیید یا رد تایم‌شیت."""
        from django.utils import timezone

        timesheet = self.get_object()
        serializer = TimesheetApproveSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        if timesheet.status != TimesheetModel.TimesheetStatus.SUBMITTED:
            return Response(
                {"detail": "فقط تایم‌شیت‌های ارسال‌شده قابل بررسی هستند."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        action_val = serializer.validated_data["action"]
        if action_val == "approve":
            timesheet.status = TimesheetModel.TimesheetStatus.APPROVED
            timesheet.approved_at = timezone.now()
            timesheet.approved_by = request.user.id
        else:
            timesheet.status = TimesheetModel.TimesheetStatus.REJECTED
            timesheet.rejection_reason = serializer.validated_data.get("reason", "")
        timesheet.save()
        return Response(TimesheetSerializer(timesheet).data)

    @action(detail=False, methods=["get"], url_path="pending")
    def pending(self, request):
        """تایم‌شیت‌های در انتظار تأیید."""
        qs = self.get_queryset().filter(
            status=TimesheetModel.TimesheetStatus.SUBMITTED
        ).order_by("submitted_at")
        serializer = TimesheetSerializer(qs, many=True)
        return Response(serializer.data)


class AttendanceRecordViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """
    API مدیریت حضور و غیاب.

    list: لیست رکوردهای حضور
    check_in: ثبت ورود
    check_out: ثبت خروج
    """

    queryset = AttendanceRecordModel.objects.all()
    serializer_class = AttendanceRecordSerializer
    permission_classes = [CanManageAttendance]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["employee", "attendance_date", "status", "source"]
    ordering = ["-attendance_date"]

    @action(detail=False, methods=["post"], url_path="check-in")
    def check_in(self, request):
        """ثبت ورود."""
        serializer = AttendanceCheckInSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data

        attendance_date = data["check_in"].date()
        record, created = AttendanceRecordModel.objects.get_or_create(
            employee_id=data["employee_id"],
            attendance_date=attendance_date,
            tenant=getattr(request, "tenant", None),
            defaults={
                "id": uuid4(),
                "check_in": data["check_in"],
                "source": data.get("source", "MANUAL"),
                "status": "PRESENT",
                "location_id": data.get("location_id"),
                "notes": data.get("notes", ""),
            },
        )
        if not created:
            record.check_in = data["check_in"]
            record.save()

        return Response(
            AttendanceRecordSerializer(record).data,
            status=status.HTTP_201_CREATED if created else status.HTTP_200_OK,
        )

    @action(detail=True, methods=["post"], url_path="check-out")
    def check_out(self, request, pk=None):
        """ثبت خروج."""
        from .serializers import AttendanceCheckOutSerializer

        record = self.get_object()
        serializer = AttendanceCheckOutSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        record.check_out = serializer.validated_data["check_out"]
        if record.check_in and record.check_out:
            delta = record.check_out - record.check_in
            record.effective_hours = round(delta.total_seconds() / 3600, 2)
        record.save()

        return Response(AttendanceRecordSerializer(record).data)


# ═══════════════════════════════════════════════════
# 5. Leave Management
# ═══════════════════════════════════════════════════

class LeavePolicyViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت سیاست‌های مرخصی."""

    queryset = LeavePolicyModel.objects.all()
    serializer_class = LeavePolicySerializer
    permission_classes = [CanManageLeave]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ["leave_type", "is_active", "accrual_method"]
    search_fields = ["name", "code"]
    ordering = ["name"]


class LeaveBalanceViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت مانده مرخصی."""

    queryset = LeaveBalanceModel.objects.all()
    serializer_class = LeaveBalanceSerializer
    permission_classes = [CanManageLeave]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ["employee", "leave_type", "year"]


class LeaveRequestViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """
    API مدیریت درخواست‌های مرخصی.

    list: لیست درخواست‌ها
    create: ایجاد درخواست مرخصی
    action: تأیید/رد/لغو درخواست
    pending: درخواست‌های در انتظار
    my_leaves: مرخصی‌های کاربر جاری
    """

    queryset = LeaveRequestModel.objects.all()
    permission_classes = [CanManageLeave]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["employee", "leave_type", "status"]
    ordering_fields = ["start_date", "created_at"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        if self.action == "create":
            return LeaveRequestCreateSerializer
        if self.action == "take_action":
            return LeaveActionSerializer
        return LeaveRequestSerializer

    def create(self, request, *args, **kwargs):
        """ایجاد درخواست مرخصی."""
        serializer = LeaveRequestCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data

        leave_request = LeaveRequestModel(
            id=uuid4(),
            employee_id=data["employee_id"],
            leave_type=data["leave_type"],
            start_date=data["start_date"],
            end_date=data["end_date"],
            is_half_day=data.get("is_half_day", False),
            half_day_period=data.get("half_day_period", ""),
            reason=data.get("reason", ""),
            substitute_id=data.get("substitute_id"),
            status=LeaveRequestModel.LeaveRequestStatus.PENDING,
            tenant=getattr(request, "tenant", None),
        )

        # محاسبه تعداد روزها
        delta = (data["end_date"] - data["start_date"]).days + 1
        if data.get("is_half_day"):
            leave_request.days_count = 0.5
        else:
            leave_request.days_count = delta

        leave_request.save()
        return Response(
            LeaveRequestSerializer(leave_request).data,
            status=status.HTTP_201_CREATED,
        )

    @action(detail=True, methods=["post"], url_path="action")
    def take_action(self, request, pk=None):
        """عملیات تأیید/رد/لغو مرخصی."""
        from django.utils import timezone

        leave = self.get_object()
        serializer = LeaveActionSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        action_val = serializer.validated_data["action"]

        if action_val == "approve":
            if leave.status != LeaveRequestModel.LeaveRequestStatus.PENDING:
                return Response(
                    {"detail": "فقط درخواست‌های در انتظار قابل تأیید هستند."},
                    status=status.HTTP_400_BAD_REQUEST,
                )
            leave.status = LeaveRequestModel.LeaveRequestStatus.APPROVED
            leave.approved_by = request.user.id
            leave.approved_at = timezone.now()

        elif action_val == "reject":
            if leave.status != LeaveRequestModel.LeaveRequestStatus.PENDING:
                return Response(
                    {"detail": "فقط درخواست‌های در انتظار قابل رد هستند."},
                    status=status.HTTP_400_BAD_REQUEST,
                )
            leave.status = LeaveRequestModel.LeaveRequestStatus.REJECTED
            leave.rejection_reason = serializer.validated_data.get("reason", "")

        elif action_val == "cancel":
            if leave.status not in (
                LeaveRequestModel.LeaveRequestStatus.DRAFT,
                LeaveRequestModel.LeaveRequestStatus.PENDING,
            ):
                return Response(
                    {"detail": "فقط درخواست‌های پیش‌نویس و در انتظار قابل لغو هستند."},
                    status=status.HTTP_400_BAD_REQUEST,
                )
            leave.status = LeaveRequestModel.LeaveRequestStatus.CANCELLED

        leave.save()
        return Response(LeaveRequestSerializer(leave).data)

    @action(detail=False, methods=["get"], url_path="pending")
    def pending(self, request):
        """درخواست‌های در انتظار تأیید."""
        qs = self.get_queryset().filter(
            status=LeaveRequestModel.LeaveRequestStatus.PENDING
        ).order_by("created_at")
        serializer = LeaveRequestSerializer(qs, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=["get"], url_path="my-leaves")
    def my_leaves(self, request):
        """مرخصی‌های کاربر جاری."""
        employee = EmployeeModel.objects.filter(
            user_id=request.user.id
        ).first()
        if not employee:
            return Response(
                {"detail": "اطلاعات کارمندی یافت نشد."},
                status=status.HTTP_404_NOT_FOUND,
            )
        qs = self.get_queryset().filter(
            employee=employee
        ).order_by("-created_at")
        serializer = LeaveRequestSerializer(qs, many=True)
        return Response(serializer.data)


# ═══════════════════════════════════════════════════
# 6. Payroll Foundation
# ═══════════════════════════════════════════════════

class PayGradeViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت رتبه‌های حقوقی."""

    queryset = PayGradeModel.objects.all()
    serializer_class = PayGradeSerializer
    permission_classes = [CanManagePayroll]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ["grade_type", "is_active"]
    search_fields = ["name", "code"]
    ordering = ["code"]


class CompensationRecordViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت سوابق حقوقی."""

    queryset = CompensationRecordModel.objects.all()
    serializer_class = CompensationRecordSerializer
    permission_classes = [CanManagePayroll]
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ["employee", "is_current"]
    ordering = ["-effective_date"]

    @action(detail=False, methods=["post"], url_path="set-salary")
    def set_salary(self, request):
        """تنظیم حقوق کارمند (ایجاد رکورد جدید و بسته شدن قبلی)."""
        serializer = SetSalarySerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data

        # بستن رکورد فعلی
        CompensationRecordModel.objects.filter(
            employee_id=data["employee_id"],
            is_current=True,
        ).update(
            is_current=False,
            end_date=data["effective_date"],
        )

        # ایجاد رکورد جدید
        record = CompensationRecordModel(
            id=uuid4(),
            employee_id=data["employee_id"],
            base_salary=data["base_salary"],
            housing_allowance=data.get("housing_allowance", 0),
            transportation_allowance=data.get("transportation_allowance", 0),
            food_allowance=data.get("food_allowance", 0),
            family_allowance=data.get("family_allowance", 0),
            pay_grade_id=data.get("pay_grade_id"),
            effective_date=data["effective_date"],
            is_current=True,
            change_reason=data.get("change_reason", ""),
            tenant=getattr(request, "tenant", None),
        )
        record.save()

        return Response(
            CompensationRecordSerializer(record).data,
            status=status.HTTP_201_CREATED,
        )


class BankAccountViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت حساب‌های بانکی."""

    queryset = BankAccountModel.objects.all()
    serializer_class = BankAccountSerializer
    permission_classes = [CanManagePayroll]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ["employee", "is_primary", "is_active"]

    def perform_create(self, serializer):
        instance = serializer.save(
            id=uuid4(),
            tenant=getattr(self.request, "tenant", None)
        )
        # اگر اصلی است، بقیه رو غیراصلی کن
        if instance.is_primary:
            BankAccountModel.objects.filter(
                employee=instance.employee,
                is_primary=True,
            ).exclude(id=instance.id).update(is_primary=False)


class CostAllocationViewSet(TenantQuerySetMixin, viewsets.ModelViewSet):
    """API مدیریت تخصیص هزینه."""

    queryset = CostAllocationModel.objects.all()
    serializer_class = CostAllocationSerializer
    permission_classes = [CanManagePayroll]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ["employee", "allocation_type", "is_active"]
