import pytest
from django.contrib.auth import get_user_model
from datetime import date, timedelta
from apps.hr.models import Employee, Attendance, Payroll, Recruitment, Onboarding, Contract, Communication, Survey


@pytest.fixture
def user(db):
    User = get_user_model()
    return User.objects.create_user(email="hr@example.com", password="pass123")


@pytest.fixture
def employee(user):
    # The hr post_save signal auto-creates an Employee stub per user — reuse it
    # (a second Employee for the same user violates the OneToOne constraint).
    emp = Employee.objects.get(user=user)
    emp.employee_id = "EMP001"
    emp.position = "Developer"
    emp.department = "IT"
    emp.hire_date = date.today()
    emp.save()
    return emp


@pytest.mark.django_db
class TestEmployeeModel:
    def test_employee_auto_created_and_updatable(self, user):
        # Signal creates the stub on user creation.
        emp = Employee.objects.get(user=user)
        emp.employee_id = "EMP002"
        emp.position = "Designer"
        emp.department = "Design"
        emp.save()
        emp.refresh_from_db()
        assert emp.employee_id == "EMP002"
        assert emp.position == "Designer"

    def test_employee_unique_id(self, employee):
        User = get_user_model()
        other = User.objects.create_user(email="hr2@example.com", password="pass123")
        dup = Employee.objects.get(user=other)
        dup.employee_id = "EMP001"
        with pytest.raises(Exception):
            dup.save()

    def test_employee_str(self, employee):
        assert "EMP001" in str(employee)


@pytest.mark.django_db
class TestAttendanceModel:
    def test_create_attendance(self, employee):
        att = Attendance.objects.create(
            employee=employee,
            type="check_in",
            date=date.today()
        )
        assert att.type == "check_in"

    def test_attendance_unique_constraint(self, employee):
        Attendance.objects.create(
            employee=employee,
            type="check_in",
            date=date.today()
        )
        with pytest.raises(Exception):
            Attendance.objects.create(
                employee=employee,
                type="check_in",
                date=date.today()
            )


@pytest.mark.django_db
class TestPayrollModel:
    def test_create_payroll(self, employee):
        payroll = Payroll.objects.create(
            employee=employee,
            period_start=date.today(),
            period_end=date.today() + timedelta(days=30),
            base_salary=5000000,
            net_salary=4500000
        )
        assert payroll.base_salary == 5000000

    def test_payroll_status_defaults(self, employee):
        payroll = Payroll.objects.create(
            employee=employee,
            period_start=date.today(),
            period_end=date.today() + timedelta(days=30),
            base_salary=5000000,
            net_salary=4500000
        )
        assert payroll.status == "draft"


@pytest.mark.django_db
class TestRecruitmentModel:
    def test_create_recruitment(self, user):
        rec = Recruitment.objects.create(
            position="Senior Developer",
            department="IT",
            description="Job description",
            requirements="Requirements",
            hiring_manager=user
        )
        assert rec.position == "Senior Developer"
        assert rec.status == "open"


@pytest.mark.django_db
class TestContractModel:
    def test_create_contract(self, employee):
        contract = Contract.objects.create(
            employee=employee,
            contract_type="full_time",
            start_date=date.today(),
            end_date=date.today() + timedelta(days=365)
        )
        assert contract.contract_type == "full_time"
        assert contract.status == "active"


@pytest.mark.django_db
class TestCommunicationModel:
    def test_create_communication(self, user):
        comm = Communication.objects.create(
            title="Announcement",
            content="Important announcement",
            communication_type="announcement",
            author=user
        )
        assert comm.title == "Announcement"


@pytest.mark.django_db
class TestSurveyModel:
    def test_create_survey(self, user):
        survey = Survey.objects.create(
            title="Employee Survey",
            description="Annual survey",
            questions=[{"question": "How satisfied?"}],
            created_by=user
        )
        assert survey.status == "draft"
        assert len(survey.questions) == 1