"""Leave settings: configured types drive what a request may use."""
import pytest
from django.contrib.auth import get_user_model

from apps.companies.models import Organization, OrganizationMembership
from apps.hr.models import LeaveSettings, LeaveRequest, Employee

User = get_user_model()


@pytest.fixture
def org_user(db):
    from apps.hr.signals import ensure_employee_stub
    org = Organization.objects.create(name="Leave Org")
    user = User.objects.create_user(email="leave@test.local", password="pw12345!")
    OrganizationMembership.objects.create(organization=org, user=user)
    ensure_employee_stub(user)
    return org, user


@pytest.mark.django_db
class TestLeaveSettings:
    def test_defaults_include_every_requested_type(self, org_user):
        org, _ = org_user
        keys = LeaveSettings.type_keys(org)
        for expected in [
            "annual", "sick", "unpaid", "marriage",
            "bereavement", "compassionate", "emergency",
        ]:
            assert expected in keys

    def test_legacy_types_survive(self, org_user):
        """Existing LeaveRequest rows use these; dropping them orphans the label."""
        org, _ = org_user
        keys = LeaveSettings.type_keys(org)
        assert "maternity" in keys and "paternity" in keys

    def test_solo_per_organization(self, db):
        a = Organization.objects.create(name="A")
        b = Organization.objects.create(name="B")
        sa = LeaveSettings.get_solo(a)
        sa.settings = {"types": [{"key": "custom", "label": "Custom", "enabled": True}], "general": {}}
        sa.save()
        assert LeaveSettings.type_keys(a) == ["custom"]
        assert "annual" in LeaveSettings.type_keys(b)

    def test_disabled_type_is_not_requestable(self, org_user):
        org, _ = org_user
        s = LeaveSettings.get_solo(org)
        types = s.settings["types"]
        for t in types:
            if t["key"] == "marriage":
                t["enabled"] = False
        s.settings = {"types": types, "general": s.settings["general"]}
        s.save()
        assert "marriage" not in LeaveSettings.type_keys(org)

    def test_label_resolves_from_config(self, org_user):
        org, user = org_user
        emp = Employee.objects.get(user=user)
        req = LeaveRequest.objects.create(
            employee=emp, leave_type="bereavement",
            start_date="2026-09-01", end_date="2026-09-02",
        )
        assert req.leave_type_label() == "Bereavement Leave"

    def test_unknown_key_falls_back_to_titleized_key(self, org_user):
        """A row whose type was deleted from settings must still render."""
        org, user = org_user
        emp = Employee.objects.get(user=user)
        req = LeaveRequest.objects.create(
            employee=emp, leave_type="study_leave",
            start_date="2026-09-01", end_date="2026-09-02",
        )
        assert req.leave_type_label() == "Study Leave"


@pytest.mark.django_db
class TestLeaveSettingsAPI:
    def test_get_returns_defaults(self, org_user, client):
        org, user = org_user
        client.force_login(user)
        res = client.get("/api/leave-settings/")
        assert res.status_code == 200
        body = res.json()
        assert len(body["types"]) == 9
        assert body["general"]["year_start_month"] == 1

    def test_put_replaces_types_wholesale(self, org_user, client):
        """A deleted type must not be resurrected by a merge."""
        org, user = org_user
        client.force_login(user)
        res = client.put(
            "/api/leave-settings/",
            data={"types": [{"key": "annual", "label": "Cuti Tahunan", "enabled": True}],
                  "general": {"year_start_month": 7}},
            content_type="application/json",
        )
        assert res.status_code == 200, res.content
        body = res.json()
        assert [t["key"] for t in body["types"]] == ["annual"]
        assert body["types"][0]["label"] == "Cuti Tahunan"
        assert body["general"]["year_start_month"] == 7
        # Unsent general keys keep their defaults.
        assert body["general"]["allow_negative_balance"] is False

    def test_duplicate_keys_rejected(self, org_user, client):
        org, user = org_user
        client.force_login(user)
        res = client.put(
            "/api/leave-settings/",
            data={"types": [{"key": "annual", "label": "A"}, {"key": "annual", "label": "B"}]},
            content_type="application/json",
        )
        assert res.status_code == 400
        assert "Duplicate" in str(res.content)

    def test_keyless_type_rejected(self, org_user, client):
        org, user = org_user
        client.force_login(user)
        res = client.put(
            "/api/leave-settings/",
            data={"types": [{"label": "No key"}]},
            content_type="application/json",
        )
        assert res.status_code == 400

    def test_anonymous_refused(self, org_user, client):
        res = client.get("/api/leave-settings/")
        assert res.status_code in (401, 403)
