from __future__ import annotations

from datetime import datetime

from sqlalchemy import (
    Boolean,
    DateTime,
    Float,
    ForeignKey,
    Integer,
    String,
    Text,
)
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship


class Base(DeclarativeBase):
    pass


class User(Base):
    __tablename__ = "users"

    user_id: Mapped[int] = mapped_column(Integer, primary_key=True)
    username: Mapped[str] = mapped_column(String(128), default="", nullable=False)
    full_name: Mapped[str] = mapped_column(String(256), default="", nullable=False)
    balance: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
    purchases_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    total_spent: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
    weekly_spent: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
    referrer_id: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True)
    referred_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    referral_earned: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
    is_banned: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, nullable=False
    )


class Category(Base):
    __tablename__ = "categories"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    sort_order: Mapped[int] = mapped_column(Integer, default=0, nullable=False)

    items: Mapped[list["Item"]] = relationship(
        back_populates="category", cascade="all, delete-orphan"
    )


class Item(Base):
    __tablename__ = "items"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    category_id: Mapped[int] = mapped_column(
        ForeignKey("categories.id"), index=True, nullable=False
    )
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    description: Mapped[str] = mapped_column(Text, default="", nullable=False)
    price: Mapped[float] = mapped_column(Float, nullable=False)
    is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
    sort_order: Mapped[int] = mapped_column(Integer, default=0, nullable=False)

    category: Mapped[Category] = relationship(back_populates="items")
    stock: Mapped[list["Stock"]] = relationship(
        back_populates="item", cascade="all, delete-orphan"
    )


class Stock(Base):
    __tablename__ = "stock"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    item_id: Mapped[int] = mapped_column(
        ForeignKey("items.id"), index=True, nullable=False
    )
    content: Mapped[str] = mapped_column(Text, nullable=False)
    totp_secret: Mapped[str] = mapped_column(String(255), default="", nullable=False)
    is_sold: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)

    item: Mapped[Item] = relationship(back_populates="stock")


class Purchase(Base):
    __tablename__ = "purchases"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    item_id: Mapped[int | None] = mapped_column(Integer, index=True, nullable=True)
    reseller_id: Mapped[int | None] = mapped_column(Integer, index=True, nullable=True)
    item_name: Mapped[str] = mapped_column(String(255), nullable=False)
    price: Mapped[float] = mapped_column(Float, nullable=False)
    content: Mapped[str] = mapped_column(Text, default="", nullable=False)
    totp_secret: Mapped[str] = mapped_column(String(255), default="", nullable=False)
    reviewed: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, nullable=False
    )


class Review(Base):
    __tablename__ = "reviews"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    purchase_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    item_id: Mapped[int | None] = mapped_column(Integer, index=True, nullable=True)
    item_name: Mapped[str] = mapped_column(String(255), default="", nullable=False)
    rating: Mapped[int] = mapped_column(Integer, nullable=False)
    text: Mapped[str] = mapped_column(Text, default="", nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, nullable=False
    )


class Setting(Base):
    """Runtime key/value config editable from the admin panel."""

    __tablename__ = "settings"

    key: Mapped[str] = mapped_column(String(64), primary_key=True)
    value: Mapped[str] = mapped_column(Text, default="", nullable=False)


class TopUp(Base):
    __tablename__ = "topups"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    amount: Mapped[float] = mapped_column(Float, nullable=False)
    status: Mapped[str] = mapped_column(String(16), default="pending", nullable=False)
    method: Mapped[str] = mapped_column(String(16), default="manual", nullable=False)
    invoice_id: Mapped[str] = mapped_column(String(64), default="", nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, nullable=False
    )


class ResellerBot(Base):
    __tablename__ = "reseller_bots"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    owner_user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    admin_user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    bot_token: Mapped[str] = mapped_column(String(255), nullable=False)
    bot_username: Mapped[str] = mapped_column(String(128), default="", nullable=False)
    markup_percent: Mapped[float] = mapped_column(Float, default=20.0, nullable=False)
    earnings_balance: Mapped[float] = mapped_column(Float, default=0.0, nullable=False)
    channel_ref: Mapped[str] = mapped_column(String(255), default="", nullable=False)
    channel_required: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, nullable=False
    )


class ResellerCustomer(Base):
    __tablename__ = "reseller_customers"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    reseller_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    username: Mapped[str] = mapped_column(String(128), default="", nullable=False)
    full_name: Mapped[str] = mapped_column(String(256), default="", nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, nullable=False
    )


class ResellerItemOverride(Base):
    __tablename__ = "reseller_item_overrides"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    reseller_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    item_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    photo_file_id: Mapped[str] = mapped_column(String(255), default="", nullable=False)
    is_hidden: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)


class ResellerOrder(Base):
    __tablename__ = "reseller_orders"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    reseller_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    buyer_user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    item_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    price: Mapped[float] = mapped_column(Float, nullable=False)
    invoice_id: Mapped[str] = mapped_column(String(64), default="", nullable=False)
    status: Mapped[str] = mapped_column(String(16), default="pending", nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, nullable=False
    )


class ResellerSale(Base):
    __tablename__ = "reseller_sales"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    reseller_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    buyer_user_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    item_id: Mapped[int | None] = mapped_column(Integer, index=True, nullable=True)
    item_name: Mapped[str] = mapped_column(String(255), nullable=False)
    base_price: Mapped[float] = mapped_column(Float, nullable=False)
    reseller_price: Mapped[float] = mapped_column(Float, nullable=False)
    reseller_profit: Mapped[float] = mapped_column(Float, nullable=False)
    platform_profit: Mapped[float] = mapped_column(Float, nullable=False)
    purchase_id: Mapped[int | None] = mapped_column(Integer, nullable=True)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, nullable=False
    )


class ResellerPayout(Base):
    __tablename__ = "reseller_payouts"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    reseller_id: Mapped[int] = mapped_column(Integer, index=True, nullable=False)
    amount: Mapped[float] = mapped_column(Float, nullable=False)
    asset: Mapped[str] = mapped_column(String(16), default="USDT", nullable=False)
    status: Mapped[str] = mapped_column(String(16), default="pending", nullable=False)
    spend_id: Mapped[str] = mapped_column(String(64), default="", nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, nullable=False
    )
