import unittest
import os
import shutil
from syfwb import io, utils, client
from unittest.mock import MagicMock, patch

class TestSyfwb(unittest.TestCase):
    def setUp(self):
        self.test_dir = "test_data"
        os.makedirs(self.test_dir, exist_ok=True)

    def tearDown(self):
        if os.path.exists(self.test_dir):
            shutil.rmtree(self.test_dir)

    def test_json_io(self):
        data = {"key": "value", "list": [1, 2, 3]}
        path = os.path.join(self.test_dir, "test.json")
        io.write_json(path, data)
        loaded = io.read_json(path)
        self.assertEqual(data, loaded)

    def test_jsonl_io(self):
        data = [{"id": 1}, {"id": 2}]
        path = os.path.join(self.test_dir, "test.jsonl")
        io.write_jsonl(path, data)
        loaded = list(io.read_jsonl(path))
        self.assertEqual(data, loaded)

    def test_retry(self):
        mock_func = MagicMock(side_effect=[ValueError("Fail"), "Success"])
        
        @utils.simple_retry(max_attempts=3, wait_min=0.1, wait_max=0.2)
        def unstable():
            return mock_func()
            
        result = unstable()
        self.assertEqual(result, "Success")
        self.assertEqual(mock_func.call_count, 2)

    @patch("syfwb.client.OpenAI")
    def test_openai_client(self, mock_openai):
        mock_instance = MagicMock()
        mock_openai.return_value = mock_instance
        mock_completion = MagicMock()
        mock_completion.choices = [MagicMock(message=MagicMock(content="Hello"))]
        mock_instance.chat.completions.create.return_value = mock_completion
        
        # Inject mock client to avoid env var dependency for test
        client._client = mock_instance
        
        response = client.call_openai([{"role": "user", "content": "Hi"}])
        self.assertEqual(response, "Hello")

if __name__ == "__main__":
    unittest.main()
