from __future__ import annotations

from pathlib import Path

import service_dashboard as sd


def write_fixture(tmp_path: Path) -> tuple[Path, Path]:
    env = tmp_path / ".env"
    env.write_text(
        "\n".join(
            [
                "NODE=http://node",
                "ROOT=/tmp/invoices",
                "PORT=8100",
                "URL=http://node:8100",
                "HOST=0.0.0.0",
            ]
        ),
        encoding="utf-8",
    )
    services = tmp_path / "services.yaml"
    services.write_text(
        """
version: urirun.services.v1
services:
  - id: invoice-panel
    label: Invoice panel
    aliases: [panel, faktury]
    node_url: ${NODE}
    public_url: ${URL}
    actions:
      status:
        uri: panel://host/php/query/status
        payload:
          root: "${ROOT}"
          port: "${PORT}"
      start:
        uri: panel://host/php/command/start
        payload:
          root: "${ROOT}"
          host: "${HOST}"
          port: "${PORT}"
      stop:
        uri: panel://host/php/command/stop
        payload:
          root: "${ROOT}"
          port: "${PORT}"
""",
        encoding="utf-8",
    )
    return services, env


class FakeTransport:
    def __init__(self) -> None:
        self.calls: list[tuple[str, str, dict, float]] = []

    def __call__(self, node_url: str, uri: str, payload: dict, timeout: float) -> dict:
        self.calls.append((node_url, uri, payload, timeout))
        if uri.endswith("/status"):
            return {"ok": True, "result": {"value": {"ok": True, "running": True, "portOpen": True, "url": "http://node:8100", "port": payload["port"]}}}
        if uri.endswith("/start"):
            return {"ok": True, "result": {"value": {"ok": True, "running": True, "portOpen": True, "started": True, "url": "http://node:8100"}}}
        if uri.endswith("/stop"):
            return {"ok": True, "result": {"value": {"ok": True, "stopped": True, "running": False}}}
        raise AssertionError(uri)


def test_load_services_expands_env_and_coerces_port(tmp_path: Path) -> None:
    services, env = write_fixture(tmp_path)
    catalog = sd.load_services(services, env)
    payload = catalog["services"][0]["actions"]["status"]["payload"]
    assert payload["root"] == "/tmp/invoices"
    assert payload["port"] == 8100


def test_chat_prompt_starts_registered_panel(tmp_path: Path) -> None:
    services, env = write_fixture(tmp_path)
    catalog = sd.load_services(services, env)
    fake = FakeTransport()
    result = sd.handle_prompt("uruchom panel faktur", catalog, transport=fake)
    assert result["ok"] is True
    assert result["action"] == "start"
    assert fake.calls[0][1] == "panel://host/php/command/start"
    assert fake.calls[0][2]["port"] == 8100


def test_chat_prompt_checks_status_without_start(tmp_path: Path) -> None:
    services, env = write_fixture(tmp_path)
    catalog = sd.load_services(services, env)
    fake = FakeTransport()
    result = sd.handle_prompt("czy działa panel?", catalog, transport=fake)
    assert result["action"] == "status"
    assert result["status"]["running"] is True
    assert len(fake.calls) == 1


def test_stop_runs_stop_then_status(tmp_path: Path) -> None:
    services, env = write_fixture(tmp_path)
    catalog = sd.load_services(services, env)
    fake = FakeTransport()
    result = sd.call_action(catalog["services"][0], "stop", transport=fake)
    assert result["ok"] is True
    assert [call[1] for call in fake.calls] == [
        "panel://host/php/command/stop",
        "panel://host/php/query/status",
    ]


def test_markdown_is_chat_friendly() -> None:
    text = sd.format_markdown(
        {
            "ok": True,
            "action": "status",
            "service": {"id": "invoice-panel", "label": "Invoice panel", "public_url": "http://node:8100"},
            "status": {"ok": True, "running": True, "portOpen": True, "url": "http://node:8100"},
        }
    )
    assert "OK:" in text
    assert "running" in text
    assert "http://node:8100" in text
