"""انواع سفارشی قابل حمل دیتابیس.

GUID: روی PostgreSQL از نوع UUID و روی SQLite (تست‌ها) از CHAR(36)
استفاده می‌کند تا مدل‌ها هم در production و هم در تست کار کنند.
"""
from __future__ import annotations

import uuid

from sqlalchemy.dialects.postgresql import UUID as PG_UUID
from sqlalchemy.types import CHAR, TypeDecorator


class GUID(TypeDecorator):
    """نوع شناسه سراسری منطبق با UUID.

    در PostgreSQL به‌صورت native UUID و در سایر دیالکت‌ها به‌صورت رشته
    ۳۶ کاراکتری ذخیره می‌شود.
    """

    impl = CHAR
    cache_ok = True

    def load_dialect_impl(self, dialect):
        if dialect.name == "postgresql":
            return dialect.type_descriptor(PG_UUID(as_uuid=True))
        return dialect.type_descriptor(CHAR(36))

    def process_bind_param(self, value, dialect):
        if value is None:
            return value
        if dialect.name == "postgresql":
            return value if isinstance(value, uuid.UUID) else uuid.UUID(str(value))
        return str(value)

    def process_result_value(self, value, dialect):
        if value is None:
            return value
        if isinstance(value, uuid.UUID):
            return value
        return uuid.UUID(str(value))
