import uuid
from datetime import datetime
from decimal import Decimal
from typing import Any

from pydantic import BaseModel, ConfigDict, Field


class TelegramUserIn(BaseModel):
    telegram_id: int
    username: str | None = None
    first_name: str | None = None
    last_name: str | None = None
    language: str = "fa"
    referral_code: str | None = None


class UserOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    telegram_id: int
    username: str | None = None
    first_name: str | None = None
    last_name: str | None = None
    language: str
    is_admin: bool
    is_blocked: bool
    note: str | None = None
    referral_code: str
    referred_by: uuid.UUID | None = None
    created_at: datetime


class UserUpdate(BaseModel):
    language: str | None = None
    note: str | None = None
    is_blocked: bool | None = None
    is_admin: bool | None = None


class WalletOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    user_id: uuid.UUID
    balance: Decimal
    locked_balance: Decimal


class TransactionOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    type: str
    amount: Decimal
    balance_after: Decimal
    description: str | None = None
    order_id: uuid.UUID | None = None
    created_at: datetime


class WalletAdjust(BaseModel):
    user_id: uuid.UUID
    amount: Decimal
    description: str = ""


class StartResponse(BaseModel):
    user: UserOut
    balance: Decimal
    is_new: bool
    menu: list[dict[str, Any]] = Field(default_factory=list)
    settings: dict[str, Any] = Field(default_factory=dict)


class LoginRequest(BaseModel):
    username: str
    password: str


class RefreshRequest(BaseModel):
    refresh_token: str


class TokenResponse(BaseModel):
    access_token: str
    refresh_token: str
    token_type: str = "bearer"


class PasswordChange(BaseModel):
    current_password: str
    new_password: str = Field(min_length=8)


class AdminOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    username: str
    role: str
    is_active: bool
    created_at: datetime


class SupportTicketIn(BaseModel):
    message: str = Field(min_length=1, max_length=2000)
    subject: str | None = None
    attachment: str | None = None


class SupportReply(BaseModel):
    message: str = Field(min_length=1, max_length=2000)


class SupportTicketOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    user_id: uuid.UUID
    subject: str | None = None
    message: str
    reply: str | None = None
    attachment: str | None = None
    status: str
    created_at: datetime


class ReferralOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    referrer_user_id: uuid.UUID
    referred_user_id: uuid.UUID
    order_id: uuid.UUID | None = None
    reward: Decimal
    status: str
    created_at: datetime


class LogOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    type: str
    event: str
    message: str | None = None
    user_id: uuid.UUID | None = None
    order_id: uuid.UUID | None = None
    payment_id: uuid.UUID | None = None
    data: dict[str, Any]
    created_at: datetime


class SettingOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    key: str
    value: Any
    title: str | None = None
    is_public: bool


class SettingsUpdate(BaseModel):
    values: dict[str, Any]


class MessagesUpdate(BaseModel):
    values: dict[str, str]


class MenuUpdate(BaseModel):
    items: list[dict[str, Any]]


class BankCardOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    user_id: uuid.UUID
    title: str | None = None
    card_number: str | None = None
    image: str | None = None
    status: str
    created_at: datetime
