"""
Tests for Utility Functions
"""

import pytest
import os
import json
import tempfile
from api.utils import (
    load_json_file, save_json_file, safe_float, safe_int,
    truncate_string, CircularBuffer, format_pnl, format_percentage
)


class TestJSONOperations:
    """Tests pour opérations JSON"""

    def test_save_and_load(self):
        """Sauvegarder et charger JSON"""
        with tempfile.TemporaryDirectory() as tmpdir:
            filepath = os.path.join(tmpdir, 'test.json')
            data = {'key': 'value', 'number': 42}

            # Sauvegarder
            assert save_json_file(filepath, data) is True

            # Charger
            loaded = load_json_file(filepath)
            assert loaded == data

    def test_load_nonexistent(self):
        """Charger fichier inexistant"""
        result = load_json_file('/nonexistent/file.json', default={'default': True})
        assert result == {'default': True}

    def test_atomic_write(self):
        """Écriture atomique (pas de corruption partielle)"""
        with tempfile.TemporaryDirectory() as tmpdir:
            filepath = os.path.join(tmpdir, 'test.json')

            # Première écriture
            save_json_file(filepath, {'v': 1})

            # Deuxième écriture (doit être atomique)
            save_json_file(filepath, {'v': 2})

            # Le fichier doit être valide
            loaded = load_json_file(filepath)
            assert loaded == {'v': 2}


class TestSafeConversions:
    """Tests pour conversions sécurisées"""

    def test_safe_float(self):
        """Conversion float sécurisée"""
        assert safe_float('3.14') == 3.14
        assert safe_float('invalid', default=1.0) == 1.0
        assert safe_float(None, default=0.0) == 0.0

    def test_safe_int(self):
        """Conversion int sécurisée"""
        assert safe_int('42') == 42
        assert safe_int('3.14') == 3
        assert safe_int('invalid', default=10) == 10
        assert safe_int(None, default=0) == 0


class TestStringUtils:
    """Tests pour utilitaires de chaînes"""

    def test_truncate_string(self):
        """Tronquer chaîne"""
        long_str = 'A' * 200
        truncated = truncate_string(long_str, max_length=50)

        assert len(truncated) == 50
        assert truncated.endswith('...')

        # Chaîne courte inchangée
        short_str = 'Hello'
        assert truncate_string(short_str, max_length=50) == short_str


class TestCircularBuffer:
    """Tests pour buffer circulaire"""

    def test_append(self):
        """Ajouter éléments"""
        buffer = CircularBuffer(max_size=3)

        buffer.append('A')
        buffer.append('B')
        buffer.append('C')

        assert buffer.get_all() == ['A', 'B', 'C']

    def test_overflow(self):
        """Dépassement de capacité"""
        buffer = CircularBuffer(max_size=3)

        buffer.append('A')
        buffer.append('B')
        buffer.append('C')
        buffer.append('D')  # Déborde, remplace 'A'

        all_items = buffer.get_all()
        assert len(all_items) == 3
        assert all_items == ['B', 'C', 'D']

    def test_clear(self):
        """Vider le buffer"""
        buffer = CircularBuffer(max_size=3)

        buffer.append('A')
        buffer.append('B')
        buffer.clear()

        assert buffer.get_all() == []


class TestFormatters:
    """Tests pour formatteurs"""

    def test_format_pnl(self):
        """Formater P&L"""
        assert format_pnl(10.5) == '+10.50 €'
        assert format_pnl(-5.25) == '-5.25 €'
        assert format_pnl(0.0) == '+0.00 €'

    def test_format_percentage(self):
        """Formater pourcentage"""
        assert format_percentage(15.5) == '+15.50%'
        assert format_percentage(-8.25) == '-8.25%'
        assert format_percentage(0.0) == '+0.00%'
