"""Webhook integration — send alerts to Slack, Discord, Zapier, n8n, or any URL.

Supports multiple named webhooks. One integration covers all webhook-based services.

Config in ~/.alive/config.json:
    {
        "webhooks": {
            "slack": {"url": "https://hooks.slack.com/...", "type": "slack"},
            "discord": {"url": "https://discord.com/api/webhooks/...", "type": "discord"},
            "custom": {"url": "https://my-server.com/webhook", "type": "generic"}
        }
    }

Usage in skills:

    from alive.integrations.webhook import send_webhook
    send_webhook("Alert: something happened!", webhook_name="slack")
    send_webhook("Data update", data={"key": "value"})
"""

from __future__ import annotations

import json
import logging
from datetime import datetime, timezone
from typing import Any

_log = logging.getLogger("alive")


# ── Config helpers ──────────────────────────────────────────────────────────


def _load_config() -> dict[str, Any]:
    """Load Alive config."""
    from alive.integrations import _load_config as _cfg

    return _cfg()


def _get_webhooks() -> dict[str, dict[str, str]]:
    """Get configured webhooks from config."""
    config = _load_config()
    return config.get("webhooks", {})


# ── Payload formatting ──────────────────────────────────────────────────────


def _format_payload(
    wh_type: str,
    message: str,
    data: dict[str, Any] | None = None,
) -> dict[str, Any]:
    """Format the webhook payload based on platform type.

    Args:
        wh_type: One of "slack", "discord", "generic".
        message: The message text.
        data: Optional extra data to include.

    Returns:
        JSON-serializable payload dict.
    """
    if wh_type == "slack":
        payload: dict[str, Any] = {"text": message}
        if data:
            payload.update(data)
        return payload

    elif wh_type == "discord":
        payload = {"content": message}
        if data:
            payload.update(data)
        return payload

    else:  # generic
        return {
            "message": message,
            "data": data or {},
            "source": "alive-agent",
            "timestamp": datetime.now(timezone.utc).isoformat(),
        }


# ── Public API ──────────────────────────────────────────────────────────────


def send_webhook(
    message: str,
    *,
    webhook_name: str | None = None,
    data: dict[str, Any] | None = None,
) -> bool:
    """Send a message to a configured webhook.

    If webhook_name is None, sends to the first/default webhook.

    Args:
        message: Text message to send.
        webhook_name: Name of the webhook to use (optional).
        data: Extra data to include in the payload (optional).

    Returns:
        True if sent successfully (HTTP 2xx).

    Raises:
        ValueError: If no webhooks are configured or name not found.
    """
    import httpx

    webhooks = _get_webhooks()

    if not webhooks:
        raise ValueError(
            "No webhooks configured. Run: alive setup webhook"
        )

    if webhook_name:
        if webhook_name not in webhooks:
            available = ", ".join(webhooks.keys())
            raise ValueError(
                f"Webhook '{webhook_name}' not found. "
                f"Available: {available}"
            )
        wh = webhooks[webhook_name]
    else:
        # Default to first webhook
        wh = list(webhooks.values())[0]

    wh_type = wh.get("type", "generic")
    url = wh.get("url", "")

    if not url:
        raise ValueError("Webhook URL is empty")

    payload = _format_payload(wh_type, message, data)

    _log.debug("Sending webhook to %s (%s): %s", url[:50], wh_type, message[:100])

    resp = httpx.post(url, json=payload, timeout=10)
    return resp.status_code < 300


def list_webhooks() -> list[dict[str, str]]:
    """List all configured webhooks with their status.

    Returns:
        List of dicts with keys: name, type, url (masked).
    """
    webhooks = _get_webhooks()
    result = []
    for name, wh in webhooks.items():
        url = wh.get("url", "")
        # Mask the URL for display (show first 30 chars + ...)
        masked_url = url[:30] + "..." if len(url) > 30 else url
        result.append({
            "name": name,
            "type": wh.get("type", "generic"),
            "url": masked_url,
        })
    return result


# ── Setup wizard ───────────────────────────────────────────────────────────


_PLATFORM_TYPES = {
    "slack": "slack",
    "discord": "discord",
    "zapier": "generic",
    "n8n": "generic",
    "custom": "generic",
}


