import enum
from datetime import datetime

from sqlalchemy import BigInteger, DateTime, Enum as SAEnum, ForeignKey, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.types import JSON

from app.models.base import BaseModel


class AgentStatus(str, enum.Enum):
    PENDING = "pending"
    ACTIVE = "active"
    OBSERVING = "observing"
    RISK_LOCKED = "risk_locked"
    SUSPENDED = "suspended"
    REJECTED = "rejected"
    TERMINATED = "terminated"


class UserAgent(BaseModel):
    __tablename__ = "user_agents"

    user_id: Mapped[int] = mapped_column(
        BigInteger, ForeignKey("users.id", ondelete="CASCADE"), unique=True, index=True, nullable=False
    )
    agent_tier_id: Mapped[int | None] = mapped_column(
        Integer, ForeignKey("agent_tiers.id", ondelete="SET NULL"), nullable=True, index=True
    )
    status: Mapped[AgentStatus] = mapped_column(
        SAEnum(AgentStatus, values_callable=lambda e: [m.value for m in e]),
        default=AgentStatus.PENDING,
        nullable=False,
        index=True,
    )
    invite_code: Mapped[str | None] = mapped_column(String(32), unique=True, index=True, nullable=True)
    total_sales: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    total_profit: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    total_subsidy: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    agent_balance: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    agent_frozen_balance: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    approved_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    approved_by: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    reject_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
    remark: Mapped[str | None] = mapped_column(Text, nullable=True)
    review_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    apply_tier: Mapped[str | None] = mapped_column(String(32), nullable=True)
    apply_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
    apply_channels: Mapped[str | None] = mapped_column(Text, nullable=True)

    observe_started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    observe_until: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
    risk_locked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    risk_reason: Mapped[str | None] = mapped_column(Text, nullable=True)
    last_evaluated_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
    last_evaluation_snapshot: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    agent_tier: Mapped["AgentTier"] = relationship("AgentTier", lazy="joined")
    user: Mapped["User"] = relationship("User", lazy="joined")
