import os
import sys
from contextlib import contextmanager
from pathlib import Path

import pytest
import typer

CLI_ROOT = Path(__file__).resolve().parents[1]
if str(CLI_ROOT) not in sys.path:
    sys.path.insert(0, str(CLI_ROOT))

import api_client
import auth
import main


@contextmanager
def _no_spinner(*_args, **_kwargs):
    yield None


def test_is_authenticated_accepts_env_api_key(monkeypatch: pytest.MonkeyPatch):
    monkeypatch.setenv("NIA_API_KEY", "test-api-key")
    monkeypatch.setattr(auth, "load_config", lambda: {})

    assert auth.is_authenticated() is True


def test_get_sources_result_preserves_api_error(monkeypatch: pytest.MonkeyPatch):
    monkeypatch.setattr(
        api_client,
        "request_json",
        lambda *_args, **_kwargs: (None, "Authentication failed"),
    )

    sources, error = api_client.get_sources_result()

    assert sources is None
    assert error == "Authentication failed"


def test_add_source_result_preserves_api_error(monkeypatch: pytest.MonkeyPatch):
    monkeypatch.setattr(
        api_client,
        "request_json",
        lambda *_args, **_kwargs: (None, "API error: backend unavailable"),
    )

    result, error = api_client.add_source_result("/tmp/demo", "folder")

    assert result is None
    assert error == "API error: backend unavailable"


def test_add_surfaces_api_errors(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]):
    monkeypatch.setattr(main, "info", lambda message, *_args, **_kwargs: print(message))
    monkeypatch.setattr(main, "error", lambda message, *_args, **_kwargs: print(message))
    monkeypatch.setattr(main, "dim", lambda message, *_args, **_kwargs: print(message))
    monkeypatch.setattr(main, "is_authenticated", lambda: True)
    monkeypatch.setattr(main.os.path, "expanduser", lambda path: path)
    monkeypatch.setattr(main.os.path, "exists", lambda _path: True)
    monkeypatch.setattr(main, "detect_source_type", lambda _path: "folder")
    monkeypatch.setattr(main, "spinner", _no_spinner)
    monkeypatch.setattr(
        main,
        "add_source_result",
        lambda *_args, **_kwargs: (None, "Authentication failed"),
        raising=False,
    )

    with pytest.raises(typer.Exit):
        main.add("/tmp/demo")

    output = capsys.readouterr().out
    assert "Authentication failed" in output
    assert "nia doctor" in output


def test_add_uses_ui_info_helper(monkeypatch: pytest.MonkeyPatch):
    seen_messages: list[str] = []

    monkeypatch.setattr(main, "is_authenticated", lambda: True)
    monkeypatch.setattr(main.os.path, "expanduser", lambda path: path)
    monkeypatch.setattr(main.os.path, "exists", lambda _path: True)
    monkeypatch.setattr(main, "detect_source_type", lambda _path: "folder")
    monkeypatch.setattr(main, "spinner", _no_spinner)
    monkeypatch.setattr(main, "info", lambda message, *_args, **_kwargs: seen_messages.append(message))
    monkeypatch.setattr(main, "success", lambda *_args, **_kwargs: None)
    monkeypatch.setattr(main, "dim", lambda *_args, **_kwargs: None)
    monkeypatch.setattr(
        main,
        "show_info",
        lambda *_args, **_kwargs: (_ for _ in ()).throw(AssertionError("show_info should not be called")),
    )
    monkeypatch.setattr(
        main,
        "add_source_result",
        lambda *_args, **_kwargs: (
            {"local_folder_id": "abcdef123456", "display_name": "demo"},
            None,
        ),
        raising=False,
    )

    main.add("/tmp/demo")

    assert seen_messages == ["Detected type: [cyan]folder[/cyan]"]


def test_status_json_reports_loading_errors(
    monkeypatch: pytest.MonkeyPatch,
    capsys: pytest.CaptureFixture[str],
):
    monkeypatch.setattr(main, "is_authenticated", lambda: True)
    monkeypatch.setattr(main, "spinner", _no_spinner)
    monkeypatch.setattr(
        main,
        "get_sources_result",
        lambda: (None, "API error: connection refused"),
        raising=False,
    )
    monkeypatch.setattr(main, "get_sources", lambda: [])

    main.status(json_output=True)

    output = capsys.readouterr().out
    assert "API error: connection refused" in output
    assert "No sources configured" not in output
