"""Conversations commands — CRUD for conversations plus conversation messages."""

from __future__ import annotations

import json

import typer

from turumba_cli.client import TurumbaClient
from turumba_cli.config import get_value
from turumba_cli.errors import TurumbaAPIError, TurumbaAuthError
from turumba_cli.output import error, render, render_meta, success

app = typer.Typer(name="conversations", help="Manage conversations (agent-visitor threads).")

API_PATH = "/v1/conversations"

LIST_COLUMNS = {
    "ID": "id",
    "Status": "status",
    "Priority": "priority",
    "Subject": "subject",
    "Source": "source",
    "Assignee ID": "assignee_id",
    "Team ID": "team_id",
    "Created At": "created_at",
}

MESSAGE_COLUMNS = {
    "ID": "id",
    "Direction": "direction",
    "Status": "status",
    "Body": "message_body",
    "Content Type": "content_type",
    "Sender Type": "sender_type",
    "Private": "is_private",
    "Created At": "created_at",
}


def _handle_error(e: Exception) -> None:
    if isinstance(e, TurumbaAuthError | TurumbaAPIError):
        error(str(e))
    else:
        error(f"Unexpected error: {e}")
    raise typer.Exit(1)


def _resolve_account_id(account_id: str | None) -> str:
    resolved = account_id or get_value("default_account_id")
    if not resolved:
        error(
            "account_id is required. Use --account-id or set: "
            "turumba config set default_account_id <id>"
        )
        raise typer.Exit(1)
    return resolved


@app.command("list")
def list_conversations(
    filter_: list[str] | None = typer.Option(None, "--filter", "-f", help="Filter: field:op:value"),
    sort: list[str] | None = typer.Option(None, "--sort", "-s", help="Sort: field:asc|desc"),
    limit: int = typer.Option(100, "--limit", "-l", help="Max results"),
    skip: int = typer.Option(0, "--skip", help="Offset"),
    output: str = typer.Option("table", "--output", "-o", help="Output format: table, json, csv"),
    gateway_url: str = typer.Option(None, "--gateway-url", "-g", help="Gateway URL override"),
) -> None:
    """List conversations."""
    client = TurumbaClient(gateway_url=gateway_url)
    try:
        data, meta = client.list(API_PATH, filter_=filter_, sort=sort, limit=limit, skip=skip)
    except Exception as e:
        _handle_error(e)

    render(data, output_format=output, columns=LIST_COLUMNS, title="Conversations")
    render_meta(meta, output_format=output)


@app.command("get")
def get_conversation(
    conversation_id: str = typer.Argument(help="Conversation ID"),
    output: str = typer.Option("table", "--output", "-o", help="Output format: table, json"),
    gateway_url: str = typer.Option(None, "--gateway-url", "-g", help="Gateway URL override"),
) -> None:
    """Get details of a specific conversation."""
    client = TurumbaClient(gateway_url=gateway_url)
    try:
        data = client.get(API_PATH, conversation_id)
    except Exception as e:
        _handle_error(e)

    render(data, output_format=output, is_list=False, title="Conversation Details")


@app.command("create")
def create_conversation(
    account_id: str = typer.Option(
        None, "--account-id", "-a", help="Account ID (defaults to config default_account_id)"
    ),
    channel_id: str = typer.Option(None, "--channel-id", "-c", help="Channel ID"),
    chat_endpoint_id: str = typer.Option(None, "--chat-endpoint-id", help="Chat endpoint ID"),
    contact_id: str = typer.Option(None, "--contact-id", help="Contact ID"),
    assignee_id: str = typer.Option(None, "--assignee-id", help="Assignee user ID"),
    team_id: str = typer.Option(None, "--team-id", help="Team ID"),
    status: str = typer.Option(
        "open", "--status", help="Status: open, assigned, pending, resolved, closed"
    ),
    priority: str = typer.Option(
        "medium", "--priority", help="Priority: low, medium, high, urgent"
    ),
    subject: str = typer.Option(None, "--subject", "-s", help="Conversation subject"),
    source: str = typer.Option(None, "--source", help="Source identifier"),
    metadata: str = typer.Option(None, "--metadata", "-m", help="Metadata as JSON string"),
    output: str = typer.Option("table", "--output", "-o", help="Output format: table, json"),
    gateway_url: str = typer.Option(None, "--gateway-url", "-g", help="Gateway URL override"),
) -> None:
    """Create a new conversation."""
    resolved_account_id = _resolve_account_id(account_id)
    client = TurumbaClient(gateway_url=gateway_url)

    data: dict = {"account_id": resolved_account_id}
    if channel_id is not None:
        data["channel_id"] = channel_id
    if chat_endpoint_id is not None:
        data["chat_endpoint_id"] = chat_endpoint_id
    if contact_id is not None:
        data["contact_id"] = contact_id
    if assignee_id is not None:
        data["assignee_id"] = assignee_id
    if team_id is not None:
        data["team_id"] = team_id
    if status != "open":
        data["status"] = status
    if priority != "medium":
        data["priority"] = priority
    if subject is not None:
        data["subject"] = subject
    if source is not None:
        data["source"] = source
    if metadata is not None:
        data["metadata"] = json.loads(metadata)

    try:
        result = client.create(API_PATH, data)
    except Exception as e:
        _handle_error(e)

    success(f"Conversation created: {result.get('id', '')}")
    render(result, output_format=output, is_list=False, title="Created Conversation")


