import pytest
from unittest.mock import Mock, patch
from notifiedby.queries import (
    get_email_detail,
    list_sent_emails,
    get_email_delivery_status,
)
from notifiedby.exceptions import NotifiedByValidationError


def test_get_email_detail_by_sqid(mock_client):
    """Test get_email_detail with SQID parameter."""
    mock_response = {
        'recipient': 'user@example.com',
        'subject': 'Test Email',
        'body': '<p>Hello</p>',
        'created_on': '2024-01-01T00:00:00Z'
    }
    mock_client.get.return_value = mock_response

    result = get_email_detail(sqid='abc123xyz', client=mock_client)

    assert result['recipient'] == 'user@example.com'
    assert result['subject'] == 'Test Email'

    mock_client.get.assert_called_once_with('/email/detail/abc123xyz/')


def test_get_email_detail_by_email(mock_client):
    """Test get_email_detail with email parameter."""
    mock_response = {
        'recipient': 'user@example.com',
        'subject': 'Recent Email',
        'body': 'Content',
        'created_on': '2024-01-02T00:00:00Z'
    }
    mock_client.get.return_value = mock_response

    result = get_email_detail(email='user@example.com', client=mock_client)

    assert result['subject'] == 'Recent Email'

    mock_client.get.assert_called_once_with(
        '/email/detail/',
        params={'email': 'user@example.com'}
    )


def test_get_email_detail_no_params(mock_client):
    """Test get_email_detail raises error when neither sqid nor email provided."""
    with pytest.raises(NotifiedByValidationError) as exc_info:
        get_email_detail(client=mock_client)

    assert "Either 'sqid' or 'email' parameter must be provided" in str(exc_info.value)
    mock_client.get.assert_not_called()


@patch('notifiedby.queries.NotifiedByClient')
def test_get_email_detail_creates_client(mock_client_class, mock_settings):
    """Test get_email_detail creates client when not provided."""
    mock_instance = Mock()
    mock_instance.get.return_value = {'recipient': 'test@example.com'}
    mock_client_class.return_value = mock_instance

    get_email_detail(sqid='test123')

    mock_client_class.assert_called_once()


def test_list_sent_emails_no_filter(mock_client):
    """Test list_sent_emails without recipient filter."""
    mock_response = {
        'count': 500,
        'next': 'http://api.example.com/v1/email/list/?page=2',
        'previous': None,
        'results': [
            {
                'recipient': 'user1@example.com',
                'subject': 'Email 1',
                'created_on': '2024-01-01T00:00:00Z'
            },
            {
                'recipient': 'user2@example.com',
                'subject': 'Email 2',
                'created_on': '2024-01-02T00:00:00Z'
            }
        ]
    }
    mock_client.get.return_value = mock_response

    result = list_sent_emails(page=1, client=mock_client)

    assert result['count'] == 500
    assert len(result['results']) == 2

    mock_client.get.assert_called_once_with(
        '/email/list/',
        params={'page': 1}
    )


def test_list_sent_emails_with_recipient(mock_client):
    """Test list_sent_emails with recipient filter."""
    mock_response = {
        'count': 10,
        'results': [
            {
                'recipient': 'user@example.com',
                'subject': 'Email 1',
                'created_on': '2024-01-01T00:00:00Z'
            }
        ]
    }
    mock_client.get.return_value = mock_response

    result = list_sent_emails(recipient='user@example.com', page=2, client=mock_client)

    assert result['count'] == 10

    mock_client.get.assert_called_once_with(
        '/email/list/',
        params={'page': 2, 'recipient': 'user@example.com'}
    )


@patch('notifiedby.queries.NotifiedByClient')
def test_list_sent_emails_creates_client(mock_client_class, mock_settings):
    """Test list_sent_emails creates client when not provided."""
    mock_instance = Mock()
    mock_instance.get.return_value = {'count': 0, 'results': []}
    mock_client_class.return_value = mock_instance

    list_sent_emails()

    mock_client_class.assert_called_once()


def test_get_email_delivery_status(mock_client):
    """Test get_email_delivery_status."""
    mock_response = {
        'status': 'delivered',
        'delivered_at': '2024-01-01T00:05:00Z',
        'opened': True,
        'clicked': False
    }
    mock_client.get.return_value = mock_response

    result = get_email_delivery_status('email123', client=mock_client)

    assert result['status'] == 'delivered'
    assert result['opened'] is True

    mock_client.get.assert_called_once_with('/email/delivery/email123/')


@patch('notifiedby.queries.NotifiedByClient')
def test_get_email_delivery_status_creates_client(mock_client_class, mock_settings):
    """Test get_email_delivery_status creates client when not provided."""
    mock_instance = Mock()
    mock_instance.get.return_value = {'status': 'pending'}
    mock_client_class.return_value = mock_instance

    get_email_delivery_status('test123')

    mock_client_class.assert_called_once()
