"""Tests for the Google Sheets OAuth-backed tool."""

# ruff: noqa: D103

from __future__ import annotations

import json
from typing import TYPE_CHECKING

import pytest

from mindroom import constants
from mindroom import tools as _mindroom_tools  # noqa: F401  # registers built-in tool metadata
from mindroom.credentials import CredentialsManager
from mindroom.custom_tools.google_sheets import GoogleSheetsTools
from mindroom.oauth.google_sheets import google_sheets_oauth_provider
from mindroom.oauth.providers import OAuthConnectionRequired
from mindroom.tool_system.metadata import get_tool_by_name
from mindroom.tool_system.worker_routing import ResolvedWorkerTarget, ToolExecutionIdentity, resolve_worker_target

if TYPE_CHECKING:
    from pathlib import Path


def _runtime_paths(tmp_path: Path, extra_env: dict[str, str] | None = None) -> constants.RuntimePaths:
    return constants.resolve_runtime_paths(
        storage_path=tmp_path / "mindroom_data",
        process_env={
            "MINDROOM_PUBLIC_URL": "https://mindroom.example.test",
            **(extra_env or {}),
        },
    )


def _worker_target() -> ResolvedWorkerTarget:
    identity = ToolExecutionIdentity(
        channel="matrix",
        agent_name="general",
        requester_id="@alice:example.org",
        room_id="!room:example.org",
        thread_id=None,
        resolved_thread_id=None,
        session_id=None,
    )
    return resolve_worker_target("user_agent", "general", execution_identity=identity)


def test_google_sheets_missing_credentials_raises_structured_connect_instruction(tmp_path: Path) -> None:
    tool = GoogleSheetsTools(
        runtime_paths=_runtime_paths(tmp_path),
        credentials_manager=CredentialsManager(tmp_path / "credentials"),
        worker_target=_worker_target(),
    )

    with pytest.raises(OAuthConnectionRequired) as exc_info:
        tool._auth()

    assert exc_info.value.provider_id == "google_sheets"
    assert exc_info.value.connect_url is not None
    assert "/api/oauth/google_sheets/authorize?connect_token=" in exc_info.value.connect_url
    assert "@alice:example.org" not in str(exc_info.value)


def test_google_sheets_public_method_returns_structured_connect_instruction(tmp_path: Path) -> None:
    tool = GoogleSheetsTools(
        runtime_paths=_runtime_paths(tmp_path),
        credentials_manager=CredentialsManager(tmp_path / "credentials"),
        worker_target=_worker_target(),
    )

    result = json.loads(tool.read_sheet(spreadsheet_id="sheet-id", spreadsheet_range="A1:B2"))

    assert result["oauth_connection_required"] is True
    assert result["provider"] == "google_sheets"
    assert "/api/oauth/google_sheets/authorize?connect_token=" in result["connect_url"]

    writable_tool = GoogleSheetsTools(
        runtime_paths=_runtime_paths(tmp_path),
        credentials_manager=CredentialsManager(tmp_path / "credentials"),
        worker_target=_worker_target(),
        create=True,
        update=True,
    )
    result = json.loads(writable_tool.create_sheet("Budget"))

    assert result["oauth_connection_required"] is True
    assert result["provider"] == "google_sheets"
    assert "/api/oauth/google_sheets/authorize?connect_token=" in result["connect_url"]


def test_google_sheets_loads_tokens_from_oauth_service(tmp_path: Path) -> None:
    credentials_manager = CredentialsManager(tmp_path / "credentials")
    credentials_manager.save_credentials("google_sheets", {"spreadsheet_id": "sheet-id", "_source": "ui"})
    credentials_manager.save_credentials(
        "google_sheets_oauth",
        {"token": "access-token", "refresh_token": "refresh-token", "_source": "oauth"},
    )
    tool = GoogleSheetsTools(
        runtime_paths=_runtime_paths(tmp_path),
        credentials_manager=credentials_manager,
        worker_target=None,
    )

    token_data = tool._load_token_data()

    assert token_data is not None
    assert token_data["token"] == "access-token"  # noqa: S105
    assert "spreadsheet_id" not in token_data


def test_google_sheets_saved_dashboard_config_maps_to_upstream_init_args(tmp_path: Path) -> None:
    credentials_manager = CredentialsManager(tmp_path / "credentials")
    credentials_manager.save_credentials(
        "google_sheets",
        {
            "read": False,
            "create": True,
            "update": True,
            "_source": "ui",
        },
    )

    tool = get_tool_by_name(
        "google_sheets",
        _runtime_paths(tmp_path),
        credentials_manager=credentials_manager,
        worker_target=None,
        disable_sandbox_proxy=True,
    )

    assert isinstance(tool, GoogleSheetsTools)
    assert [registered.__name__ for registered in tool.tools] == [
        "create_sheet",
        "update_sheet",
    ]


def test_google_sheets_default_config_enables_read_and_write_methods(tmp_path: Path) -> None:
    tool = get_tool_by_name(
        "google_sheets",
        _runtime_paths(tmp_path),
        credentials_manager=CredentialsManager(tmp_path / "credentials"),
        worker_target=None,
        disable_sandbox_proxy=True,
    )

    assert isinstance(tool, GoogleSheetsTools)
    assert {registered.__name__ for registered in tool.tools} == {
        "read_sheet",
        "create_sheet",
        "update_sheet",
    }


def test_google_sheets_provider_uses_sheets_scope_without_drive_scope() -> None:
    provider = google_sheets_oauth_provider()

    assert "https://www.googleapis.com/auth/spreadsheets" in provider.scopes
    assert "https://www.googleapis.com/auth/drive.file" not in provider.scopes
    assert "https://www.googleapis.com/auth/drive" not in provider.scopes


def test_google_sheets_service_account_env_uses_upstream_auth(tmp_path: Path) -> None:
    tool = GoogleSheetsTools(
        runtime_paths=_runtime_paths(
            tmp_path,
            {"GOOGLE_SERVICE_ACCOUNT_FILE": str(tmp_path / "service-account.json")},
        ),
        credentials_manager=CredentialsManager(tmp_path / "credentials"),
        worker_target=None,
    )

    assert tool._should_fallback_to_original_auth() is True
