"""Tests for PassthroughSTACHook."""

import json

from earthcatalog.stac_hooks import (
    PassthroughSTACHook,
    parse_hook_config,
    serialize_hook,
)


class TestPassthroughSTACHook:
    """Tests for the passthrough STAC hook."""

    def test_fetch_valid_stac_item(self):
        """Test fetching a valid STAC item from JSON string."""
        hook = PassthroughSTACHook()
        stac_json = json.dumps(
            {
                "type": "Feature",
                "id": "test_item",
                "geometry": {"type": "Point", "coordinates": [0, 0]},
                "properties": {"datetime": "2024-01-01T00:00:00Z"},
            }
        )

        result = hook.fetch(stac_json)

        assert result is not None
        assert result["id"] == "test_item"
        assert result["type"] == "Feature"

    def test_fetch_missing_type_field(self):
        """Test that missing 'type' field returns None."""
        hook = PassthroughSTACHook()
        invalid_json = json.dumps({"id": "test", "geometry": {}, "properties": {}})

        result = hook.fetch(invalid_json)

        assert result is None

    def test_fetch_missing_geometry(self):
        """Test that missing 'geometry' field returns None."""
        hook = PassthroughSTACHook()
        invalid_json = json.dumps({"type": "Feature", "id": "test", "properties": {}})

        result = hook.fetch(invalid_json)

        assert result is None

    def test_fetch_missing_properties(self):
        """Test that missing 'properties' field returns None."""
        hook = PassthroughSTACHook()
        invalid_json = json.dumps({"type": "Feature", "id": "test", "geometry": {}})

        result = hook.fetch(invalid_json)

        assert result is None

    def test_fetch_invalid_json(self):
        """Test that invalid JSON string returns None."""
        hook = PassthroughSTACHook()
        invalid_json = "not valid json"

        result = hook.fetch(invalid_json)

        assert result is None

    def test_fetch_non_dict_json(self):
        """Test that non-dict JSON returns None."""
        hook = PassthroughSTACHook()
        # JSON array instead of object
        invalid_json = json.dumps([{"id": "test"}])

        result = hook.fetch(invalid_json)

        assert result is None

    def test_fetch_batch(self):
        """Test batch fetching multiple STAC items."""
        hook = PassthroughSTACHook()

        stac_items = [
            json.dumps({"type": "Feature", "id": "item1", "geometry": {}, "properties": {}}),
            json.dumps({"type": "Feature", "id": "item2", "geometry": {}, "properties": {}}),
            json.dumps({"type": "Feature", "id": "item3", "geometry": {}, "properties": {}}),
        ]

        results = hook.fetch_batch(stac_items)

        assert len(results) == 3
        assert results[0]["id"] == "item1"
        assert results[1]["id"] == "item2"
        assert results[2]["id"] == "item3"

    def test_fetch_batch_with_invalid_items(self):
        """Test batch fetching with some invalid items."""
        hook = PassthroughSTACHook()

        items = [
            json.dumps({"type": "Feature", "id": "valid1", "geometry": {}, "properties": {}}),
            "invalid json",
            json.dumps({"type": "Feature", "id": "valid2", "geometry": {}, "properties": {}}),
            '{"type": "NotFeature", "geometry": {}, "properties": {}}',  # Wrong type
        ]

        results = hook.fetch_batch(items)

        assert len(results) == 4
        assert results[0]["id"] == "valid1"
        assert results[1] is None  # invalid json
        assert results[2]["id"] == "valid2"
        assert results[3] is None  # wrong type

    def test_to_config(self):
        """Test serialization to config string."""
        hook = PassthroughSTACHook()

        config_str = hook.to_config()

        assert config_str == "passthrough"

    def test_parse_hook_config_passthrough(self):
        """Test parsing 'passthrough' string returns PassthroughSTACHook."""
        hook = parse_hook_config("passthrough")

        assert isinstance(hook, PassthroughSTACHook)

    def test_parse_hook_config_default(self):
        """Test parsing 'default' string returns DefaultSTACHook."""
        from earthcatalog.stac_hooks import DefaultSTACHook

        hook = parse_hook_config("default")

        assert isinstance(hook, DefaultSTACHook)
        assert not isinstance(hook, PassthroughSTACHook)

    def test_serialize_passthrough_hook(self):
        """Test serializing PassthroughSTACHook."""
        hook = PassthroughSTACHook()

        config_str = serialize_hook(hook)

        assert config_str == "passthrough"

    def test_serialize_and_parse_passthrough(self):
        """Test round-trip serialization for passthrough hook."""
        original = PassthroughSTACHook()

        config_str = serialize_hook(original)
        restored = parse_hook_config(config_str)

        assert isinstance(restored, PassthroughSTACHook)


class TestPassthroughIntegration:
    """Integration tests for passthrough hook usage."""

    def test_passthrough_with_its_live_like_data(self):
        """Test passthrough hook with ITS_LIVE-style bulk data."""
        hook = PassthroughSTACHook()

        # Simulate ITS_LIVE NDJSON line with STAC item
        its_live_item = {
            "type": "Feature",
            "id": "ITS_LIVE_test_item",
            "geometry": {
                "type": "Polygon",
                "coordinates": [[[[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]]]],
            },
            "properties": {
                "datetime": "2020-01-01T00:00:00Z",
                "dataset_id": "TEST_DATASET",
            },
        }

        url = json.dumps(its_live_item)
        result = hook.fetch(url)

        assert result is not None
        assert result["id"] == "ITS_LIVE_test_item"
        assert result["properties"]["dataset_id"] == "TEST_DATASET"

    def test_passthrough_performance_skip_http(self):
        """Test that passthrough doesn't make HTTP requests."""
        hook = PassthroughSTACHook()

        # Even with timeout/retry params, they're ignored
        result = hook.fetch(
            '{"type": "Feature", "id": "test", "geometry": {}, "properties": {}}',
            timeout=999,  # Should be ignored
            retry_attempts=999,  # Should be ignored
        )

        assert result is not None
        assert result["id"] == "test"
