"""Forms / surveys / appointments policies — Phase 11.6."""
from __future__ import annotations

from typing import Any

from app.models.types import (
    AppointmentBookingStatus,
    AppointmentPageStatus,
    FormStatus,
    FormSubmissionStatus,
    SurveyResponseStatus,
    SurveyStatus,
)
from app.validators.forms import (
    ensure_appointment_page_status_transition,
    ensure_booking_status_transition,
    ensure_form_status_transition,
    ensure_response_status_transition,
    ensure_submission_status_transition,
    ensure_survey_status_transition,
)
from shared.exceptions import AppError


class FormLifecyclePolicy:
    def assert_status_change(
        self, *, current: FormStatus, target: FormStatus
    ) -> FormStatus:
        ensure_form_status_transition(current, target)
        return target

    def assert_accepts_submissions(self, form: Any) -> None:
        if getattr(form, "is_deleted", False):
            raise AppError(
                "فرم حذف‌شده قابل ارسال نیست",
                error_code="form_deleted",
                status_code=409,
            )
        if getattr(form, "status", None) != FormStatus.ACTIVE:
            raise AppError(
                "فقط فرم فعال قابل ارسال است",
                error_code="form_not_active",
                status_code=409,
            )


class FormSubmissionPolicy:
    def assert_status_change(
        self, *, current: FormSubmissionStatus, target: FormSubmissionStatus
    ) -> FormSubmissionStatus:
        ensure_submission_status_transition(current, target)
        return target


class SurveyLifecyclePolicy:
    def assert_status_change(
        self, *, current: SurveyStatus, target: SurveyStatus
    ) -> SurveyStatus:
        ensure_survey_status_transition(current, target)
        return target

    def assert_accepts_responses(self, survey: Any) -> None:
        if getattr(survey, "is_deleted", False):
            raise AppError(
                "نظرسنجی حذف‌شده قابل پاسخ نیست",
                error_code="survey_deleted",
                status_code=409,
            )
        if getattr(survey, "status", None) != SurveyStatus.ACTIVE:
            raise AppError(
                "فقط نظرسنجی فعال قابل پاسخ است",
                error_code="survey_not_active",
                status_code=409,
            )


class SurveyResponsePolicy:
    def assert_status_change(
        self, *, current: SurveyResponseStatus, target: SurveyResponseStatus
    ) -> SurveyResponseStatus:
        ensure_response_status_transition(current, target)
        return target


class AppointmentPagePolicy:
    def assert_status_change(
        self, *, current: AppointmentPageStatus, target: AppointmentPageStatus
    ) -> AppointmentPageStatus:
        ensure_appointment_page_status_transition(current, target)
        return target

    def assert_accepts_bookings(self, page: Any) -> None:
        if getattr(page, "is_deleted", False):
            raise AppError(
                "صفحه نوبت حذف‌شده قابل رزرو نیست",
                error_code="appointment_page_deleted",
                status_code=409,
            )
        if getattr(page, "status", None) != AppointmentPageStatus.ACTIVE:
            raise AppError(
                "فقط صفحه نوبت فعال قابل رزرو است",
                error_code="appointment_page_not_active",
                status_code=409,
            )


class AppointmentBookingPolicy:
    def assert_status_change(
        self, *, current: AppointmentBookingStatus, target: AppointmentBookingStatus
    ) -> AppointmentBookingStatus:
        ensure_booking_status_transition(current, target)
        return target
