"""Tests for kernel/notebook tools."""

from unittest.mock import MagicMock, patch

import pytest

from tests.conftest import MockMCP


@pytest.fixture
def mcp():
    m = MockMCP()
    from kaggle_mcp import kernels
    kernels.register(m)
    return m


# ---------------------------------------------------------------------------
# kernels_list
# ---------------------------------------------------------------------------

def test_kernels_list_returns_formatted(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        k = MagicMock()
        k.title = "EDA Notebook"
        k.ref = "user/eda-notebook"
        k.total_votes = 42
        k.language = "python"
        mock_gc.return_value.kernels.kernels_api_client.list_kernels.return_value.kernels = [k]

        result = mcp.tools["kernels_list"]()
        assert "EDA Notebook" in result
        assert "user/eda-notebook" in result


def test_kernels_list_empty(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        mock_gc.return_value.kernels.kernels_api_client.list_kernels.return_value.kernels = []
        result = mcp.tools["kernels_list"]()
        assert result == "No kernels found."


# ---------------------------------------------------------------------------
# kernel_pull
# ---------------------------------------------------------------------------

def test_kernel_pull_returns_source(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        resp = MagicMock()
        resp.metadata.to_dict.return_value = {"language": "python"}
        resp.blob.source = "print('hello')"
        mock_gc.return_value.kernels.kernels_api_client.get_kernel.return_value = resp

        result = mcp.tools["kernel_pull"]("user", "my-kernel")
        assert "print('hello')" in result


# ---------------------------------------------------------------------------
# kernel_push
# ---------------------------------------------------------------------------

def test_kernel_push(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        resp = MagicMock()
        resp.to_dict.return_value = {"ref": "user/new-kernel", "status": "ok"}
        mock_gc.return_value.kernels.kernels_api_client.save_kernel.return_value = resp

        result = mcp.tools["kernel_push"]("New Kernel", "print('hi')")
        assert "new-kernel" in result or "ok" in result


# ---------------------------------------------------------------------------
# kernel_output
# ---------------------------------------------------------------------------

def test_kernel_output_returns_url(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        resp = MagicMock()
        resp.url = "https://example.com/output.zip"
        mock_gc.return_value.kernels.kernels_api_client.download_kernel_output.return_value = resp

        result = mcp.tools["kernel_output"]("user", "my-kernel")
        assert "https://example.com/output.zip" in result


def test_kernel_output_error(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        mock_gc.return_value.kernels.kernels_api_client.download_kernel_output.side_effect = Exception("not found")
        result = mcp.tools["kernel_output"]("user", "bad-kernel")
        assert "Error" in result


# ---------------------------------------------------------------------------
# kernel_session_create
# ---------------------------------------------------------------------------

def test_kernel_session_create(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        resp = MagicMock()
        resp.to_dict.return_value = {"session_id": "sess_001", "status": "running"}
        mock_gc.return_value.kernels.kernels_api_client.create_kernel_session.return_value = resp

        result = mcp.tools["kernel_session_create"]("user", "my-kernel")
        assert "sess_001" in result or "running" in result


# ---------------------------------------------------------------------------
# kernel_session_status
# ---------------------------------------------------------------------------

def test_kernel_session_status_running(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        resp = MagicMock()
        resp.status.name = "RUNNING"
        resp.failure_message = None
        mock_gc.return_value.kernels.kernels_api_client.get_kernel_session_status.return_value = resp

        result = mcp.tools["kernel_session_status"]("user", "my-kernel")
        assert "RUNNING" in result


def test_kernel_session_status_failed(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        resp = MagicMock()
        resp.status.name = "ERROR"
        resp.failure_message = "OOM killed"
        mock_gc.return_value.kernels.kernels_api_client.get_kernel_session_status.return_value = resp

        result = mcp.tools["kernel_session_status"]("user", "my-kernel")
        assert "ERROR" in result
        assert "OOM killed" in result


# ---------------------------------------------------------------------------
# kernel_session_output
# ---------------------------------------------------------------------------

def test_kernel_session_output_returns_files(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        f = MagicMock()
        f.file_name = "submission.csv"
        f.url = "https://example.com/submission.csv"
        resp = MagicMock()
        resp.files = [f]
        mock_gc.return_value.kernels.kernels_api_client.list_kernel_session_output.return_value = resp

        result = mcp.tools["kernel_session_output"]("user", "my-kernel")
        assert "submission.csv" in result


def test_kernel_session_output_empty(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        resp = MagicMock()
        resp.files = []
        mock_gc.return_value.kernels.kernels_api_client.list_kernel_session_output.return_value = resp

        result = mcp.tools["kernel_session_output"]("user", "my-kernel")
        assert "No output files found." in result


# ---------------------------------------------------------------------------
# kernel_session_cancel
# ---------------------------------------------------------------------------

def test_kernel_session_cancel_success(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        status_resp = MagicMock()
        status_resp.kernel_session_id = 777
        cancel_resp = MagicMock()
        cancel_resp.error_message = None
        client = mock_gc.return_value
        client.kernels.kernels_api_client.get_kernel_session_status.return_value = status_resp
        client.kernels.kernels_api_client.cancel_kernel_session.return_value = cancel_resp

        result = mcp.tools["kernel_session_cancel"]("user", "my-kernel")
        assert "cancelled" in result.lower()


def test_kernel_session_cancel_error(mcp):
    with patch("kaggle_mcp.kernels.get_client") as mock_gc:
        mock_gc.return_value.kernels.kernels_api_client.get_kernel_session_status.side_effect = Exception("timeout")
        result = mcp.tools["kernel_session_cancel"]("user", "my-kernel")
        assert "Error" in result
