"""Tests for organization validation."""

from prisme.spec import AuthConfig, FieldSpec, FieldType, ModelSpec, StackSpec
from prisme.spec.auth import OrganizationConfig, OrgRole
from prisme.spec.project import ProjectSpec
from prisme.spec.validators import validate_org_config, validate_stack


def _make_user_model() -> ModelSpec:
    """Create a valid User model for testing."""
    return ModelSpec(
        name="User",
        fields=[
            FieldSpec(name="email", type=FieldType.STRING, required=True, unique=True),
            FieldSpec(name="password_hash", type=FieldType.STRING, required=True, hidden=True),
            FieldSpec(name="is_active", type=FieldType.BOOLEAN, default=True),
            FieldSpec(name="roles", type=FieldType.JSON, default=["user"]),
        ],
    )


class TestValidateOrgConfig:
    """Tests for validate_org_config."""

    def test_no_errors_when_org_disabled(self):
        stack = StackSpec(name="test", models=[_make_user_model()])
        project = ProjectSpec(
            name="test",
            auth=AuthConfig(
                enabled=True,
                secret_key="${JWT_SECRET}",
                organization=OrganizationConfig(enabled=False),
            ),
        )
        errors = validate_org_config(stack, project)
        assert errors == []

    def test_no_errors_when_project_none(self):
        stack = StackSpec(name="test", models=[_make_user_model()])
        errors = validate_org_config(stack, None)
        assert errors == []

    def test_error_when_auth_disabled_but_org_enabled(self):
        stack = StackSpec(name="test", models=[_make_user_model()])
        project = ProjectSpec(
            name="test",
            auth=AuthConfig(
                enabled=False,
                organization=OrganizationConfig(enabled=True),
            ),
        )
        errors = validate_org_config(stack, project)
        assert len(errors) == 1
        assert "authentication" in errors[0].lower()

    def test_error_on_duplicate_role_names(self):
        stack = StackSpec(name="test", models=[_make_user_model()])
        project = ProjectSpec(
            name="test",
            auth=AuthConfig(
                enabled=True,
                secret_key="${JWT_SECRET}",
                organization=OrganizationConfig(
                    enabled=True,
                    roles=[
                        OrgRole(name="admin", permissions=["*"]),
                        OrgRole(name="admin", permissions=["members.manage"]),
                    ],
                    default_role="admin",
                ),
            ),
        )
        errors = validate_org_config(stack, project)
        assert any("duplicate" in e.lower() for e in errors)

    def test_error_when_default_role_not_in_roles(self):
        stack = StackSpec(name="test", models=[_make_user_model()])
        project = ProjectSpec(
            name="test",
            auth=AuthConfig(
                enabled=True,
                secret_key="${JWT_SECRET}",
                organization=OrganizationConfig(
                    enabled=True,
                    roles=[
                        OrgRole(name="owner", permissions=["*"]),
                        OrgRole(name="viewer", permissions=[]),
                    ],
                    default_role="member",  # not in roles list
                ),
            ),
        )
        errors = validate_org_config(stack, project)
        assert any("member" in e for e in errors)

    def test_no_errors_with_valid_config(self):
        stack = StackSpec(name="test", models=[_make_user_model()])
        project = ProjectSpec(
            name="test",
            auth=AuthConfig(
                enabled=True,
                secret_key="${JWT_SECRET}",
                organization=OrganizationConfig(
                    enabled=True,
                    roles=[
                        OrgRole(name="owner", permissions=["*"]),
                        OrgRole(name="member", permissions=["content.view"]),
                    ],
                    default_role="member",
                ),
            ),
        )
        errors = validate_org_config(stack, project)
        assert errors == []

    def test_validate_stack_includes_org_validation(self):
        stack = StackSpec(name="test", models=[_make_user_model()])
        project = ProjectSpec(
            name="test",
            auth=AuthConfig(
                enabled=False,
                organization=OrganizationConfig(enabled=True),
            ),
        )
        errors = validate_stack(stack, project)
        assert any("authentication" in e.lower() for e in errors)
