"""Unit tests for component policies — Phase 11.2."""
from __future__ import annotations

import pytest

from app.models.types import ComponentStatus, ComponentVersionStatus
from app.policies.components import (
    ComponentLifecyclePolicy,
    ComponentVersionPolicy,
    PagePlacementPolicy,
)
from shared.exceptions import AppError


def test_component_lifecycle_transitions():
    policy = ComponentLifecyclePolicy()
    assert (
        policy.assert_status_change(
            current=ComponentStatus.DRAFT, target=ComponentStatus.ACTIVE
        )
        == ComponentStatus.ACTIVE
    )
    with pytest.raises(AppError) as exc:
        policy.assert_status_change(
            current=ComponentStatus.ARCHIVED, target=ComponentStatus.ACTIVE
        )
    assert exc.value.error_code == "invalid_component_status_transition"


def test_version_immutability_policy():
    policy = ComponentVersionPolicy()

    class _V:
        status = ComponentVersionStatus.PUBLISHED
        is_immutable = True

    with pytest.raises(AppError) as exc:
        policy.assert_can_update(_V())
    assert exc.value.error_code == "component_version_immutable"

    assert (
        policy.assert_publish(current=ComponentVersionStatus.DRAFT)
        == ComponentVersionStatus.PUBLISHED
    )


def test_placement_requires_published_version():
    policy = PagePlacementPolicy()

    class _Draft:
        status = ComponentVersionStatus.DRAFT
        is_deleted = False

    class _Comp:
        status = ComponentStatus.ACTIVE
        is_deleted = False

    with pytest.raises(AppError) as exc:
        policy.assert_version_placeable(_Draft())
    assert exc.value.error_code == "component_version_not_published"
    policy.assert_component_placeable(_Comp())
