"""
Tests for FileExtractor.
"""

import json
import tempfile
from pathlib import Path

import pytest

from pycharter.etl_generator.extractors.file import FileExtractor


class TestFileExtractorJSON:
    """Tests for FileExtractor with JSON files."""

    @pytest.fixture
    def json_file(self):
        """Create a temporary JSON file."""
        data = [
            {"id": 1, "name": "Alice"},
            {"id": 2, "name": "Bob"},
            {"id": 3, "name": "Charlie"},
        ]

        with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
            json.dump(data, f)
            path = f.name

        yield path
        Path(path).unlink()

    @pytest.mark.asyncio
    async def test_extract_json(self, json_file):
        """Test extracting from JSON file."""
        extractor = FileExtractor(path=json_file)

        batches = []
        async for batch in extractor.extract():
            batches.append(batch)

        # Should get all records
        all_records = [r for batch in batches for r in batch]
        assert len(all_records) == 3
        assert all_records[0]["name"] == "Alice"

    @pytest.mark.asyncio
    async def test_extract_json_batched(self, json_file):
        """Test extracting with small batch size."""
        extractor = FileExtractor(path=json_file, batch_size=2)

        batches = []
        async for batch in extractor.extract():
            batches.append(batch)

        assert len(batches) == 2  # 3 records / 2 per batch = 2 batches
        assert len(batches[0]) == 2
        assert len(batches[1]) == 1


class TestFileExtractorJSONL:
    """Tests for FileExtractor with JSONL files."""

    @pytest.fixture
    def jsonl_file(self):
        """Create a temporary JSONL file."""
        with tempfile.NamedTemporaryFile(mode="w", suffix=".jsonl", delete=False) as f:
            for i in range(5):
                f.write(json.dumps({"id": i, "name": f"User{i}"}) + "\n")
            path = f.name

        yield path
        Path(path).unlink()

    @pytest.mark.asyncio
    async def test_extract_jsonl(self, jsonl_file):
        """Test extracting from JSONL file."""
        extractor = FileExtractor(path=jsonl_file, file_format="jsonl")

        batches = []
        async for batch in extractor.extract():
            batches.append(batch)

        all_records = [r for batch in batches for r in batch]
        assert len(all_records) == 5


class TestFileExtractorCSV:
    """Tests for FileExtractor with CSV files."""

    @pytest.fixture
    def csv_file(self):
        """Create a temporary CSV file."""
        with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f:
            f.write("id,name,email\n")
            f.write("1,Alice,alice@example.com\n")
            f.write("2,Bob,bob@example.com\n")
            path = f.name

        yield path
        Path(path).unlink()

    @pytest.mark.asyncio
    async def test_extract_csv(self, csv_file):
        """Test extracting from CSV file."""
        extractor = FileExtractor(path=csv_file, file_format="csv")

        batches = []
        async for batch in extractor.extract():
            batches.append(batch)

        all_records = [r for batch in batches for r in batch]
        assert len(all_records) == 2
        assert all_records[0]["name"] == "Alice"
        assert all_records[0]["email"] == "alice@example.com"


class TestFileExtractorErrors:
    """Tests for FileExtractor error handling."""

    @pytest.mark.asyncio
    async def test_file_not_found(self):
        """Test error on missing file."""
        extractor = FileExtractor(path="/nonexistent/file.json")

        with pytest.raises(FileNotFoundError):
            async for _ in extractor.extract():
                pass
