import uuid
from decimal import Decimal
from typing import Any

from sqlalchemy import Boolean, ForeignKey, Numeric, String, Text
from sqlalchemy.orm import Mapped, mapped_column

from app.models.types import GUID, JSONColumn

from app.models.base import BaseModel


class Referral(BaseModel):
    __tablename__ = "referrals"

    referrer_user_id: Mapped[uuid.UUID] = mapped_column(
        GUID, ForeignKey("users.id", ondelete="CASCADE"), index=True, nullable=False
    )
    referred_user_id: Mapped[uuid.UUID] = mapped_column(
        GUID, ForeignKey("users.id", ondelete="CASCADE"), index=True, nullable=False
    )
    order_id: Mapped[uuid.UUID | None] = mapped_column(
        GUID, ForeignKey("orders.id", ondelete="SET NULL"), index=True
    )
    reward: Mapped[Decimal] = mapped_column(Numeric(18, 2), default=Decimal("0"), nullable=False)
    status: Mapped[str] = mapped_column(String(16), default="pending", index=True, nullable=False)


class BankCard(BaseModel):
    __tablename__ = "bank_cards"

    user_id: Mapped[uuid.UUID] = mapped_column(
        GUID, ForeignKey("users.id", ondelete="CASCADE"), index=True, nullable=False
    )
    title: Mapped[str | None] = mapped_column(String(128))
    card_number: Mapped[str | None] = mapped_column(String(32))
    image: Mapped[str | None] = mapped_column(String(255))
    status: Mapped[str] = mapped_column(String(16), default="pending", index=True, nullable=False)


class SupportTicket(BaseModel):
    __tablename__ = "support_tickets"

    user_id: Mapped[uuid.UUID] = mapped_column(
        GUID, ForeignKey("users.id", ondelete="CASCADE"), index=True, nullable=False
    )
    subject: Mapped[str | None] = mapped_column(String(160))
    message: Mapped[str] = mapped_column(Text, nullable=False)
    reply: Mapped[str | None] = mapped_column(Text)
    attachment: Mapped[str | None] = mapped_column(String(255))
    status: Mapped[str] = mapped_column(String(16), default="open", index=True, nullable=False)


class Setting(BaseModel):
    """Global key/value configuration. Value is always JSON."""

    __tablename__ = "settings"

    key: Mapped[str] = mapped_column(String(64), unique=True, index=True, nullable=False)
    value: Mapped[Any] = mapped_column(JSONColumn, nullable=False)
    title: Mapped[str | None] = mapped_column(String(160))
    is_public: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)


class Log(BaseModel):
    __tablename__ = "logs"

    type: Mapped[str] = mapped_column(String(32), index=True, nullable=False)
    event: Mapped[str] = mapped_column(String(64), index=True, nullable=False)
    message: Mapped[str | None] = mapped_column(Text)
    user_id: Mapped[uuid.UUID | None] = mapped_column(
        GUID, ForeignKey("users.id", ondelete="SET NULL"), index=True
    )
    order_id: Mapped[uuid.UUID | None] = mapped_column(
        GUID, ForeignKey("orders.id", ondelete="SET NULL"), index=True
    )
    payment_id: Mapped[uuid.UUID | None] = mapped_column(
        GUID, ForeignKey("payments.id", ondelete="SET NULL"), index=True
    )
    data: Mapped[dict[str, Any]] = mapped_column(JSONColumn, default=dict, nullable=False)
