"""استثناهای مشترک دامنه (Domain Exceptions).

این استثناها مستقل از فریم‌ورک هستند تا در همه سرویس‌ها قابل استفاده باشند.
لایه API هر سرویس آن‌ها را به پاسخ HTTP مناسب تبدیل می‌کند.
"""
from __future__ import annotations

from typing import Any


class AppError(Exception):
    """پایه همه خطاهای دامنه‌ای برنامه."""

    status_code: int = 500
    error_code: str = "internal_error"

    def __init__(
        self,
        message: str | None = None,
        *,
        error_code: str | None = None,
        status_code: int | None = None,
        details: Any | None = None,
    ) -> None:
        self.message = message or self.__class__.__doc__ or "Application error"
        if error_code is not None:
            self.error_code = error_code
        if status_code is not None:
            self.status_code = status_code
        self.details = details
        super().__init__(self.message)


class NotFoundError(AppError):
    """منبع درخواستی یافت نشد."""

    status_code = 404
    error_code = "not_found"


class ConflictError(AppError):
    """تعارض داده (مثلاً مقدار تکراری)."""

    status_code = 409
    error_code = "conflict"


class ValidationAppError(AppError):
    """داده ورودی نامعتبر است."""

    status_code = 422
    error_code = "validation_error"


class UnauthorizedError(AppError):
    """احراز هویت انجام نشده است."""

    status_code = 401
    error_code = "unauthorized"


class ForbiddenError(AppError):
    """دسترسی مجاز نیست."""

    status_code = 403
    error_code = "forbidden"


class TenantNotResolvedError(AppError):
    """tenant قابل تشخیص نبود در حالی که endpoint نیازمند tenant است."""

    status_code = 400
    error_code = "tenant_not_resolved"


class FeatureAccessDeniedError(ForbiddenError):
    """tenant به این قابلیت دسترسی ندارد."""

    error_code = "feature_access_denied"
