from sqlalchemy import ForeignKey, Numeric, String, DateTime, Enum, Float
from sqlalchemy.orm import Mapped, mapped_column, relationship
from datetime import datetime
from decimal import Decimal
import enum
from app.database import Base


class BetCategory(enum.Enum):
    SPORTS = "sports"
    ESPORTS = "esports"
    POLITICS = "politics"
    ENTERTAINMENT = "entertainment"
    CUSTOM = "custom"


class BetStatus(enum.Enum):
    OPEN = "open"
    MATCHED = "matched"
    IN_PROGRESS = "in_progress"
    PENDING_RESULT = "pending_result"
    COMPLETED = "completed"
    CANCELLED = "cancelled"
    DISPUTED = "disputed"


class BetVisibility(enum.Enum):
    PUBLIC = "public"
    PRIVATE = "private"
    FRIENDS_ONLY = "friends_only"


class Bet(Base):
    __tablename__ = "bets"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    creator_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    opponent_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)

    title: Mapped[str] = mapped_column(String(200))
    description: Mapped[str] = mapped_column(String(2000))
    category: Mapped[BetCategory] = mapped_column(Enum(BetCategory))

    # Event info
    event_name: Mapped[str] = mapped_column(String(200))
    event_date: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)

    # Terms
    creator_position: Mapped[str] = mapped_column(String(500))
    opponent_position: Mapped[str] = mapped_column(String(500))
    creator_odds: Mapped[float] = mapped_column(Float, default=1.0)
    opponent_odds: Mapped[float] = mapped_column(Float, default=1.0)

    # Stake
    stake_amount: Mapped[Decimal] = mapped_column(Numeric(12, 2))
    currency: Mapped[str] = mapped_column(String(3), default="USD")

    status: Mapped[BetStatus] = mapped_column(Enum(BetStatus), default=BetStatus.OPEN)
    visibility: Mapped[BetVisibility] = mapped_column(Enum(BetVisibility), default=BetVisibility.PUBLIC)

    # Result
    winner_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)
    settled_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
    settled_by: Mapped[str | None] = mapped_column(String(20), nullable=True)

    expires_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    # Relationships
    creator: Mapped["User"] = relationship(back_populates="created_bets", foreign_keys=[creator_id])
    opponent: Mapped["User"] = relationship(back_populates="accepted_bets", foreign_keys=[opponent_id])
    proposals: Mapped[list["BetProposal"]] = relationship(back_populates="bet")


class ProposalStatus(enum.Enum):
    PENDING = "pending"
    ACCEPTED = "accepted"
    REJECTED = "rejected"
    EXPIRED = "expired"


class BetProposal(Base):
    __tablename__ = "bet_proposals"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    bet_id: Mapped[int] = mapped_column(ForeignKey("bets.id"))
    proposer_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    proposed_stake: Mapped[Decimal] = mapped_column(Numeric(12, 2))
    proposed_creator_odds: Mapped[float] = mapped_column(Float)
    proposed_opponent_odds: Mapped[float] = mapped_column(Float)
    message: Mapped[str | None] = mapped_column(String(500), nullable=True)
    status: Mapped[ProposalStatus] = mapped_column(Enum(ProposalStatus), default=ProposalStatus.PENDING)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    expires_at: Mapped[datetime] = mapped_column(DateTime)

    # Relationships
    bet: Mapped["Bet"] = relationship(back_populates="proposals")
