"""Tests for tabular load and save operations."""

from pathlib import Path

import polars as pl

from axm_tabular.operations.load import LoadOperation
from axm_tabular.operations.save import SaveOperation


class TestLoadOperation:
    """Tests for LoadOperation."""

    def test_name(self) -> None:
        """Test operation name."""
        op = LoadOperation()
        assert op.name == "tabular.load"

    def test_load_csv(self, tmp_path: Path) -> None:
        """Test loading a CSV file."""
        csv_file = tmp_path / "data.csv"
        csv_file.write_text("name,age\nAlice,30\nBob,25")

        op = LoadOperation()
        result = op.execute(None, {"path": str(csv_file)}, {})

        assert result.success
        assert isinstance(result.data, pl.DataFrame)
        assert result.data.shape == (2, 2)
        assert result.data["name"].to_list() == ["Alice", "Bob"]

    def test_load_parquet(self, tmp_path: Path) -> None:
        """Test loading a Parquet file."""
        parquet_file = tmp_path / "data.parquet"
        df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
        df.write_parquet(parquet_file)

        op = LoadOperation()
        result = op.execute(None, {"path": str(parquet_file)}, {})

        assert result.success
        assert result.data.shape == (3, 2)

    def test_load_missing_path(self) -> None:
        """Test error when path is missing from context."""
        op = LoadOperation()
        result = op.execute(None, {}, {})

        assert not result.success
        assert "Missing 'path'" in result.error

    def test_load_file_not_found(self, tmp_path: Path) -> None:
        """Test error when file doesn't exist."""
        op = LoadOperation()
        result = op.execute(None, {"path": str(tmp_path / "missing.csv")}, {})

        assert not result.success
        assert "File not found" in result.error

    def test_load_unsupported_extension(self, tmp_path: Path) -> None:
        """Test error for unsupported file extension."""
        json_file = tmp_path / "data.json"
        json_file.write_text('{"a": 1}')

        op = LoadOperation()
        result = op.execute(None, {"path": str(json_file)}, {})

        assert not result.success
        assert "Unsupported extension" in result.error


class TestSaveOperation:
    """Tests for SaveOperation."""

    def test_name(self) -> None:
        """Test operation name."""
        op = SaveOperation()
        assert op.name == "tabular.save"

    def test_save_csv(self, tmp_path: Path) -> None:
        """Test saving a CSV file."""
        df = pl.DataFrame({"name": ["Alice", "Bob"], "age": [30, 25]})
        csv_file = tmp_path / "output.csv"

        op = SaveOperation()
        result = op.execute(df, {"path": str(csv_file)}, {})

        assert result.success
        assert csv_file.exists()
        loaded = pl.read_csv(csv_file)
        assert loaded.shape == (2, 2)

    def test_save_parquet(self, tmp_path: Path) -> None:
        """Test saving a Parquet file."""
        df = pl.DataFrame({"x": [1, 2, 3]})
        parquet_file = tmp_path / "output.parquet"

        op = SaveOperation()
        result = op.execute(df, {"path": str(parquet_file)}, {})

        assert result.success
        assert parquet_file.exists()

    def test_save_creates_parent_dirs(self, tmp_path: Path) -> None:
        """Test that save creates parent directories."""
        df = pl.DataFrame({"a": [1]})
        nested_file = tmp_path / "nested" / "dir" / "output.csv"

        op = SaveOperation()
        result = op.execute(df, {"path": str(nested_file)}, {})

        assert result.success
        assert nested_file.exists()

    def test_save_missing_path(self) -> None:
        """Test error when path is missing from context."""
        df = pl.DataFrame({"a": [1]})
        op = SaveOperation()
        result = op.execute(df, {}, {})

        assert not result.success
        assert "Missing 'path'" in result.error

    def test_save_invalid_data_type(self, tmp_path: Path) -> None:
        """Test error when data is not a DataFrame."""
        op = SaveOperation()
        result = op.execute(
            {"not": "a dataframe"}, {"path": str(tmp_path / "out.csv")}, {}
        )

        assert not result.success
        assert "must be a Polars DataFrame" in result.error

    def test_save_unsupported_extension(self, tmp_path: Path) -> None:
        """Test error for unsupported file extension."""
        df = pl.DataFrame({"a": [1]})
        json_file = tmp_path / "output.json"

        op = SaveOperation()
        result = op.execute(df, {"path": str(json_file)}, {})

        assert not result.success
        assert "Unsupported extension" in result.error
