"""Conversation config commands — CRUD for conversation routing rules."""

from __future__ import annotations

import json

import typer

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

app = typer.Typer(name="conversation-configs", help="Manage conversation configuration rules.")

API_PATH = "/v1/conversation-configs"

LIST_COLUMNS = {
    "ID": "id",
    "Name": "name",
    "Active": "is_active",
    "Priority": "priority",
    "Audience": "audience_mode",
    "Creation": "creation_mode",
    "Reopen": "reopen_policy",
    "Created": "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)


@app.command("list")
def list_conversation_configs(
    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 conversation configs."""
    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="Conversation Configs")
    render_meta(meta, output_format=output)


@app.command("get")
def get_conversation_config(
    config_id: str = typer.Argument(help="Conversation config 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 config."""
    client = TurumbaClient(gateway_url=gateway_url)
    try:
        data = client.get(API_PATH, config_id)
    except Exception as e:
        _handle_error(e)

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


@app.command("create")
def create_conversation_config(
    name: str = typer.Option(..., "--name", "-n", help="Config name"),
    description: str = typer.Option(None, "--description", "-d", help="Description"),
    is_active: bool = typer.Option(True, "--active/--inactive", help="Enable or disable config"),
    priority: int = typer.Option(0, "--priority", "-p", help="Priority (higher = matched first)"),
    audience_mode: str = typer.Option(
        "all",
        "--audience-mode",
        help="Audience mode: all, known_only, groups, allowlist",
    ),
    audience_group_ids: str = typer.Option(
        None, "--audience-group-ids", help="Group IDs as JSON array (required for groups mode)"
    ),
    audience_contact_ids: str = typer.Option(
        None,
        "--audience-contact-ids",
        help="Contact IDs as JSON array (required for allowlist mode)",
    ),
    source_channels: str = typer.Option(
        None, "--source-channels", help="Source channel types as JSON array"
    ),
    source_channel_ids: str = typer.Option(
        None, "--source-channel-ids", help="Source channel IDs as JSON array"
    ),
    creation_mode: str = typer.Option(
        "always", "--creation-mode", help="Creation mode: always, first_only, manual"
    ),
    reopen_policy: str = typer.Option(
        "new", "--reopen-policy", help="Reopen policy: new, reopen, threshold"
    ),
    reopen_window_minutes: int = typer.Option(
        None, "--reopen-window", help="Reopen window in minutes (required for reopen policy)"
    ),
    reopen_threshold_hours: int = typer.Option(
        None, "--reopen-threshold", help="Reopen threshold in hours (required for threshold policy)"
    ),
    default_team_id: str = typer.Option(None, "--default-team-id", help="Default team ID"),
    default_assignee_id: str = typer.Option(
        None, "--default-assignee-id", help="Default assignee user ID"
    ),
    auto_resolve_hours: int = typer.Option(
        None, "--auto-resolve-hours", help="Auto-resolve after N hours of inactivity"
    ),
    metadata: str = typer.Option(None, "--metadata", help="Custom metadata as JSON"),
    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 config."""
    client = TurumbaClient(gateway_url=gateway_url)

    data: dict = {
        "name": name,
        "is_active": is_active,
        "priority": priority,
        "audience_mode": audience_mode,
        "creation_mode": creation_mode,
        "reopen_policy": reopen_policy,
    }
    if description:
        data["description"] = description
    if audience_group_ids:
        data["audience_group_ids"] = json.loads(audience_group_ids)
    if audience_contact_ids:
        data["audience_contact_ids"] = json.loads(audience_contact_ids)
    if source_channels:
        data["source_channels"] = json.loads(source_channels)
    if source_channel_ids:
        data["source_channel_ids"] = json.loads(source_channel_ids)
    if reopen_window_minutes is not None:
        data["reopen_window_minutes"] = reopen_window_minutes
    if reopen_threshold_hours is not None:
        data["reopen_threshold_hours"] = reopen_threshold_hours
    if default_team_id:
        data["default_team_id"] = default_team_id
    if default_assignee_id:
        data["default_assignee_id"] = default_assignee_id
    if auto_resolve_hours is not None:
        data["auto_resolve_hours"] = auto_resolve_hours
    if metadata:
        data["metadata"] = json.loads(metadata)

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

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


@app.command("update")
def update_conversation_config(  # noqa: PLR0912
    config_id: str = typer.Argument(help="Conversation config ID"),
    name: str = typer.Option(None, "--name", "-n", help="Config name"),
    description: str = typer.Option(None, "--description", "-d", help="Description"),
    is_active: bool = typer.Option(None, "--active/--inactive", help="Enable or disable config"),
    priority: int = typer.Option(None, "--priority", "-p", help="Priority"),
    audience_mode: str = typer.Option(None, "--audience-mode", help="Audience mode"),
    audience_group_ids: str = typer.Option(
        None, "--audience-group-ids", help="Group IDs as JSON array"
    ),
    audience_contact_ids: str = typer.Option(
        None, "--audience-contact-ids", help="Contact IDs as JSON array"
    ),
    source_channels: str = typer.Option(
        None, "--source-channels", help="Source channel types as JSON array"
    ),
    source_channel_ids: str = typer.Option(
        None, "--source-channel-ids", help="Source channel IDs as JSON array"
    ),
    creation_mode: str = typer.Option(None, "--creation-mode", help="Creation mode"),
    reopen_policy: str = typer.Option(None, "--reopen-policy", help="Reopen policy"),
    reopen_window_minutes: int = typer.Option(None, "--reopen-window", help="Reopen window mins"),
    reopen_threshold_hours: int = typer.Option(
        None, "--reopen-threshold", help="Reopen threshold hrs"
    ),
    default_team_id: str = typer.Option(None, "--default-team-id", help="Default team ID"),
    default_assignee_id: str = typer.Option(
        None, "--default-assignee-id", help="Default assignee ID"
    ),
    auto_resolve_hours: int = typer.Option(None, "--auto-resolve-hours", help="Auto-resolve hours"),
    metadata: str = typer.Option(None, "--metadata", help="Custom metadata as JSON"),
    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 config."""
    client = TurumbaClient(gateway_url=gateway_url)

    data: dict = {}
    if name is not None:
        data["name"] = name
    if description is not None:
        data["description"] = description
    if is_active is not None:
        data["is_active"] = is_active
    if priority is not None:
        data["priority"] = priority
    if audience_mode is not None:
        data["audience_mode"] = audience_mode
    if audience_group_ids is not None:
        data["audience_group_ids"] = json.loads(audience_group_ids)
    if audience_contact_ids is not None:
        data["audience_contact_ids"] = json.loads(audience_contact_ids)
    if source_channels is not None:
        data["source_channels"] = json.loads(source_channels)
    if source_channel_ids is not None:
        data["source_channel_ids"] = json.loads(source_channel_ids)
    if creation_mode is not None:
        data["creation_mode"] = creation_mode
    if reopen_policy is not None:
        data["reopen_policy"] = reopen_policy
    if reopen_window_minutes is not None:
        data["reopen_window_minutes"] = reopen_window_minutes
    if reopen_threshold_hours is not None:
        data["reopen_threshold_hours"] = reopen_threshold_hours
    if default_team_id is not None:
        data["default_team_id"] = default_team_id
    if default_assignee_id is not None:
        data["default_assignee_id"] = default_assignee_id
    if auto_resolve_hours is not None:
        data["auto_resolve_hours"] = auto_resolve_hours
    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, config_id, data)
    except Exception as e:
        _handle_error(e)

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


@app.command("delete")
def delete_conversation_config(
    config_id: str = typer.Argument(help="Conversation config 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 config."""
    if not force:
        typer.confirm(f"Delete conversation config {config_id}?", abort=True)

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

    success(f"Conversation config deleted: {config_id}")


@app.command("evaluate")
def evaluate_conversation_config(
    source_channel_type: str = typer.Option(
        ..., "--channel-type", help="Source channel type (e.g., telegram, sms)"
    ),
    source_channel_id: str = typer.Option(..., "--channel-id", help="Source channel ID"),
    contact_id: str = typer.Option(None, "--contact-id", help="Contact ID"),
    is_known_contact: bool = typer.Option(False, "--known/--unknown", help="Known contact flag"),
    contact_group_ids: str = typer.Option(
        None, "--contact-group-ids", help="Contact group IDs as JSON array"
    ),
    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:
    """Evaluate which conversation config matches for an inbound message context."""
    client = TurumbaClient(gateway_url=gateway_url)

    data: dict = {
        "source_channel_type": source_channel_type,
        "source_channel_id": source_channel_id,
        "is_known_contact": is_known_contact,
    }
    if contact_id:
        data["contact_id"] = contact_id
    if contact_group_ids:
        data["contact_group_ids"] = json.loads(contact_group_ids)

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

    render(result, output_format=output, is_list=False, title="Config Evaluation Result")
