"""Template domain policies — Phase 11.4."""
from __future__ import annotations

from typing import Any

from app.models.types import TemplateStatus, TemplateVersionStatus
from app.validators.templates import (
    ensure_template_status_transition,
    ensure_template_version_mutable,
    ensure_template_version_status_transition,
)
from shared.exceptions import AppError


class TemplateLifecyclePolicy:
    def assert_status_change(
        self, *, current: TemplateStatus, target: TemplateStatus
    ) -> TemplateStatus:
        ensure_template_status_transition(current, target)
        return target


class TemplateVersionPolicy:
    def assert_can_update(self, version: Any) -> None:
        ensure_template_version_mutable(version)

    def assert_publish(
        self, *, current: TemplateVersionStatus
    ) -> TemplateVersionStatus:
        ensure_template_version_status_transition(
            current, TemplateVersionStatus.PUBLISHED
        )
        return TemplateVersionStatus.PUBLISHED

    def assert_retire(
        self, *, current: TemplateVersionStatus
    ) -> TemplateVersionStatus:
        ensure_template_version_status_transition(
            current, TemplateVersionStatus.RETIRED
        )
        return TemplateVersionStatus.RETIRED


class TemplateInstantiationPolicy:
    def assert_template_instantiable(self, template: Any) -> None:
        status = getattr(template, "status", None)
        if status == TemplateStatus.ARCHIVED:
            raise AppError(
                "قالب بایگانی‌شده قابل نمونه‌سازی نیست",
                error_code="template_archived",
                status_code=409,
            )
        if getattr(template, "is_deleted", False):
            raise AppError(
                "قالب حذف‌شده قابل نمونه‌سازی نیست",
                error_code="template_deleted",
                status_code=409,
            )

    def assert_version_instantiable(self, version: Any) -> None:
        status = getattr(version, "status", None)
        if status != TemplateVersionStatus.PUBLISHED:
            raise AppError(
                "فقط نسخه منتشرشده قالب قابل نمونه‌سازی است",
                error_code="template_version_not_published",
                status_code=409,
                details={"status": getattr(status, "value", status)},
            )
        if getattr(version, "is_deleted", False):
            raise AppError(
                "نسخه حذف‌شده قالب قابل نمونه‌سازی نیست",
                error_code="template_version_deleted",
                status_code=409,
            )
