"""Tests for organization configuration specification models."""

import pytest
from pydantic import ValidationError

from prisme.spec.auth import AuthConfig, OrganizationConfig, OrgRole
from prisme.spec.project import ProjectSpec


class TestOrgRole:
    """Tests for OrgRole model."""

    def test_basic_role_creation(self):
        role = OrgRole(name="admin", permissions=["members.manage", "settings.edit"])
        assert role.name == "admin"
        assert role.permissions == ["members.manage", "settings.edit"]
        assert role.description is None

    def test_role_with_description(self):
        role = OrgRole(
            name="owner",
            permissions=["*"],
            description="Full organization access",
        )
        assert role.name == "owner"
        assert role.permissions == ["*"]
        assert role.description == "Full organization access"

    def test_role_with_empty_permissions(self):
        role = OrgRole(name="viewer")
        assert role.permissions == []

    def test_role_forbids_extra_fields(self):
        with pytest.raises(ValidationError):
            OrgRole(name="test", invalid_field="value")


class TestOrganizationConfig:
    """Tests for OrganizationConfig model."""

    def test_defaults(self):
        config = OrganizationConfig()
        assert config.enabled is False
        assert config.default_role == "member"
        assert config.max_members_per_org == 0
        assert config.max_orgs_per_user == 0
        assert config.allow_multiple_orgs is True
        assert config.require_org_context is False
        assert config.invitation_expiry_hours == 72
        assert config.slug_field == "slug"

    def test_default_roles(self):
        config = OrganizationConfig()
        role_names = [r.name for r in config.roles]
        assert "owner" in role_names
        assert "admin" in role_names
        assert "member" in role_names
        assert "viewer" in role_names

    def test_owner_has_wildcard_permission(self):
        config = OrganizationConfig()
        owner = next(r for r in config.roles if r.name == "owner")
        assert "*" in owner.permissions

    def test_enabled_config(self):
        config = OrganizationConfig(enabled=True)
        assert config.enabled is True

    def test_custom_roles(self):
        config = OrganizationConfig(
            enabled=True,
            roles=[
                OrgRole(name="admin", permissions=["*"]),
                OrgRole(name="editor", permissions=["content.edit"]),
            ],
            default_role="editor",
        )
        assert len(config.roles) == 2
        assert config.default_role == "editor"

    def test_member_limits(self):
        config = OrganizationConfig(
            max_members_per_org=50,
            max_orgs_per_user=10,
        )
        assert config.max_members_per_org == 50
        assert config.max_orgs_per_user == 10

    def test_negative_member_limit_rejected(self):
        with pytest.raises(ValidationError):
            OrganizationConfig(max_members_per_org=-1)

    def test_single_org_mode(self):
        config = OrganizationConfig(
            allow_multiple_orgs=False,
            max_orgs_per_user=1,
        )
        assert config.allow_multiple_orgs is False
        assert config.max_orgs_per_user == 1

    def test_require_org_context(self):
        config = OrganizationConfig(require_org_context=True)
        assert config.require_org_context is True

    def test_custom_invitation_expiry(self):
        config = OrganizationConfig(invitation_expiry_hours=24)
        assert config.invitation_expiry_hours == 24

    def test_zero_invitation_expiry_rejected(self):
        with pytest.raises(ValidationError):
            OrganizationConfig(invitation_expiry_hours=0)

    def test_forbids_extra_fields(self):
        with pytest.raises(ValidationError):
            OrganizationConfig(invalid_field="value")


class TestAuthConfigWithOrganization:
    """Tests for AuthConfig integration with OrganizationConfig."""

    def test_default_org_disabled(self):
        auth = AuthConfig()
        assert auth.organization.enabled is False

    def test_org_enabled_in_auth(self):
        auth = AuthConfig(
            enabled=True,
            secret_key="${JWT_SECRET}",
            organization=OrganizationConfig(enabled=True),
        )
        assert auth.organization.enabled is True
        assert len(auth.organization.roles) == 4  # default roles

    def test_org_config_in_project_spec(self):
        project = ProjectSpec(
            name="test-project",
            auth=AuthConfig(
                enabled=True,
                secret_key="${JWT_SECRET}",
                organization=OrganizationConfig(
                    enabled=True,
                    default_role="member",
                ),
            ),
        )
        assert project.auth.organization.enabled is True
        assert project.auth.organization.default_role == "member"
