from __future__ import annotations

from datetime import datetime
from decimal import Decimal
import uuid
from enum import Enum

from sqlalchemy import (
    DateTime,
    Enum as SqlEnum,
    Integer,
    Numeric,
    String,
    func,
    text,
)
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column

from core.db.base import Base, SoftDeleteMixin, TimestampMixin


class AgentChatSessionStatus(str, Enum):
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"


class SessionType(str, Enum):
    CHAT = "chat"
    AUTOMATION = "automation"


class AgentChatSession(TimestampMixin, SoftDeleteMixin, Base):
    __tablename__: str = "sessions"
    __table_args__ = {"extend_existing": True}

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
    )
    user_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        nullable=False,
        index=True,
    )
    session_type: Mapped[SessionType] = mapped_column(
        String(20),
        nullable=False,
        default=SessionType.CHAT,
    )
    job_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True),
        nullable=True,
    )
    title: Mapped[str | None] = mapped_column(String(255), nullable=True)
    status: Mapped[AgentChatSessionStatus] = mapped_column(
        SqlEnum(
            AgentChatSessionStatus, name="agent_chat_session_status", native_enum=False
        ),
        nullable=False,
        default=AgentChatSessionStatus.PENDING,
    )
    last_activity_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        server_default=func.now(),
        nullable=False,
    )
    message_count: Mapped[int] = mapped_column(
        Integer, nullable=False, server_default=text("0")
    )
    total_tokens: Mapped[int] = mapped_column(
        Integer, nullable=False, server_default=text("0")
    )
    total_cost: Mapped[Decimal] = mapped_column(
        Numeric(12, 6), nullable=False, server_default=text("0")
    )
