from datetime import datetime

from sqlalchemy import String, Integer, Float, DateTime, Text, JSON
from sqlalchemy.orm import Mapped, mapped_column

from backend.database.connection import Base


class Product(Base):
    __tablename__ = "products"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    platform: Mapped[str] = mapped_column(String(20), default="tiktok_shop", index=True)
    product_id: Mapped[str] = mapped_column(String(100), index=True)
    title: Mapped[str] = mapped_column(Text, default="")
    description: Mapped[str] = mapped_column(Text, default="")
    image: Mapped[str] = mapped_column(Text, default="")
    url: Mapped[str] = mapped_column(Text, default="")

    price: Mapped[str] = mapped_column(String(50), default="")
    original_price: Mapped[str] = mapped_column(String(50), default="")
    discount: Mapped[str] = mapped_column(String(50), default="")

    sold_count: Mapped[int] = mapped_column(Integer, default=0, index=True)
    rating: Mapped[float] = mapped_column(Float, default=0.0)
    review_count: Mapped[int] = mapped_column(Integer, default=0)
    stock: Mapped[int] = mapped_column(Integer, default=0)

    seller_name: Mapped[str] = mapped_column(String(200), default="")
    shop_name: Mapped[str] = mapped_column(String(200), default="")
    shop_url: Mapped[str] = mapped_column(Text, default="")

    category: Mapped[str] = mapped_column(String(200), default="")
    related_video_count: Mapped[int] = mapped_column(Integer, default=0)
    related_videos: Mapped[dict | None] = mapped_column(JSON, default=list)

    collected_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    updated_at: Mapped[datetime] = mapped_column(
        DateTime, default=datetime.utcnow, onupdate=datetime.utcnow
    )

    def __repr__(self):
        return f"<Product {self.product_id}: {self.title[:50]}>"

    @property
    def sold_formatted(self) -> str:
        if self.sold_count >= 1_000_000:
            return f"{self.sold_count / 1_000_000:.1f}M"
        if self.sold_count >= 1_000:
            return f"{self.sold_count / 1_000:.1f}K"
        return str(self.sold_count)

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "platform": self.platform,
            "product_id": self.product_id,
            "title": self.title,
            "description": self.description[:200] if self.description else "",
            "image": self.image,
            "url": self.url,
            "price": self.price,
            "original_price": self.original_price,
            "discount": self.discount,
            "sold_count": self.sold_count,
            "sold_formatted": self.sold_formatted,
            "rating": self.rating,
            "review_count": self.review_count,
            "stock": self.stock,
            "seller_name": self.seller_name,
            "shop_name": self.shop_name,
            "shop_url": self.shop_url,
            "category": self.category,
            "related_video_count": self.related_video_count,
            "related_videos": self.related_videos or [],
            "collected_at": self.collected_at.isoformat() if self.collected_at else None,
        }
