"""
HRM Module — Pytest Fixtures.

فیکسچرهای مشترک برای تست‌های ماژول منابع انسانی.
"""
import sys
from pathlib import Path
import uuid
from datetime import date, time, datetime, timedelta
from decimal import Decimal

# Ensure project root is on sys.path so "modules.hrm.backend" is importable
PROJECT_ROOT = str(Path(__file__).resolve().parent.parent.parent.parent)
if PROJECT_ROOT not in sys.path:
    sys.path.insert(0, PROJECT_ROOT)

import pytest

from apps.core.tenant.models import Tenant, Domain
from apps.core.tenant.middleware import _thread_locals
from apps.core.auth.models import User

# ─── Force import of HRM views BEFORE any test runs ─────────
# This ensures the ViewSet class-level `queryset` attributes are
# evaluated while get_current_tenant() returns None (no tenant),
# preventing a stale tenant_id from being baked into the queryset's
# WHERE clause via TenantAwareManager.
import modules.hrm.backend.api.v1.views  # noqa: F401

from modules.hrm.backend.infrastructure.persistence.models import (
    LegalEntityModel,
    LocationModel,
    EmployeeModel,
    EmploymentRecordModel,
    EmployeeDocumentModel,
    JobFamilyModel,
    JobTitleModel,
    PositionModel,
    ReportingLineModel,
)
from modules.hrm.backend.infrastructure.persistence.models_extended import (
    WorkScheduleModel,
    ShiftPatternModel,
    TimesheetModel,
    AttendanceRecordModel,
    LeavePolicyModel,
    LeaveBalanceModel,
    LeaveRequestModel,
    PayGradeModel,
    CompensationRecordModel,
    BankAccountModel,
    CostAllocationModel,
)


# ─── Tenant & Auth ──────────────────────────────────────────

@pytest.fixture(autouse=True)
def _patch_tenant_middleware(tenant, monkeypatch):
    """
    Ensure get_current_tenant() returns the fixture tenant for ORM queries.
    The TenantMainMiddleware is already replaced by TestTenantMiddleware
    in test settings, which sets request.tenant from the DB transaction.
    """
    from django.db import connection
    from apps.core.tenant import middleware as tenant_mw

    # Make get_current_tenant() return our fixture tenant
    monkeypatch.setattr(tenant_mw, "get_current_tenant", lambda: tenant)

    # Ensure connection.tenant points to our tenant
    if hasattr(connection, "set_tenant"):
        connection.set_tenant(tenant)

    yield

    # Cleanup thread-locals
    if hasattr(_thread_locals, "tenant"):
        del _thread_locals.tenant
    if hasattr(_thread_locals, "request"):
        del _thread_locals.request


@pytest.fixture(scope="function")
def tenant(db):
    """Create a test tenant with domain."""
    t = Tenant.objects.create(
        name="Test Tenant",
        slug="test-tenant",
        schema_name="public",
    )
    Domain.objects.create(
        domain="localhost",
        tenant=t,
        is_primary=True,
    )
    return t


@pytest.fixture
def user(tenant):
    """Create a regular user."""
    return User.objects.create_user(
        email="hrm-user@example.com",
        password="testpass123",
        first_name="HR",
        last_name="User",
        tenant=tenant,
    )


@pytest.fixture
def admin_user(tenant):
    """Create a superuser."""
    return User.objects.create_superuser(
        email="hrm-admin@example.com",
        password="adminpass123",
        first_name="HR",
        last_name="Admin",
        tenant=tenant,
    )


@pytest.fixture
def api_client():
    """DRF APIClient that sends HTTP_HOST for tenant middleware."""
    from rest_framework.test import APIClient

    class TenantAPIClient(APIClient):
        def request(self, **kwargs):
            if "HTTP_HOST" not in kwargs:
                kwargs["HTTP_HOST"] = "localhost"
            return super().request(**kwargs)

    return TenantAPIClient()


@pytest.fixture
def authenticated_client(api_client, user):
    """Authenticated API client."""
    from rest_framework_simplejwt.tokens import RefreshToken
    refresh = RefreshToken.for_user(user)
    api_client.credentials(HTTP_AUTHORIZATION=f"Bearer {refresh.access_token}")
    return api_client


