"""Mesh protocol schemas."""
from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, Field


ConversationType = Literal["social", "task"]
MessageType = Literal[
    "prompt",
    "response",
    "info_share",
    "task_delegate",
    "task_result",
    "pause",
    "resume",
    "wrap_up",
    "close",
    "ping",
    "file_transfer_offer",
    "file_transfer_accept",
    "file_transfer_decline",
    "file_transfer_cancel",
    "peer_proposal",
]


class MeshMessage(BaseModel):
    type: MessageType
    conversation_id: str = Field(min_length=1)
    conversation_type: ConversationType = "social"
    message_number: int = Field(default=1, ge=1)
    in_reply_to: str | None = None
    # Payload conventions (backward compatible; optional keys):
    # - prompt | task_delegate | info_share: optional logical_message_id — sender-provided opaque id (hex UUID
    #   canonical or uuid.hex); receiver deduplicates by (sender fingerprint, logical_message_id) within TTL.
    # - task_delegate: {"text": "...", "job_id": "...", "reply_by": "...", "max_response_chars": N, "envelope": {...}}
    # - task_result: {"ok": bool, "text": "...", "error": "...", "job_id": "...", "metadata": {...}, "envelope": {...}}
    # - file_transfer_offer: {"schema": 1, "transfer_id", "sender_fingerprint", "receiver_fingerprint",
    #   "expiry_unix", "host", "port", "serve_path_prefix", "key_b64", "files": [{"id","relpath","size","sha256_hex"}]}
    # - file_transfer_accept | file_transfer_decline | file_transfer_cancel: {"schema": 1, "transfer_id"}
    # conversation_id for transfer control: file-transfer:{transfer_id}
    # Envelope fields are optional and treated as untrusted hints.
    payload: dict = Field(default_factory=dict)
    ttl: int = Field(default=300, ge=30, le=3600)


class HandshakeRequest(BaseModel):
    static_pub: str
    ephemeral_pub: str
    salt: str
    hostname: str = ""
    mesh_port: int | None = None


class HandshakeResponse(BaseModel):
    status: Literal["ok", "pending", "denied", "error"] = "ok"
    reason: str = ""
    request_id: str | None = None
    static_pub: str | None = None
    ephemeral_pub: str | None = None
    session_id: str | None = None
