"""SSH task runner service definition.

An ``ssh_tasks`` instance is an SSH endpoint that can run reusable saved tasks.
Tasks themselves stay in the global saved-task registry; the instance only owns
transport (host/port/user/key). Every run is recorded in ``service_task_runs``
and shown as history on the instance's service page.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from media_library_viewer_api.integrations.base import (
    SecretField,
    ServiceConfigBase,
    ServiceDefinition,
    TestResult,
    WidgetConfigBase,
    translate_connection_error,
    widget_kind,
)

if TYPE_CHECKING:
    from media_library_viewer_api.services.settings_store import SettingsStore


def test_connection(
    config: dict[str, Any],
    secrets: dict[str, str],
    store: SettingsStore,
) -> TestResult:
    """Build an SSH client via build_ssh_client and attempt .connect().

    Reuses the same error-translation patterns as test_machine_ssh (banner,
    auth failed). Known-host recording is preserved.
    """
    from media_library_viewer_api.services.task_runner import build_ssh_client
    from media_library_viewer_api.widgets.sources import ServiceRecord

    host = str(config.get("host") or "").strip()
    port = int(config.get("port") or 22)
    try:
        service = ServiceRecord(
            id="",
            service_type="ssh_tasks",
            name="test",
            config=config,
            secrets=secrets,
            enabled=True,
        )
        client = build_ssh_client(store, service)
        try:
            client.connect()
        except Exception as exc:
            lowered = str(exc).lower()
            if "protocol banner" in lowered:
                return TestResult(
                    ok=False,
                    detail=f"SSH banner not received from {host}:{port}; confirm the SSH service is running.",
                )
            if "no authentication methods available" in lowered or "authentication failed" in lowered:
                return TestResult(
                    ok=False,
                    detail=f"SSH authentication failed for {host}:{port}; check the SSH key, passphrase, or username.",
                )
            return translate_connection_error(exc, context=f"SSH {host}:{port}")
        finally:
            client.close()
        return TestResult(
            ok=True,
            detail=f"SSH connection succeeded for {host}:{port}.",
            evidence=f"Connected to {host}:{port}",
        )
    except ValueError as exc:
        return TestResult(ok=False, detail=str(exc))
    except Exception as exc:
        return translate_connection_error(exc, context=f"SSH {host}:{port}")


class SshTasksConfig(ServiceConfigBase):
    """Non-secret SSH task runner config.

    The SSH key itself lives in the saved SSH-key registry and is referenced by
    ``ssh_key_id``. An optional ``passphrase`` is stored as a secret.
    """

    host: str
    port: int = 22
    username: str = ""
    ssh_key_id: str = ""
    timeout_seconds: int = 30


class SshTaskOutputWidgetConfig(WidgetConfigBase):
    """Output of a saved task run on this instance."""

    task_id: str
    # service_id is implicit (the widget's service); allow overriding per-widget.
    service_id: str | None = None


DEFINITION = ServiceDefinition(
    service_type="ssh_tasks",
    name="SSH task runner",
    description="Run reusable saved tasks over SSH and keep run history.",
    config_model=SshTasksConfig,
    secret_fields=[
        SecretField(key="passphrase", label="Key passphrase", helper="Optional"),
    ],
    widget_kinds=[
        widget_kind(
            kind="task_output",
            name="Task output",
            description="Output of a saved task run.",
            model_cls=SshTaskOutputWidgetConfig,
            default_config={"task_id": ""},
            refresh_interval_ms=0,
        ),
    ],
    test_callable=test_connection,
)
