"""Integration tests for end-to-end workflows."""

import pytest
import os
import sys
from pathlib import Path

# Add src to path
sys.path.insert(0, str(Path(__file__).parent.parent / 'src'))


@pytest.mark.integration
def test_full_submission_workflow(api_client, valid_token, correct_solution):
    """Test the complete submission workflow from code to results."""
    # Step 1: Submit code
    response = api_client['submit'](
        code=correct_solution,
        function_name='two_sum',
        token=valid_token
    )
    
    assert response.status_code == 200
    data = response.json()
    
    # Step 2: Verify response structure
    assert 'passed' in data
    assert 'failed' in data
    assert 'total' in data
    assert 'success' in data
    assert 'test_results' in data
    
    # Step 3: Verify all tests passed
    assert data['success'] is True
    assert data['passed'] == 7
    assert data['failed'] == 0
    
    # Step 4: Verify test result details
    assert len(data['test_results']) == 7
    
    for test_result in data['test_results']:
        assert test_result['passed'] is True
        assert 'test_number' in test_result
        assert 'description' in test_result


@pytest.mark.integration
def test_get_test_cases_endpoint(api_client, question_1_id):
    """Test fetching public test cases from the API."""
    response = api_client['get_test_cases'](question_1_id)
    
    assert response.status_code == 200
    data = response.json()
    
    # Should return test cases
    assert 'test_cases' in data
    test_cases = data['test_cases']
    
    # Should have 4 public test cases (hidden ones not included)
    assert len(test_cases) == 4
    
    # Each test case should have required fields
    for tc in test_cases:
        assert 'args' in tc or 'kwargs' in tc
        assert 'expected' in tc
        assert 'description' in tc

@pytest.mark.integration

def test_local_test_then_submit_workflow(api_client, valid_token, correct_solution, monkeypatch, server_url):
    """Test the workflow of running local tests then submitting."""
    monkeypatch.setenv('ZEST_SERVER_URL', server_url)
    
    from zest import Question
    
    # Step 1: Get test cases for local testing
    response = api_client['get_test_cases'](1)
    assert response.status_code == 200
    test_cases = response.json()['test_cases']
    
    # Step 2: Create Question instance and run local tests
    exec(correct_solution, globals())
    q = Question(1, func=two_sum)  # noqa: F821
    
    local_results = q.test(test_cases=test_cases, quiet=True)
    
    # Local tests should pass
    assert local_results['success'] is True
    assert local_results['passed'] == 4  # Only public tests
    
    # Step 3: Submit to server
    response = api_client['submit'](
        code=correct_solution,
        function_name='two_sum',
        token=valid_token
    )
    
    assert response.status_code == 200
    data = response.json()
    
    # Server tests should also pass (including hidden)
    assert data['success'] is True
    assert data['passed'] == 7  # Public + hidden

@pytest.mark.integration

def test_iterative_debugging_workflow(api_client, valid_token):
    """Test iterative debugging with multiple submissions."""
    # Attempt 1: Wrong solution
    wrong_code = 'def two_sum(nums, target):\n    return [0, 0]'
    
    response1 = api_client['submit'](
        code=wrong_code,
        function_name='two_sum',
        token=valid_token
    )
    
    assert response1.status_code == 200
    data1 = response1.json()
    assert data1['success'] is False
    
    # Attempt 2: Better solution (might pass some tests)
    better_code = '''def two_sum(nums, target):
    for i in range(len(nums)):
        for j in range(i + 1, len(nums)):
            if nums[i] + nums[j] == target:
                return [i, j]
    return []
'''
    
    response2 = api_client['submit'](
        code=better_code,
        function_name='two_sum',
        token=valid_token
    )
    
    assert response2.status_code == 200
    data2 = response2.json()
    # This solution should actually work
    assert data2['success'] is True
    
    # Attempt 3: Optimal solution
    optimal_code = '''def two_sum(nums, target):
    seen = {}
    for i, num in enumerate(nums):
        if target - num in seen:
            return [seen[target - num], i]
        seen[num] = i
    return []
'''
    
    response3 = api_client['submit'](
        code=optimal_code,
        function_name='two_sum',
        token=valid_token
    )
    
    assert response3.status_code == 200
    data3 = response3.json()
    assert data3['success'] is True
    assert data3['passed'] == 7

@pytest.mark.integration

def test_error_messages_helpful_for_debugging(api_client, valid_token):
    """Test that error messages provide useful debugging information."""
    # Code with a specific error
    error_code = '''def two_sum(nums, target):
    result = nums[999]  # Index out of range
    return [0, 1]
'''
    
    response = api_client['submit'](
        code=error_code,
        function_name='two_sum',
        token=valid_token
    )
    
    assert response.status_code == 200
    data = response.json()
    
    assert data['success'] is False
    
    # Should have test results with error information
    # At least one public test should have error details
    public_tests = [tr for tr in data['test_results'] if not tr.get('is_hidden', False)]
    
    failed_public = [tr for tr in public_tests if not tr.get('passed', False)]
    assert len(failed_public) > 0
    
    # Error should be present in at least one failed public test
    has_error_info = any('error' in tr for tr in failed_public)
    assert has_error_info
