"""
SQLAlchemy 2.0 ORM models for web chat conversations.

These models support the Phase 6 web chat feature — a WebSocket-based
channel that allows portal users to chat with AI employees directly from
the Konstruct portal UI.

Tables:
  web_conversations         — One per portal user + agent pair per tenant
  web_conversation_messages — Individual messages within a conversation

RLS is applied to both tables via app.current_tenant session variable,
same pattern as agents and channel_connections (migration 008).

Design notes:
  - UniqueConstraint on (tenant_id, agent_id, user_id) for get-or-create semantics
  - role column is TEXT+CHECK (not sa.Enum) per Phase 1 ADR to avoid Alembic DDL conflicts
  - ON DELETE CASCADE on messages.conversation_id: deleting a conversation
    removes all its messages automatically
"""

from __future__ import annotations

import uuid
from datetime import datetime

from sqlalchemy import DateTime, ForeignKey, Text, UniqueConstraint, func
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column

from shared.models.tenant import Base


class WebConversation(Base):
    """
    A web chat conversation between a portal user and an AI employee.

    One row per (tenant_id, agent_id, user_id) triple — callers use
    get-or-create semantics when starting a chat session.

    RLS scoped to tenant_id so the app role only sees conversations
    for the currently-configured tenant.
    """

    __tablename__ = "web_conversations"

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        primary_key=True,
        default=uuid.uuid4,
        server_default=func.gen_random_uuid(),
    )
    tenant_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("tenants.id", ondelete="CASCADE"),
        nullable=False,
    )
    agent_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("agents.id", ondelete="CASCADE"),
        nullable=False,
    )
    user_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        nullable=False,
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
        onupdate=func.now(),
    )

    __table_args__ = (
        UniqueConstraint("tenant_id", "agent_id", "user_id", name="uq_web_conversations_tenant_agent_user"),
    )


class WebConversationMessage(Base):
    """
    A single message within a web chat conversation.

    role is stored as TEXT with a CHECK constraint ('user' or 'assistant'),
    following the Phase 1 convention that avoids PostgreSQL ENUM DDL issues.

    Messages are deleted via ON DELETE CASCADE when their parent conversation
    is deleted, or explicitly during a conversation reset (DELETE /conversations/{id}).
    """

    __tablename__ = "web_conversation_messages"

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        primary_key=True,
        default=uuid.uuid4,
        server_default=func.gen_random_uuid(),
    )
    conversation_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("web_conversations.id", ondelete="CASCADE"),
        nullable=False,
    )
    tenant_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        nullable=False,
    )
    role: Mapped[str] = mapped_column(
        Text,
        nullable=False,
    )
    content: Mapped[str] = mapped_column(
        Text,
        nullable=False,
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
    )
