"""Pydantic models for Discord bot configuration and messaging endpoints."""

from __future__ import annotations

from datetime import datetime
from typing import Any

from pydantic import BaseModel


class DiscordConfigCreate(BaseModel):
    bot_token: str
    guild_id: str = ""
    enabled: bool = True
    dm_policy: str = "disabled"
    guild_policy: str = "open"
    require_mention: bool = False
    history_limit: int = 10
    model: str = ""
    system_prompt: str = ""


class DiscordConfigUpdate(BaseModel):
    bot_token: str | None = None
    guild_id: str | None = None
    enabled: bool | None = None
    dm_policy: str | None = None
    guild_policy: str | None = None
    require_mention: bool | None = None
    history_limit: int | None = None
    model: str | None = None
    system_prompt: str | None = None


class DiscordConfigResponse(BaseModel):
    id: int
    # bot_token is intentionally masked in API responses
    bot_token_masked: str
    guild_id: str
    enabled: bool
    dm_policy: str
    guild_policy: str
    require_mention: bool
    history_limit: int
    model: str
    system_prompt: str
    created_at: datetime
    updated_at: datetime


class ChannelMappingCreate(BaseModel):
    channel_id: str
    channel_name: str = ""
    allowed_user_ids: list[str] = []
    allowed_role_ids: list[str] = []
    subscribed_events: list[str] = []
    enabled: bool = True
    project_id: str = ""
    discord_config_id: int | None = None


class ChannelMappingUpdate(BaseModel):
    channel_name: str | None = None
    allowed_user_ids: list[str] | None = None
    allowed_role_ids: list[str] | None = None
    subscribed_events: list[str] | None = None
    enabled: bool | None = None
    project_id: str | None = None


class ChannelMappingResponse(BaseModel):
    id: int
    discord_config_id: int
    channel_id: str
    channel_name: str
    allowed_user_ids: list[str]
    allowed_role_ids: list[str]
    subscribed_events: list[str]
    enabled: bool
    project_id: str
    created_at: datetime


class DiscordEmbedField(BaseModel):
    name: str
    value: str
    inline: bool = False


class DiscordMessagePayload(BaseModel):
    content: str = ""
    embed_title: str = ""
    embed_description: str = ""
    embed_color: int = 0x00FF00
    embed_fields: list[DiscordEmbedField] = []


class BotStatusResponse(BaseModel):
    config_id: int
    status: str  # "connected" | "disconnected" | "error"
    error: str | None = None


class DiscordInboundMessageResponse(BaseModel):
    id: int
    discord_config_id: int
    channel_id: str
    channel_name: str
    author_id: str
    author_name: str
    content: str
    status: str  # "pending" | "processed" | "ignored"
    created_at: datetime


class SendMessageRequest(BaseModel):
    channel_id: str
    content: str = ""
    embed_title: str = ""
    embed_description: str = ""


class SendMessageResponse(BaseModel):
    config_id: int
    channel_id: str
    sent: bool
    error: str | None = None


class InboundMessageCreate(BaseModel):
    """Payload for POST /api/discord/messages/inbound from the bot gateway."""

    config_id: int
    channel_id: str
    user_id: str
    username: str = ""
    content: str
    message_id: str = ""
    replied_to: str = ""
    # Access control fields — set by gateway when routing denies the message
    denied: bool = False
    deny_reason: str = ""
    # Role IDs the sender holds (used for allowlist checks and audit logs)
    member_roles: list[str] = []


class InboundMessageResponse(BaseModel):
    """Stored inbound Discord message."""

    id: int
    config_id: int
    channel_id: str
    user_id: str
    username: str
    content: str
    message_id: str
    replied_to: str
    processed: bool
    denied: bool
    deny_reason: str
    created_at: datetime


class InboundMessageAck(BaseModel):
    """Acknowledgment returned after storing an inbound message."""

    message_db_id: int
    status: str


# ---------------------------------------------------------------------------
# Paired users (DM pairing flow)
# ---------------------------------------------------------------------------


class PairedUserCreate(BaseModel):
    """Payload for approving a Discord user for DM pairing."""

    user_id: str
    username: str = ""
    pairing_code: str = ""
    approved_by: str = ""


class PairedUserResponse(BaseModel):
    """An approved Discord paired user."""

    id: int
    discord_config_id: int
    user_id: str
    username: str
    pairing_code: str
    approved_by: str
    paired_at: datetime


# ---------------------------------------------------------------------------
# Activity logs
# ---------------------------------------------------------------------------

DISCORD_EVENT_TYPES = frozenset([
    "bot_connected",
    "bot_disconnected",
    "message_received",
    "message_denied",
    "message_sent",
    "ai_response",
    "command_invoked",
])


class ActivityLogCreate(BaseModel):
    """Payload for logging a Discord activity event."""

    config_id: int
    event_type: str
    channel_id: str = ""
    user_id: str = ""
    detail: str = ""


class ActivityLogResponse(BaseModel):
    """A Discord activity log entry."""

    id: int
    config_id: int
    event_type: str
    channel_id: str
    user_id: str
    detail: str
    created_at: datetime