@pytest.fixture
def admin_client(api_client, admin_user):
    """Authenticated admin API client."""
    from rest_framework_simplejwt.tokens import RefreshToken
    refresh = RefreshToken.for_user(admin_user)
    api_client.credentials(HTTP_AUTHORIZATION=f"Bearer {refresh.access_token}")
    return api_client


# ─── Organization ────────────────────────────────────────────

@pytest.fixture
def legal_entity(tenant):
    return LegalEntityModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="شرکت آزمایشی",
        name_en="Test Company",
        registration_number="12345",
        national_id="10101010101",
        entity_type=LegalEntityModel.EntityType.COMPANY,
        is_active=True,
    )


@pytest.fixture
def location(tenant, legal_entity):
    return LocationModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="دفتر مرکزی",
        code="HQ-01",
        location_type=LocationModel.LocationType.HEADQUARTERS,
        legal_entity=legal_entity,
        city="تهران",
        province="تهران",
        is_active=True,
    )


# ─── Employee ────────────────────────────────────────────────

@pytest.fixture
def employee(tenant, legal_entity, location, user):
    return EmployeeModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        employee_code="EMP-001",
        first_name="علی",
        last_name="محمدی",
        national_code="0012345678",
        gender=EmployeeModel.GenderChoices.MALE,
        hire_date=date(2023, 1, 15),
        employment_status=EmployeeModel.EmploymentStatus.ACTIVE,
        employment_type=EmployeeModel.EmploymentType.FULL_TIME,
        legal_entity=legal_entity,
        location=location,
        user=user,
        is_active=True,
    )


@pytest.fixture
def employee_2(tenant, legal_entity):
    return EmployeeModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        employee_code="EMP-002",
        first_name="سارا",
        last_name="رضایی",
        national_code="0098765432",
        gender=EmployeeModel.GenderChoices.FEMALE,
        hire_date=date(2023, 6, 1),
        employment_status=EmployeeModel.EmploymentStatus.ACTIVE,
        employment_type=EmployeeModel.EmploymentType.FULL_TIME,
        legal_entity=legal_entity,
        is_active=True,
    )


# ─── Job / Position ─────────────────────────────────────────

@pytest.fixture
def job_family(tenant):
    return JobFamilyModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="فناوری اطلاعات",
        code="IT",
        is_active=True,
    )


@pytest.fixture
def job_title(tenant, job_family):
    return JobTitleModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        title="مهندس نرم‌افزار",
        code="SE-01",
        job_family=job_family,
        level=JobTitleModel.JobLevel.SENIOR,
        is_active=True,
    )


@pytest.fixture
def position(tenant, job_title, legal_entity, location, employee):
    return PositionModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        title="مهندس نرم‌افزار ارشد",
        code="POS-001",
        job_title=job_title,
        legal_entity=legal_entity,
        location=location,
        incumbent=employee,
        status=PositionModel.PositionStatus.ACTIVE,
    )


# ─── Time & Attendance ──────────────────────────────────────

@pytest.fixture
def work_schedule(tenant):
    return WorkScheduleModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="استاندارد صبح",
        code="WS-STD",
        schedule_type=WorkScheduleModel.ScheduleType.STANDARD,
        start_time=time(8, 0),
        end_time=time(17, 0),
        working_days=[0, 1, 2, 3, 4],  # شنبه تا چهارشنبه
        daily_hours=Decimal("8.00"),
        weekly_hours=Decimal("44.00"),
        is_active=True,
    )


@pytest.fixture
def shift_pattern(tenant):
    return ShiftPatternModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="شیفت گردشی",
        code="SP-ROT",
        cycle_days=14,
        shifts=[{"day": 1, "schedule": "WS-STD"}],
        is_active=True,
    )


@pytest.fixture
def leave_policy(tenant):
    return LeavePolicyModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="مرخصی استحقاقی",
        code="LP-ANN",
        leave_type=LeavePolicyModel.LeaveType.ANNUAL,
        annual_entitlement_days=Decimal("26.00"),
        is_active=True,
    )


@pytest.fixture
def pay_grade(tenant):
    return PayGradeModel.objects.create(
        id=uuid.uuid4(),
        tenant=tenant,
        name="رتبه ۵",
        code="PG-05",
        grade_type=PayGradeModel.GradeType.MONTHLY,
        min_amount=Decimal("50000000"),
        mid_amount=Decimal("70000000"),
        max_amount=Decimal("90000000"),
        currency="IRR",
        is_active=True,
    )
