import pytest
from unittest.mock import Mock, patch
from notifiedby.recipients import (
    create_or_update_recipient,
    list_recipients,
    set_recipient_flags,
    clear_recipient_flags,
)


def test_create_or_update_recipient_minimal(mock_client):
    """Test create_or_update_recipient with only email."""
    mock_response = {
        'sqid': 'abc123',
        'email': 'test@example.com',
        'has_been_sent_email': False,
        'created_at': '2024-01-01T00:00:00Z',
        'updated_at': '2024-01-01T00:00:00Z',
    }
    mock_client.post.return_value = mock_response

    result = create_or_update_recipient('test@example.com', client=mock_client)

    assert result['sqid'] == 'abc123'
    assert result['email'] == 'test@example.com'

    mock_client.post.assert_called_once_with(
        '/recipients/',
        json={'email': 'test@example.com'}
    )


def test_create_or_update_recipient_full(mock_client):
    """Test create_or_update_recipient with all parameters."""
    mock_response = {
        'sqid': 'xyz789',
        'email': 'user@example.com',
        'first_name': 'Jane',
        'last_name': 'Doe',
        'has_been_sent_email': True,
    }
    mock_client.post.return_value = mock_response

    result = create_or_update_recipient(
        'user@example.com',
        first_name='Jane',
        last_name='Doe',
        flags=['premium', 'beta_tester'],
        client=mock_client
    )

    assert result['first_name'] == 'Jane'

    call_args = mock_client.post.call_args
    payload = call_args.kwargs['json']
    assert payload['email'] == 'user@example.com'
    assert payload['first_name'] == 'Jane'
    assert payload['last_name'] == 'Doe'
    assert payload['flags'] == ['premium', 'beta_tester']


@patch('notifiedby.recipients.NotifiedByClient')
def test_create_or_update_recipient_creates_client(mock_client_class, mock_settings):
    """Test create_or_update_recipient creates client when not provided."""
    mock_instance = Mock()
    mock_instance.post.return_value = {'sqid': 'test', 'email': 'test@example.com'}
    mock_client_class.return_value = mock_instance

    create_or_update_recipient('test@example.com')

    mock_client_class.assert_called_once()


def test_list_recipients(mock_client):
    """Test list_recipients."""
    mock_response = {
        'count': 100,
        'next': 'http://api.example.com/v1/recipients/?page=2',
        'previous': None,
        'results': [
            {
                'sqid': 'abc123',
                'email': 'user1@example.com',
                'first_name': 'John',
                'last_name': 'Doe',
                'has_been_sent_email': True,
            },
            {
                'sqid': 'xyz789',
                'email': 'user2@example.com',
                'first_name': 'Jane',
                'last_name': 'Smith',
                'has_been_sent_email': False,
            }
        ]
    }
    mock_client.get.return_value = mock_response

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

    assert result['count'] == 100
    assert len(result['results']) == 2
    assert result['results'][0]['email'] == 'user1@example.com'

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


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

    list_recipients()

    mock_client_class.assert_called_once()


def test_set_recipient_flags(mock_client):
    """Test set_recipient_flags."""
    mock_client.post.return_value = {}

    result = set_recipient_flags(
        'user@example.com',
        ['premium', 'annual_plan'],
        client=mock_client
    )

    assert result == {}
    mock_client.post.assert_called_once_with(
        '/recipients/flags/set/',
        json={
            'email': 'user@example.com',
            'flags': ['premium', 'annual_plan']
        }
    )


@patch('notifiedby.recipients.NotifiedByClient')
def test_set_recipient_flags_creates_client(mock_client_class, mock_settings):
    """Test set_recipient_flags creates client when not provided."""
    mock_instance = Mock()
    mock_instance.post.return_value = {}
    mock_client_class.return_value = mock_instance

    set_recipient_flags('test@example.com', ['flag1'])

    mock_client_class.assert_called_once()


def test_clear_recipient_flags(mock_client):
    """Test clear_recipient_flags."""
    mock_client.post.return_value = {}

    result = clear_recipient_flags(
        'user@example.com',
        ['trial', 'pending'],
        client=mock_client
    )

    assert result == {}
    mock_client.post.assert_called_once_with(
        '/recipients/flags/clear/',
        json={
            'email': 'user@example.com',
            'flags': ['trial', 'pending']
        }
    )


@patch('notifiedby.recipients.NotifiedByClient')
def test_clear_recipient_flags_creates_client(mock_client_class, mock_settings):
    """Test clear_recipient_flags creates client when not provided."""
    mock_instance = Mock()
    mock_instance.post.return_value = {}
    mock_client_class.return_value = mock_instance

    clear_recipient_flags('test@example.com', ['flag1'])

    mock_client_class.assert_called_once()
