"""
Heavy tests for image processing tasks using distributed compute
"""
import pytest
import threading
import time
from distributed_compute import Coordinator, Worker


def apply_convolution(image_data):
    """Apply convolution filter to image data"""
    import random
    # Simulate heavy image processing
    height = len(image_data)
    width = len(image_data[0]) if height > 0 else 0
    
    result = [[0 for _ in range(width)] for _ in range(height)]
    
    # Simple edge detection simulation
    for i in range(1, height - 1):
        for j in range(1, width - 1):
            val = abs(image_data[i][j] - image_data[i+1][j]) + \
                  abs(image_data[i][j] - image_data[i][j+1])
            result[i][j] = min(255, val)
    
    return result


def gaussian_blur(image_data):
    """Apply Gaussian blur to image"""
    height = len(image_data)
    width = len(image_data[0]) if height > 0 else 0
    
    result = [[0.0 for _ in range(width)] for _ in range(height)]
    
    # Simple 3x3 blur
    for i in range(1, height - 1):
        for j in range(1, width - 1):
            total = sum(image_data[i+di][j+dj] 
                       for di in [-1, 0, 1] 
                       for dj in [-1, 0, 1])
            result[i][j] = total / 9.0
    
    return result


def compute_histogram(image_data):
    """Compute histogram of image"""
    histogram = [0] * 256
    
    for row in image_data:
        for pixel in row:
            histogram[int(pixel) % 256] += 1
    
    return histogram


@pytest.mark.timeout(60)
def test_image_convolution():
    """Test applying convolution filters to multiple images"""
    import random
    random.seed(42)
    
    # Create synthetic images
    images = [
        [[random.randint(0, 255) for _ in range(100)] for _ in range(100)]
        for _ in range(10)
    ]
    
    coordinator = Coordinator(port=5560, verbose=False)
    coordinator.start_server()
    time.sleep(0.5)
    
    workers = []
    for i in range(3):
        worker = Worker('localhost', 5560, name=f'worker_{i}')
        workers.append(worker)
        thread = threading.Thread(target=worker.start, daemon=True)
        thread.start()
    
    time.sleep(2)
    
    try:
        results = coordinator.map(apply_convolution, images, timeout=50)
        
        assert len(results) == len(images)
        assert all(len(result) == 100 for result in results)
        assert all(len(result[0]) == 100 for result in results)
    finally:
        coordinator.stop_server()
        for worker in workers:
            worker.stop()


@pytest.mark.timeout(60)
def test_gaussian_blur():
    """Test Gaussian blur on multiple images"""
    import random
    random.seed(123)
    
    images = [
        [[random.randint(0, 255) for _ in range(80)] for _ in range(80)]
        for _ in range(15)
    ]
    
    coordinator = Coordinator(port=5561, verbose=False)
    coordinator.start_server()
    time.sleep(0.5)
    
    workers = []
    for i in range(3):
        worker = Worker('localhost', 5561, name=f'worker_{i}')
        workers.append(worker)
        thread = threading.Thread(target=worker.start, daemon=True)
        thread.start()
    
    time.sleep(2)
    
    try:
        results = coordinator.map(gaussian_blur, images, timeout=50)
        
        assert len(results) == len(images)
        assert all(len(result) == 80 for result in results)
    finally:
        coordinator.stop_server()
        for worker in workers:
            worker.stop()


@pytest.mark.timeout(60)
def test_histogram_computation():
    """Test histogram computation across multiple images"""
    import random
    random.seed(456)
    
    images = [
        [[random.randint(0, 255) for _ in range(120)] for _ in range(120)]
        for _ in range(20)
    ]
    
    coordinator = Coordinator(port=5562, verbose=False)
    coordinator.start_server()
    time.sleep(0.5)
    
    workers = []
    for i in range(4):
        worker = Worker('localhost', 5562, name=f'worker_{i}')
        workers.append(worker)
        thread = threading.Thread(target=worker.start, daemon=True)
        thread.start()
    
    time.sleep(2)
    
    try:
        results = coordinator.map(compute_histogram, images, timeout=50)
        
        assert len(results) == len(images)
        assert all(len(histogram) == 256 for histogram in results)
        assert all(sum(histogram) == 120 * 120 for histogram in results)
    finally:
        coordinator.stop_server()
        for worker in workers:
            worker.stop()
