import json
from unittest.mock import patch, MagicMock
from src.gemini_cli_adapter import GeminiCliAdapter


class TestGeminiCliAdapter:
 @patch("subprocess.Popen")
 def test_send_starts_subprocess_with_correct_args(
  self, mock_popen: MagicMock
 ) -> None:
  adapter = GeminiCliAdapter(binary_path="gemini")
  mock_process = MagicMock()
  mock_process.communicate.return_value = (
   '{"type": "message", "content": "hello"}',
   "",
  )
  mock_process.returncode = 0
  mock_popen.return_value = mock_process
  adapter.send("test prompt")
  assert mock_popen.called
  args, kwargs = mock_popen.call_args
  cmd_list = args[0]
  assert "gemini" in cmd_list
  assert "--prompt" in cmd_list
  assert "--output-format" in cmd_list
  assert "stream-json" in cmd_list

 @patch("subprocess.Popen")
 def test_send_parses_jsonl_output(self, mock_popen: MagicMock) -> None:
  adapter = GeminiCliAdapter()
  stdout_str = '{"type": "message", "content": "Hello "}\n{"type": "message", "content": "world!"}\n'
  mock_process = MagicMock()
  mock_process.communicate.return_value = (stdout_str, "")
  mock_process.returncode = 0
  mock_popen.return_value = mock_process
  result = adapter.send("msg")
  assert result["text"] == "Hello world!"

 @patch("subprocess.Popen")
 def test_send_handles_tool_use_events(self, mock_popen: MagicMock) -> None:
  adapter = GeminiCliAdapter()
  tool_json = {
   "type": "tool_use",
   "tool_name": "read_file",
   "parameters": {"path": "test.txt"},
   "tool_id": "call_123",
  }
  stdout_str = json.dumps(tool_json) + "\n"
  mock_process = MagicMock()
  mock_process.communicate.return_value = (stdout_str, "")
  mock_process.returncode = 0
  mock_popen.return_value = mock_process
  result = adapter.send("msg")
  assert len(result["tool_calls"]) == 1
  assert result["tool_calls"][0]["name"] == "read_file"
  assert result["tool_calls"][0]["args"]["path"] == "test.txt"

 @patch("subprocess.Popen")
 def test_send_captures_usage_metadata(self, mock_popen: MagicMock) -> None:
  adapter = GeminiCliAdapter()
  result_json = {"type": "result", "stats": {"total_tokens": 50}}
  stdout_str = json.dumps(result_json) + "\n"
  mock_process = MagicMock()
  mock_process.communicate.return_value = (stdout_str, "")
  mock_process.returncode = 0
  mock_popen.return_value = mock_process
  adapter.send("msg")
  assert adapter.last_usage is not None
  assert adapter.last_usage.get("total_tokens") == 50

 @patch("subprocess.Popen")
 def test_full_flow_integration(self, mock_popen: MagicMock) -> None:
  adapter = GeminiCliAdapter()
  msg_json = {"type": "message", "content": "Final response"}
  result_json = {
   "type": "result",
   "stats": {"total_tokens": 25, "input_tokens": 10, "output_tokens": 15},
  }
  stdout_str = json.dumps(msg_json) + "\n" + json.dumps(result_json) + "\n"
  mock_process = MagicMock()
  mock_process.communicate.return_value = (stdout_str, "")
  mock_process.returncode = 0
  mock_popen.return_value = mock_process
  result = adapter.send("test")
  assert "Final response" in result["text"]
