"""Channels commands — CRUD + test-connection. Reference implementation for other resources."""

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="channels", help="Manage delivery channels (SMS, Telegram, WhatsApp, etc.).")

API_PATH = "/v1/channels"

LIST_COLUMNS = {
    "ID": "id",
    "Name": "name",
    "Type": "channel_type",
    "Status": "status",
    "Enabled": "is_enabled",
    "Sender": "sender_name",
    "Priority": "priority",
}


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_channels(
    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 delivery channels."""
    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="Channels")
    render_meta(meta, output_format=output)


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

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


@app.command("create")
def create_channel(
    name: str = typer.Option(..., "--name", "-n", help="Channel name"),
    channel_type: str = typer.Option(
        ..., "--type", "-t", help="Channel type: sms, smpp, telegram, whatsapp, messenger, email"
    ),
    credentials: str = typer.Option(
        None, "--credentials", help="Channel credentials as JSON string"
    ),
    sender_name: str = typer.Option(None, "--sender-name", help="Sender display name"),
    default_country_code: str = typer.Option(None, "--country-code", help="Default country code"),
    rate_limit: int = typer.Option(None, "--rate-limit", help="Messages per second limit"),
    priority: int = typer.Option(0, "--priority", help="Channel priority (higher = preferred)"),
    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 delivery channel."""
    client = TurumbaClient(gateway_url=gateway_url)

    data: dict = {
        "name": name,
        "channel_type": channel_type,
        "priority": priority,
    }
    if credentials:
        data["credentials"] = json.loads(credentials)
    if sender_name:
        data["sender_name"] = sender_name
    if default_country_code:
        data["default_country_code"] = default_country_code
    if rate_limit is not None:
        data["rate_limit"] = rate_limit

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

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


@app.command("update")
def update_channel(
    channel_id: str = typer.Argument(help="Channel ID"),
    name: str = typer.Option(None, "--name", "-n", help="Channel name"),
    credentials: str = typer.Option(
        None, "--credentials", help="Channel credentials as JSON string"
    ),
    sender_name: str = typer.Option(None, "--sender-name", help="Sender display name"),
    is_enabled: bool = typer.Option(None, "--enabled/--disabled", help="Enable or disable channel"),
    rate_limit: int = typer.Option(None, "--rate-limit", help="Messages per second limit"),
    priority: int = typer.Option(None, "--priority", help="Channel priority"),
    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 channel."""
    client = TurumbaClient(gateway_url=gateway_url)

    data: dict = {}
    if name is not None:
        data["name"] = name
    if credentials is not None:
        data["credentials"] = json.loads(credentials)
    if sender_name is not None:
        data["sender_name"] = sender_name
    if is_enabled is not None:
        data["is_enabled"] = is_enabled
    if rate_limit is not None:
        data["rate_limit"] = rate_limit
    if priority is not None:
        data["priority"] = priority

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

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

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


@app.command("delete")
def delete_channel(
    channel_id: str = typer.Argument(help="Channel 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 channel."""
    if not force:
        typer.confirm(f"Delete channel {channel_id}?", abort=True)

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

    success(f"Channel deleted: {channel_id}")


@app.command("test-connection")
def test_connection(
    channel_id: str = typer.Option(None, "--id", help="Test an existing channel by ID"),
    channel_type: str = typer.Option(
        None, "--type", "-t", help="Channel type for new credentials test"
    ),
    credentials: str = typer.Option(None, "--credentials", help="Credentials JSON for new test"),
    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:
    """Test a channel's connection to its provider."""
    if not channel_id and not (channel_type and credentials):
        error("Provide --id for existing channel, or --type and --credentials for new test.")
        raise typer.Exit(1)

    client = TurumbaClient(gateway_url=gateway_url)

    try:
        if channel_id:
            result = client.post(f"{API_PATH}/{channel_id}/test-connection")
        else:
            data = {
                "channel_type": channel_type,
                "credentials": json.loads(credentials),
            }
            result = client.post(f"{API_PATH}/test-connection", data=data)
    except Exception as e:
        _handle_error(e)

    if isinstance(result, dict) and result.get("data"):
        result = result["data"]

    render(result, output_format=output, is_list=False, title="Connection Test Result")
