import pytest
from src.result_types import (
 ErrorKind,
 ErrorInfo,
 Result,
 NilPath,
 NilRAGState,
)

def test_error_kind_enum_has_expected_values() -> None:
 assert ErrorKind.NETWORK.value == "network"
 assert ErrorKind.AUTH.value == "auth"
 assert ErrorKind.RATE_LIMIT.value == "rate_limit"
 assert ErrorKind.NOT_FOUND.value == "not_found"
 assert ErrorKind.NOT_READY.value == "not_ready"
 assert ErrorKind.UNKNOWN.value == "unknown"

def test_error_info_ui_message_with_source() -> None:
 e = ErrorInfo(kind=ErrorKind.RATE_LIMIT, message="too many requests", source="mcp.read_file")
 assert e.ui_message() == "[mcp.read_file] rate_limit: too many requests"

def test_error_info_ui_message_without_source() -> None:
 e = ErrorInfo(kind=ErrorKind.AUTH, message="bad key")
 assert e.ui_message() == "auth: bad key"

def test_result_ok_when_no_errors() -> None:
 r: Result[str] = Result(data="hello")
 assert r.ok is True
 assert r.data == "hello"
 assert r.errors == []

def test_result_not_ok_when_errors_present() -> None:
 r: Result[str] = Result(data="", errors=[ErrorInfo(kind=ErrorKind.NOT_FOUND, message="nope", source="test")])
 assert r.ok is False

def test_result_with_error_returns_new_result_with_appended_error() -> None:
 r1: Result[str] = Result(data="hello")
 err = ErrorInfo(kind=ErrorKind.NETWORK, message="timeout", source="test")
 r2 = r1.with_error(err)
 assert r1.errors == []
 assert r2.errors == [err]
 assert r2.data == "hello"

def test_result_with_data_replaces_data_keeps_errors() -> None:
 r1: Result[str] = Result(data="", errors=[ErrorInfo(kind=ErrorKind.NETWORK, message="x", source="t")])
 r2 = r1.with_data("new value")
 assert r2.data == "new value"
 assert len(r2.errors) == 1

def test_result_with_errors_appends_batch() -> None:
 r1: Result[str] = Result(data="hello")
 errs = [
  ErrorInfo(kind=ErrorKind.NETWORK, message="a", source="t"),
  ErrorInfo(kind=ErrorKind.AUTH, message="b", source="t"),
 ]
 r2 = r1.with_errors(errs)
 assert r1.errors == []
 assert r2.errors == errs
 assert r2.data == "hello"

def test_result_is_frozen() -> None:
 from dataclasses import FrozenInstanceError
 r: Result[str] = Result(data="x")
 with pytest.raises(FrozenInstanceError):
  r.data = "y"

def test_nil_path_singleton_has_default_values() -> None:
 assert NilPath.exists is False
 assert NilPath.read_text == ""
 assert NilPath.errors == []
 assert isinstance(NilPath(), NilPath)

def test_nil_rag_state_singleton_has_default_values() -> None:
 assert NilRAGState.enabled is False
 assert NilRAGState.is_empty_result is True
 assert NilRAGState.errors == []