@app.command("update")
def update_conversation(
    conversation_id: str = typer.Argument(help="Conversation ID"),
    assignee_id: str = typer.Option(None, "--assignee-id", help="Assignee user ID"),
    team_id: str = typer.Option(None, "--team-id", help="Team ID"),
    status: str = typer.Option(
        None, "--status", help="Status: open, assigned, pending, resolved, closed"
    ),
    priority: str = typer.Option(None, "--priority", help="Priority: low, medium, high, urgent"),
    subject: str = typer.Option(None, "--subject", "-s", help="Conversation subject"),
    metadata: str = typer.Option(None, "--metadata", "-m", help="Metadata as JSON string"),
    output: str = typer.Option("table", "--output", "-o", help="Output format: table, json"),
    gateway_url: str = typer.Option(None, "--gateway-url", "-g", help="Gateway URL override"),
) -> None:
    """Update an existing conversation."""
    client = TurumbaClient(gateway_url=gateway_url)

    data: dict = {}
    if assignee_id is not None:
        data["assignee_id"] = assignee_id
    if team_id is not None:
        data["team_id"] = team_id
    if status is not None:
        data["status"] = status
    if priority is not None:
        data["priority"] = priority
    if subject is not None:
        data["subject"] = subject
    if metadata is not None:
        data["metadata"] = json.loads(metadata)

    if not data:
        error("No fields to update. Provide at least one option.")
        raise typer.Exit(1)

    try:
        result = client.update(API_PATH, conversation_id, data)
    except Exception as e:
        _handle_error(e)

    success(f"Conversation updated: {conversation_id}")
    render(result, output_format=output, is_list=False, title="Updated Conversation")


@app.command("delete")
def delete_conversation(
    conversation_id: str = typer.Argument(help="Conversation ID"),
    force: bool = typer.Option(False, "--force", "-y", help="Skip confirmation"),
    gateway_url: str = typer.Option(None, "--gateway-url", "-g", help="Gateway URL override"),
) -> None:
    """Delete a conversation."""
    if not force:
        typer.confirm(f"Delete conversation {conversation_id}?", abort=True)

    client = TurumbaClient(gateway_url=gateway_url)
    try:
        client.delete(API_PATH, conversation_id)
    except Exception as e:
        _handle_error(e)

    success(f"Conversation deleted: {conversation_id}")


# ── Conversation Messages ────────────────────────────────────────────────────


@app.command("list-messages")
def list_messages(
    conversation_id: str = typer.Argument(help="Conversation ID"),
    filter_: list[str] | None = typer.Option(None, "--filter", "-f", help="Filter: field:op:value"),
    sort: list[str] | None = typer.Option(None, "--sort", "-s", help="Sort: field:asc|desc"),
    limit: int = typer.Option(100, "--limit", "-l", help="Max results"),
    skip: int = typer.Option(0, "--skip", help="Offset"),
    output: str = typer.Option("table", "--output", "-o", help="Output format: table, json, csv"),
    gateway_url: str = typer.Option(None, "--gateway-url", "-g", help="Gateway URL override"),
) -> None:
    """List messages in a conversation."""
    client = TurumbaClient(gateway_url=gateway_url)
    try:
        data, meta = client.list(
            f"{API_PATH}/{conversation_id}/messages",
            filter_=filter_,
            sort=sort,
            limit=limit,
            skip=skip,
        )
    except Exception as e:
        _handle_error(e)

    render(data, output_format=output, columns=MESSAGE_COLUMNS, title="Conversation Messages")
    render_meta(meta, output_format=output)


@app.command("send-message")
def send_message(
    conversation_id: str = typer.Argument(help="Conversation ID"),
    message_body: str = typer.Option(..., "--body", "-b", help="Message body text"),
    content_type: str = typer.Option(
        "text", "--content-type", help="Content type: text, image, file, audio, video"
    ),
    is_private: bool = typer.Option(False, "--private", help="Mark as private (internal note)"),
    metadata: str = typer.Option(None, "--metadata", "-m", help="Metadata as JSON string"),
    output: str = typer.Option("table", "--output", "-o", help="Output format: table, json"),
    gateway_url: str = typer.Option(None, "--gateway-url", "-g", help="Gateway URL override"),
) -> None:
    """Send a message in a conversation."""
    client = TurumbaClient(gateway_url=gateway_url)

    data: dict = {"message_body": message_body}
    if content_type != "text":
        data["content_type"] = content_type
    if is_private:
        data["is_private"] = True
    if metadata is not None:
        data["metadata"] = json.loads(metadata)

    try:
        result = client.create(f"{API_PATH}/{conversation_id}/messages", data)
    except Exception as e:
        _handle_error(e)

    success(f"Message sent in conversation {conversation_id}")
    render(result, output_format=output, is_list=False, title="Sent Message")
