"""
Test cases for sink structure functionality (new flattened structure only).
"""
import pytest
from jinja2 import Environment

from noetl.tools.shared.storage import execute_sink_task


class TestSinkStructure:
    """Test cases for sink structure functionality."""

    def test_execute_sink_task_event_log(self):
        """Test execute_sink_task with event_log tool."""
        task_config = {
            'type': 'sink',
            'sink': {
                'tool': 'event_log',
                'data': {
                    'message': 'test message'
                }
            }
        }
        
        context = {'execution_id': 'test_123'}
        jinja_env = Environment()
        
        result = execute_sink_task(task_config, context, jinja_env)
        
        assert result['status'] == 'success'
        assert result['data']['saved'] == 'event'
        assert result['data']['data']['message'] == 'test message'

    def test_execute_sink_task_event_tool(self):
        """Test execute_sink_task with 'event' tool (alternative name)."""
        task_config = {
            'type': 'sink',
            'sink': {
                'tool': 'event',
                'data': {
                    'message': 'test message event'
                }
            }
        }
        
        context = {'execution_id': 'test_456'}
        jinja_env = Environment()
        
        result = execute_sink_task(task_config, context, jinja_env)
        
        assert result['status'] == 'success'
        assert result['data']['saved'] == 'event'
        assert result['data']['data']['message'] == 'test message event'

    def test_execute_sink_task_with_auth_string(self):
        """Test execute_sink_task with string auth reference."""
        task_config = {
            'type': 'sink',
            'sink': {
                'tool': 'postgres',
                'auth': 'pg_local',
                'table': 'test_table',
                'mode': 'upsert',
                'key': ['id'],
                'data': {
                    'id': '123',
                    'name': 'Test User'
                }
            }
        }
        
        context = {'execution_id': 'test_789'}
        jinja_env = Environment()
        
        # This will fail at postgres execution but should pass validation
        try:
            result = execute_sink_task(task_config, context, jinja_env)
            # If postgres is not configured, we expect an error but the validation should work
            if result['status'] == 'error':
                # This is expected if postgres is not available
                assert 'postgres' in str(result.get('error', '')).lower() or 'save failed' in str(result.get('error', '')).lower()
            else:
                # If postgres worked, that's fine too
                assert result['status'] == 'success'
        except Exception as e:
            # Postgres plugin might not be available in test environment
            assert 'postgres' in str(e).lower() or 'save' in str(e).lower()

    def test_execute_sink_task_with_auth_dict(self):
        """Test execute_sink_task with unified auth dictionary."""
        task_config = {
            'type': 'sink',
            'sink': {
                'tool': 'postgres',
                'auth': {
                    'pg': {
                        'type': 'postgres',
                        'key': 'pg_local'
                    }
                },
                'table': 'test_table',
                'data': {
                    'id': '456',
                    'name': 'Test User 2'
                }
            }
        }
        
        context = {'execution_id': 'test_abc'}
        jinja_env = Environment()
        
        # This will fail at postgres execution but should pass validation
        try:
            result = execute_sink_task(task_config, context, jinja_env)
            if result['status'] == 'error':
                assert 'postgres' in str(result.get('error', '')).lower() or 'save failed' in str(result.get('error', '')).lower()
            else:
                assert result['status'] == 'success'
        except Exception as e:
            assert 'postgres' in str(e).lower() or 'save' in str(e).lower()

    def test_execute_sink_task_invalid_storage_structure(self):
        """Test that legacy storage structure raises an error."""
        task_config = {
            'type': 'sink',
            'sink': {
                'tool': {  # This should fail - only string allowed
                    'kind': 'postgres',
                    'auth': 'pg_local'
                },
                'table': 'test_table'
            }
        }
        
        context = {'execution_id': 'test_def'}
        jinja_env = Environment()
        
        with pytest.raises(ValueError) as exc_info:
            execute_sink_task(task_config, context, jinja_env)
        
        assert "save.storage must be a string enum" in str(exc_info.value)
        assert "Legacy save.storage.kind structure is no longer supported" in str(exc_info.value)

    def test_execute_sink_task_default_event_storage(self):
        """Test that missing storage defaults to 'event'."""
        task_config = {
            'type': 'sink',
            'sink': {
                'data': {
                    'message': 'default storage test'
                }
            }
        }
        
        context = {'execution_id': 'test_default'}
        jinja_env = Environment()
        
        result = execute_sink_task(task_config, context, jinja_env)
        
        assert result['status'] == 'success'
        assert result['data']['saved'] == 'event'
        assert result['data']['data']['message'] == 'default storage test'

    def test_execute_sink_task_with_statement_mode(self):
        """Test execute_sink_task with statement mode."""
        task_config = {
            'type': 'sink',
            'sink': {
                'tool': 'postgres',
                'auth': 'pg_local',
                'statement': 'INSERT INTO test_table (id, name) VALUES (:id, :name)',
                'params': {
                    'id': '999',
                    'name': 'Statement Test'
                }
            }
        }
        
        context = {'execution_id': 'test_stmt'}
        jinja_env = Environment()
        
        # This will fail at postgres execution but should pass validation  
        try:
            result = execute_sink_task(task_config, context, jinja_env)
            if result['status'] == 'error':
                assert 'postgres' in str(result.get('error', '')).lower() or 'save failed' in str(result.get('error', '')).lower()
            else:
                assert result['status'] == 'success'
        except Exception as e:
            assert 'postgres' in str(e).lower() or 'save' in str(e).lower()