"""Reusable validators for Experience foundation."""
from __future__ import annotations

import re
from typing import Any

from shared.exceptions import AppError

CODE_RE = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9_\-]{1,49}$")


class ValidationError(AppError):
    def __init__(self, message: str, details: dict[str, Any] | None = None):
        super().__init__(
            message=message,
            error_code="validation_error",
            status_code=422,
            details=details or {},
        )


def validate_non_empty(value: str | None, field: str) -> str:
    if value is None or not str(value).strip():
        raise ValidationError(f"{field} الزامی است", {"field": field})
    return str(value).strip()


def validate_code(code: str) -> str:
    code = validate_non_empty(code, "code")
    if not CODE_RE.match(code):
        raise ValidationError(
            "کد نامعتبر است — فقط لاتین/عدد/_/- و حداقل ۲ کاراکتر "
            "(مثال: main-shop یا ws_01). فارسی و فاصله مجاز نیست.",
            {"field": "code", "pattern": CODE_RE.pattern},
        )
    return code


def validate_currency_code(code: str) -> str:
    code = validate_non_empty(code, "currency_code").upper()
    if len(code) != 3:
        raise ValidationError("currency_code باید ۳ حرفی باشد", {"field": "currency_code"})
    return code


def ensure_optimistic_version(entity: Any, expected: int) -> None:
    current = getattr(entity, "version", None)
    if current is None:
        return
    if current != expected:
        raise AppError(
            "نسخه موجودیت هم‌خوان نیست",
            error_code="version_conflict",
            status_code=409,
            details={"expected": expected, "actual": current},
        )
