"""Chat modülü ORM: ChatWidget, ChatSession, ChatMessage. Sadece tablo şeması.

NOT: chat_sessions.visitor_id şimdilik FK'sız String — flovy_visitors tablosu
Adım 5'te gelecek, FK kısıtı o migration'da eklenecek.
"""
from datetime import UTC, datetime

from sqlalchemy import (
    DECIMAL,
    JSON,
    Boolean,
    DateTime,
    Enum,
    ForeignKey,
    Integer,
    String,
    Text,
    func,
)
from sqlalchemy.dialects.mysql import DATETIME as MySQLDateTime
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.database import Base, TimestampMixin, UUIDMixin

SESSION_STATUS = ("open", "closed", "escalated")
SENDER_TYPE = ("visitor", "ai", "operator", "system")
MESSAGE_TYPE = ("text", "ai", "system", "tool_result")


def _utcnow() -> datetime:
    return datetime.now(UTC).replace(tzinfo=None)


class ChatWidget(UUIDMixin, TimestampMixin, Base):
    __tablename__ = "chat_widgets"

    tenant_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True
    )
    name: Mapped[str] = mapped_column(String(200), nullable=False)
    api_key: Mapped[str] = mapped_column(String(64), nullable=False, unique=True, index=True)
    allowed_domains: Mapped[list | None] = mapped_column(JSON, nullable=True)
    ai_enabled: Mapped[bool] = mapped_column(Boolean, default=True, server_default="1")
    is_online: Mapped[bool] = mapped_column(Boolean, default=True, server_default="1")
    persona: Mapped[dict | None] = mapped_column(JSON, nullable=True)
    settings: Mapped[dict | None] = mapped_column(JSON, nullable=True)
    ai_budget_monthly: Mapped[float] = mapped_column(DECIMAL(10, 2), default=0, server_default="0")
    ai_budget_used: Mapped[float] = mapped_column(DECIMAL(10, 2), default=0, server_default="0")
    ai_budget_period: Mapped[str | None] = mapped_column(String(7), nullable=True)


class ChatSession(UUIDMixin, Base):
    __tablename__ = "chat_sessions"

    tenant_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True
    )
    widget_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("chat_widgets.id", ondelete="CASCADE"), nullable=False
    )
    visitor_id: Mapped[str | None] = mapped_column(
        String(36),
        ForeignKey("flovy_visitors.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )

    session_token: Mapped[str] = mapped_column(
        String(64), nullable=False, unique=True, index=True
    )
    status: Mapped[str] = mapped_column(
        Enum(*SESSION_STATUS, name="session_status"), default="open", server_default="open"
    )

    visitor_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
    visitor_email: Mapped[str | None] = mapped_column(String(200), nullable=True)
    visitor_phone: Mapped[str | None] = mapped_column(String(30), nullable=True)
    visitor_ip: Mapped[str | None] = mapped_column(String(45), nullable=True)
    visitor_browser: Mapped[str | None] = mapped_column(String(255), nullable=True)
    page_url: Mapped[str | None] = mapped_column(String(1000), nullable=True)
    referrer: Mapped[str | None] = mapped_column(String(500), nullable=True)

    kvkk_consent_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
    intent: Mapped[str | None] = mapped_column(String(50), nullable=True)

    nps_score: Mapped[int | None] = mapped_column(Integer, nullable=True)
    nps_comment: Mapped[str | None] = mapped_column(Text, nullable=True)
    nps_submitted_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)

    escalated_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
    idle_ping_sent_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)

    # 'metadata' SQLAlchemy'de rezerve → python attr session_metadata, kolon adı 'metadata'
    session_metadata: Mapped[dict | None] = mapped_column("metadata", JSON, nullable=True)

    started_at: Mapped[datetime] = mapped_column(DateTime, default=_utcnow, nullable=False)
    ended_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)

    messages: Mapped[list["ChatMessage"]] = relationship(
        back_populates="session", cascade="all, delete-orphan"
    )


class ChatMessage(UUIDMixin, Base):
    __tablename__ = "chat_messages"

    session_id: Mapped[str] = mapped_column(
        String(36), ForeignKey("chat_sessions.id", ondelete="CASCADE"), nullable=False, index=True
    )
    tenant_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)

    sender_type: Mapped[str] = mapped_column(Enum(*SENDER_TYPE, name="sender_type"), nullable=False)
    message: Mapped[str] = mapped_column(Text, nullable=False)
    message_type: Mapped[str] = mapped_column(
        Enum(*MESSAGE_TYPE, name="message_type"), default="text", server_default="text"
    )
    meta: Mapped[dict | None] = mapped_column(JSON, nullable=True)
    model: Mapped[str | None] = mapped_column(String(100), nullable=True)
    latency_ms: Mapped[int | None] = mapped_column(Integer, nullable=True)
    is_read: Mapped[bool] = mapped_column(Boolean, default=False, server_default="0")
    # Mikrosaniye hassasiyeti — aynı saniyedeki ziyaretçi+AI mesajları doğru sıralanır
    created_at: Mapped[datetime] = mapped_column(
        MySQLDateTime(fsp=6), server_default=func.now(6), nullable=False
    )

    session: Mapped["ChatSession"] = relationship(back_populates="messages")