def setup_webhook(console=None) -> bool:
    """Interactive setup wizard for webhook integration.

    Returns True if at least one webhook was configured.
    """
    import httpx
    from rich.console import Console
    from rich.panel import Panel
    from rich.prompt import Prompt

    from alive.integrations import _load_config as _cfg, _save_config

    con = console or Console()

    while True:
        con.print(Panel(
            "[bold]Configure a webhook for alerts[/]\n\n"
            "Supported platforms:\n"
            "• Slack (incoming webhooks)\n"
            "• Discord (channel webhooks)\n"
            "• Zapier, n8n, Make.com\n"
            "• Any custom URL",
            title="[bold cyan]Webhook Setup[/]",
            border_style="cyan",
            padding=(1, 2),
        ))

        # Platform
        con.print()
        platform = Prompt.ask(
            "[bold]What platform?[/]",
            choices=["slack", "discord", "zapier", "n8n", "custom"],
            default="slack",
            console=con,
        )

        # URL
        con.print()
        url = Prompt.ask("[bold]Paste the webhook URL[/]", console=con)
        url = url.strip()
        if not url:
            con.print("[red]No URL provided.[/]")
            continue

        # Name
        con.print()
        default_name = platform
        name = Prompt.ask(
            "[bold]Give it a name[/]",
            default=default_name,
            console=con,
        )
        name = name.strip().lower().replace(" ", "-")

        # Test the webhook
        con.print()
        wh_type = _PLATFORM_TYPES.get(platform, "generic")
        payload = _format_payload(wh_type, "🎉 Alive webhook connected!")

        with con.status("[bold cyan]Sending test message...", spinner="dots"):
            try:
                resp = httpx.post(url, json=payload, timeout=10)
                test_ok = resp.status_code < 300
            except Exception as e:
                _log.debug("Webhook test failed: %s", e)
                test_ok = False

        if test_ok:
            con.print(f"[green]✓ Webhook '{name}' configured and tested![/]")
        else:
            con.print(f"[yellow]⚠ Test message may have failed, but config will be saved.[/]")

        # Save
        cfg = _cfg()
        if "webhooks" not in cfg:
            cfg["webhooks"] = {}
        cfg["webhooks"][name] = {"url": url, "type": wh_type}
        _save_config(cfg)

        # Add another?
        con.print()
        another = Prompt.ask(
            "[bold]Add another webhook?[/]",
            choices=["y", "n"],
            default="n",
            console=con,
        )
        if another.lower() != "y":
            break

    con.print(Panel(
        "[bold green]Webhooks configured![/]\n\n"
        "[dim]Skills can now:[/]\n"
        "  from alive.integrations.webhook import send_webhook\n"
        f"  send_webhook('Alert!', webhook_name='{name}')\n\n"
        "[dim]List webhooks:[/] alive webhooks",
        title="[bold green]Setup Complete[/]",
        border_style="green",
        padding=(1, 2),
    ))
    return True


def display_webhooks(console=None) -> None:
    """Display configured webhooks as a rich panel."""
    from rich.console import Console
    from rich.panel import Panel

    con = console or Console()
    webhooks = list_webhooks()

    if not webhooks:
        con.print(Panel(
            "[dim]No webhooks configured.[/]\n\n"
            "[dim]Set one up:[/] alive setup webhook",
            title="[bold]Webhooks[/]",
            border_style="yellow",
        ))
        return

    lines = []
    for wh in webhooks:
        type_label = wh["type"].title()
        lines.append(f"[bold green]{wh['name']}[/]   — {type_label}   — [dim]{wh['url']}[/]")

    con.print(Panel(
        "\n".join(lines),
        title="[bold cyan]Configured Webhooks[/]",
        border_style="cyan",
        padding=(1, 2),
    ))


def test_webhook(webhook_name: str | None = None, console=None) -> bool:
    """Send a test message to a webhook. Returns True on success."""
    from rich.console import Console

    con = console or Console()
    con.print("[bold cyan]Testing webhook...[/]\n")

    try:
        result = send_webhook(
            "🧪 Test message from Alive — webhook integration working!",
            webhook_name=webhook_name,
        )
        if result:
            label = f" ({webhook_name})" if webhook_name else ""
            con.print(f"[bold green]✓ Webhook test passed!{label}[/]")
            return True
        else:
            con.print("[bold red]✗ Webhook returned non-success status.[/]")
            return False
    except ValueError as e:
        con.print(f"[bold red]✗ {e}[/]")
        return False
    except Exception as e:
        con.print(f"[bold red]✗ Failed: {e}[/]")
        return False
