import pytest
from unittest.mock import Mock, patch
from notifiedby.flows import (
    subscribe_to_flow,
    unsubscribe_from_flow,
    list_flow_subscriptions,
    delete_all_subscriptions,
)


def test_subscribe_to_flow_minimal(mock_client):
    """Test subscribe_to_flow with minimal parameters."""
    mock_client.post.return_value = {'flow_trigger': 'welcome', 'email': 'test@example.com'}

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

    assert result['flow_trigger'] == 'welcome'
    assert result['email'] == 'test@example.com'

    mock_client.post.assert_called_once_with(
        '/flows/subscribe/',
        json={
            'flow_trigger': 'welcome',
            'email': 'test@example.com'
        }
    )


def test_subscribe_to_flow_full(mock_client):
    """Test subscribe_to_flow with all parameters."""
    mock_client.post.return_value = {'flow_trigger': 'onboarding', 'email': 'user@example.com'}

    result = subscribe_to_flow(
        'onboarding',
        'user@example.com',
        first_name='John',
        last_name='Doe',
        flags=['premium', 'beta'],
        client=mock_client
    )

    assert result['flow_trigger'] == 'onboarding'

    call_args = mock_client.post.call_args
    payload = call_args.kwargs['json']
    assert payload['flow_trigger'] == 'onboarding'
    assert payload['email'] == 'user@example.com'
    assert payload['first_name'] == 'John'
    assert payload['last_name'] == 'Doe'
    assert payload['flags'] == ['premium', 'beta']


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

    subscribe_to_flow('welcome', 'test@example.com')

    mock_client_class.assert_called_once()
    mock_instance.post.assert_called_once()


def test_unsubscribe_from_flow(mock_client):
    """Test unsubscribe_from_flow."""
    mock_client.post.return_value = {}

    result = unsubscribe_from_flow('newsletter', 'user@example.com', client=mock_client)

    assert result == {}
    mock_client.post.assert_called_once_with(
        '/flows/unsubscribe/',
        json={
            'flow_trigger': 'newsletter',
            'email': 'user@example.com'
        }
    )


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

    unsubscribe_from_flow('newsletter', 'test@example.com')

    mock_client_class.assert_called_once()


def test_list_flow_subscriptions(mock_client):
    """Test list_flow_subscriptions."""
    mock_response = {
        'count': 50,
        'next': 'http://api.example.com/v1/flows/subscriptions/?page=2',
        'previous': None,
        'results': [
            {
                'id': 1,
                'flow_name': 'Welcome Series',
                'flow_trigger': 'welcome',
                'recipient_email': 'user1@example.com',
                'status': 'active',
            },
            {
                'id': 2,
                'flow_name': 'Onboarding',
                'flow_trigger': 'onboarding',
                'recipient_email': 'user2@example.com',
                'status': 'completed',
            }
        ]
    }
    mock_client.get.return_value = mock_response

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

    assert result['count'] == 50
    assert len(result['results']) == 2
    assert result['results'][0]['flow_trigger'] == 'welcome'

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


def test_list_flow_subscriptions_page_2(mock_client):
    """Test list_flow_subscriptions with page 2."""
    mock_client.get.return_value = {'count': 0, 'results': []}

    list_flow_subscriptions(page=2, client=mock_client)

    mock_client.get.assert_called_once_with(
        '/flows/subscriptions/',
        params={'page': 2}
    )


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

    list_flow_subscriptions()

    mock_client_class.assert_called_once()


def test_delete_all_subscriptions(mock_client):
    """Test delete_all_subscriptions."""
    mock_client.delete.return_value = {}

    result = delete_all_subscriptions(client=mock_client)

    assert result == {}
    mock_client.delete.assert_called_once_with('/flows/subscriptions/')


@patch('notifiedby.flows.NotifiedByClient')
def test_delete_all_subscriptions_creates_client(mock_client_class, mock_settings):
    """Test delete_all_subscriptions creates client when not provided."""
    mock_instance = Mock()
    mock_instance.delete.return_value = {}
    mock_client_class.return_value = mock_instance

    delete_all_subscriptions()

    mock_client_class.assert_called_once()
