"""Theme & layout domain policies — Phase 11.3 (versioned)."""
from __future__ import annotations

from typing import Any

from app.models.types import (
    LayoutStatus,
    LayoutVersionStatus,
    ThemeStatus,
    ThemeVersionStatus,
)
from app.validators.themes import (
    ensure_assignable_layout,
    ensure_assignable_layout_version,
    ensure_assignable_theme,
    ensure_assignable_theme_version,
    ensure_layout_status_transition,
    ensure_layout_version_mutable,
    ensure_layout_version_status_transition,
    ensure_theme_status_transition,
    ensure_theme_version_mutable,
    ensure_theme_version_status_transition,
)


class ThemeLifecyclePolicy:
    def assert_status_change(
        self, *, current: ThemeStatus, target: ThemeStatus
    ) -> ThemeStatus:
        ensure_theme_status_transition(current, target)
        return target


class ThemeVersionPolicy:
    def assert_can_update(self, version: Any) -> None:
        ensure_theme_version_mutable(version)

    def assert_publish(self, *, current: ThemeVersionStatus) -> None:
        ensure_theme_version_status_transition(current, ThemeVersionStatus.PUBLISHED)

    def assert_retire(self, *, current: ThemeVersionStatus) -> None:
        ensure_theme_version_status_transition(current, ThemeVersionStatus.RETIRED)


class LayoutLifecyclePolicy:
    def assert_status_change(
        self, *, current: LayoutStatus, target: LayoutStatus
    ) -> LayoutStatus:
        ensure_layout_status_transition(current, target)
        return target


class LayoutVersionPolicy:
    def assert_can_update(self, version: Any) -> None:
        ensure_layout_version_mutable(version)

    def assert_publish(self, *, current: LayoutVersionStatus) -> None:
        ensure_layout_version_status_transition(current, LayoutVersionStatus.PUBLISHED)

    def assert_retire(self, *, current: LayoutVersionStatus) -> None:
        ensure_layout_version_status_transition(current, LayoutVersionStatus.RETIRED)


class SiteThemeBindingPolicy:
    def assert_theme_assignable(self, theme: Any) -> None:
        ensure_assignable_theme(theme)

    def assert_version_assignable(self, version: Any) -> None:
        ensure_assignable_theme_version(version)


class PageLayoutBindingPolicy:
    def assert_layout_assignable(self, layout: Any) -> None:
        ensure_assignable_layout(layout)

    def assert_version_assignable(self, version: Any) -> None:
        ensure_assignable_layout_version(version)
