"""
Tests for deployment monitoring functionality
"""

import pytest
from datetime import datetime
from unittest.mock import Mock, patch
from src.iicy.utils.deployment_monitor import (
    DeploymentMonitor, 
    DeploymentEvent, 
    EventStatus,
    monitor_deployment
)


def test_deployment_event_creation():
    """Test DeploymentEvent creation and properties"""
    event = DeploymentEvent(
        timestamp=datetime.now(),
        resource_type="AWS::Lambda::Function",
        logical_id="TestFunction",
        status=EventStatus.CREATE_IN_PROGRESS,
        status_reason="Creating Lambda function"
    )
    
    assert event.is_in_progress
    assert not event.is_success
    assert not event.is_failure


def test_deployment_event_success():
    """Test DeploymentEvent success detection"""
    event = DeploymentEvent(
        timestamp=datetime.now(),
        resource_type="AWS::Lambda::Function",
        logical_id="TestFunction",
        status=EventStatus.CREATE_COMPLETE
    )
    
    assert event.is_success
    assert not event.is_in_progress
    assert not event.is_failure


def test_deployment_event_failure():
    """Test DeploymentEvent failure detection"""
    event = DeploymentEvent(
        timestamp=datetime.now(),
        resource_type="AWS::Lambda::Function",
        logical_id="TestFunction",
        status=EventStatus.CREATE_FAILED,
        status_reason="Resource creation failed"
    )
    
    assert event.is_failure
    assert not event.is_success
    assert not event.is_in_progress


def test_deployment_monitor_initialization():
    """Test DeploymentMonitor initialization"""
    mock_client = Mock()
    monitor = DeploymentMonitor(mock_client, "TestStack")
    
    assert monitor.stack_name == "TestStack"
    assert monitor.cf_client == mock_client
    assert len(monitor.events) == 0
    assert not monitor.monitoring


@patch('src.iicy.utils.deployment_monitor.time.sleep')
def test_deployment_monitor_start_stop(mock_sleep):
    """Test starting and stopping deployment monitoring"""
    mock_client = Mock()
    monitor = DeploymentMonitor(mock_client, "TestStack")
    
    # Mock the _fetch_and_process_events method to avoid actual API calls
    monitor._fetch_and_process_events = Mock()
    
    # Start monitoring
    monitor.start_monitoring(poll_interval=1)
    assert monitor.monitoring
    
    # Stop monitoring
    monitor.stop_monitoring()
    assert not monitor.monitoring


def test_parse_event_valid():
    """Test parsing valid CloudFormation event data"""
    mock_client = Mock()
    monitor = DeploymentMonitor(mock_client, "TestStack")
    
    event_data = {
        'EventId': 'test-event-123',
        'Timestamp': datetime.now(),
        'ResourceType': 'AWS::Lambda::Function',
        'LogicalResourceId': 'TestFunction',
        'ResourceStatus': 'CREATE_IN_PROGRESS',
        'StatusReason': 'Creating Lambda function'
    }
    
    event = monitor._parse_event(event_data)
    
    assert event is not None
    assert event.resource_type == 'AWS::Lambda::Function'
    assert event.logical_id == 'TestFunction'
    assert event.status == EventStatus.CREATE_IN_PROGRESS
    assert event.status_reason == 'Creating Lambda function'


def test_parse_event_invalid_status():
    """Test parsing event with invalid status"""
    mock_client = Mock()
    monitor = DeploymentMonitor(mock_client, "TestStack")
    
    event_data = {
        'EventId': 'test-event-123',
        'Timestamp': datetime.now(),
        'ResourceType': 'AWS::Lambda::Function',
        'LogicalResourceId': 'TestFunction',
        'ResourceStatus': 'INVALID_STATUS'
    }
    
    event = monitor._parse_event(event_data)
    
    # Should return None for invalid status
    assert event is None


@patch('src.iicy.utils.deployment_monitor.DeploymentMonitor')
def test_monitor_deployment_function(mock_monitor_class):
    """Test the monitor_deployment function"""
    mock_client = Mock()
    mock_monitor = Mock()
    mock_monitor.wait_for_completion.return_value = True
    mock_monitor_class.return_value = mock_monitor
    
    result = monitor_deployment(mock_client, "TestStack", timeout_minutes=5)
    
    assert result is True
    mock_monitor_class.assert_called_once_with(mock_client, "TestStack")
    mock_monitor.wait_for_completion.assert_called_once_with(5)


def test_event_status_enum():
    """Test EventStatus enum values"""
    assert EventStatus.CREATE_IN_PROGRESS.value == "CREATE_IN_PROGRESS"
    assert EventStatus.CREATE_COMPLETE.value == "CREATE_COMPLETE"
    assert EventStatus.CREATE_FAILED.value == "CREATE_FAILED"
    assert EventStatus.UPDATE_IN_PROGRESS.value == "UPDATE_IN_PROGRESS"
    assert EventStatus.UPDATE_COMPLETE.value == "UPDATE_COMPLETE"
    assert EventStatus.UPDATE_FAILED.value == "UPDATE_FAILED"
    assert EventStatus.DELETE_IN_PROGRESS.value == "DELETE_IN_PROGRESS"
    assert EventStatus.DELETE_COMPLETE.value == "DELETE_COMPLETE"
    assert EventStatus.DELETE_FAILED.value == "DELETE_FAILED"
