"""
HRM Module — API Integration Tests.

تست‌های API (CRUD) برای اندپوینت‌های ماژول منابع انسانی.
"""
import uuid
from unittest.mock import patch

import pytest
from rest_framework.test import APIClient

pytestmark = pytest.mark.django_db


BASE = "/api/v1/hrm"


@pytest.fixture
def tenant_api_client(admin_user, tenant):
    """
    APIClient that sets both force_authenticate AND HTTP_HOST
    so that TenantMainMiddleware can resolve the tenant.
    """
    client = APIClient()
    client.force_authenticate(user=admin_user)
    client.defaults["HTTP_HOST"] = "localhost"
    client.defaults["SERVER_NAME"] = "localhost"
    return client


# ═══════════════════════════════════════════════
# 1) Legal Entities
# ═══════════════════════════════════════════════

class TestLegalEntityAPI:
    endpoint = f"{BASE}/legal-entities/"

    def test_list(self, tenant_api_client, legal_entity):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client, tenant):
        data = {
            "name": "شرکت جدید",
            "registration_number": "99999",
            "national_id": "30303030303",
            "entity_type": "COMPANY",
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201
        assert res.data["name"] == "شرکت جدید"

    def test_retrieve(self, tenant_api_client, legal_entity):
        res = tenant_api_client.get(f"{self.endpoint}{legal_entity.id}/")
        assert res.status_code == 200
        assert res.data["name"] == "شرکت آزمایشی"

    def test_update(self, tenant_api_client, legal_entity):
        res = tenant_api_client.patch(
            f"{self.endpoint}{legal_entity.id}/",
            {"name": "شرکت بروز‌شده"},
            format="json",
        )
        assert res.status_code == 200
        assert res.data["name"] == "شرکت بروز‌شده"

    def test_delete(self, tenant_api_client, legal_entity):
        res = tenant_api_client.delete(f"{self.endpoint}{legal_entity.id}/")
        assert res.status_code == 204

    def test_unauthenticated(self, tenant):
        client = APIClient()
        client.defaults["HTTP_HOST"] = "localhost"
        res = client.get(self.endpoint)
        assert res.status_code in (401, 403)


# ═══════════════════════════════════════════════
# 2) Locations
# ═══════════════════════════════════════════════

class TestLocationAPI:
    endpoint = f"{BASE}/locations/"

    def test_list(self, tenant_api_client, location):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client, legal_entity):
        data = {
            "name": "دفتر جدید",
            "code": "OFF-02",
            "location_type": "OFFICE",
            "legal_entity": str(legal_entity.id),
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201

    def test_retrieve(self, tenant_api_client, location):
        res = tenant_api_client.get(f"{self.endpoint}{location.id}/")
        assert res.status_code == 200


# ═══════════════════════════════════════════════
# 3) Employees
# ═══════════════════════════════════════════════

class TestEmployeeAPI:
    endpoint = f"{BASE}/employees/"

    def test_list(self, tenant_api_client, employee):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client, legal_entity):
        data = {
            "employee_code": "EMP-100",
            "first_name": "مریم",
            "last_name": "احمدی",
            "national_code": "1234567890",
            "gender": "FEMALE",
            "hire_date": "2024-01-01",
            "employment_type": "FULL_TIME",
            "legal_entity_id": str(legal_entity.id),
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201

    def test_retrieve(self, tenant_api_client, employee):
        res = tenant_api_client.get(f"{self.endpoint}{employee.id}/")
        assert res.status_code == 200
        assert res.data["employee_code"] == "EMP-001"

    def test_update(self, tenant_api_client, employee):
        res = tenant_api_client.patch(
            f"{self.endpoint}{employee.id}/",
            {"first_name": "حسین"},
            format="json",
        )
        assert res.status_code == 200


# ═══════════════════════════════════════════════
# 4) Job Families
# ═══════════════════════════════════════════════

class TestJobFamilyAPI:
    endpoint = f"{BASE}/job-families/"

    def test_list(self, tenant_api_client, job_family):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client):
        data = {"name": "مالی", "code": "FIN"}
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201


# ═══════════════════════════════════════════════
# 5) Job Titles
# ═══════════════════════════════════════════════

class TestJobTitleAPI:
    endpoint = f"{BASE}/job-titles/"

    def test_list(self, tenant_api_client, job_title):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client, job_family):
        data = {
            "title": "تحلیلگر سیستم",
            "code": "SA-01",
            "job_family": str(job_family.id),
            "level": "MID",
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201


# ═══════════════════════════════════════════════
# 6) Positions
# ═══════════════════════════════════════════════

class TestPositionAPI:
    endpoint = f"{BASE}/positions/"

    def test_list(self, tenant_api_client, position):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client, job_title, legal_entity):
        data = {
            "title": "پست جدید",
            "code": "POS-NEW",
            "job_title": str(job_title.id),
            "legal_entity": str(legal_entity.id),
            "status": "ACTIVE",
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201


# ═══════════════════════════════════════════════
# 7) Work Schedules
# ═══════════════════════════════════════════════

class TestWorkScheduleAPI:
    endpoint = f"{BASE}/work-schedules/"

    def test_list(self, tenant_api_client, work_schedule):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client):
        data = {
            "name": "شیفت عصر",
            "code": "WS-EVE",
            "schedule_type": "STANDARD",
            "start_time": "14:00:00",
            "end_time": "22:00:00",
            "working_days": [0, 1, 2, 3, 4],
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201


# ═══════════════════════════════════════════════
# 8) Shift Patterns
# ═══════════════════════════════════════════════

class TestShiftPatternAPI:
    endpoint = f"{BASE}/shift-patterns/"

    def test_list(self, tenant_api_client, shift_pattern):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client):
        data = {
            "name": "الگوی جدید",
            "code": "SP-NEW",
            "cycle_days": 7,
            "shifts": [],
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201


# ═══════════════════════════════════════════════
# 9) Leave Policies
# ═══════════════════════════════════════════════

class TestLeavePolicyAPI:
    endpoint = f"{BASE}/leave-policies/"

    def test_list(self, tenant_api_client, leave_policy):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client):
        data = {
            "name": "مرخصی استعلاجی",
            "code": "LP-SICK",
            "leave_type": "SICK",
            "annual_entitlement_days": "12.00",
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201


# ═══════════════════════════════════════════════
# 10) Pay Grades
# ═══════════════════════════════════════════════

class TestPayGradeAPI:
    endpoint = f"{BASE}/pay-grades/"

    def test_list(self, tenant_api_client, pay_grade):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client):
        data = {
            "name": "رتبه ۶",
            "code": "PG-06",
            "grade_type": "MONTHLY",
            "min_amount": "55000000",
            "mid_amount": "75000000",
            "max_amount": "95000000",
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201


# ═══════════════════════════════════════════════
# 11) Bank Accounts
# ═══════════════════════════════════════════════

class TestBankAccountAPI:
    endpoint = f"{BASE}/bank-accounts/"

    def test_list(self, tenant_api_client, employee):
        res = tenant_api_client.get(self.endpoint)
        assert res.status_code == 200

    def test_create(self, tenant_api_client, employee):
        data = {
            "employee": str(employee.id),
            "bank_name": "بانک صادرات",
            "account_number": "9876543210",
            "is_primary": True,
        }
        res = tenant_api_client.post(self.endpoint, data, format="json")
        assert res.status_code == 201
