from datetime import datetime, timedelta

import pytest
from freezegun import freeze_time

from tests.app.db import (
    create_inbound_sms,
    create_service,
    create_service_data_retention,
    create_service_with_inbound_number,
)


def test_post_to_get_inbound_sms_with_no_params(admin_request, sample_service):
    one = create_inbound_sms(sample_service)
    two = create_inbound_sms(sample_service)

    sms = admin_request.post(
        'inbound_sms.post_inbound_sms_for_service',
        service_id=sample_service.id,
        _data={}
    )['data']

    assert len(sms) == 2
    assert {inbound['id'] for inbound in sms} == {str(one.id), str(two.id)}
    assert sms[0]['content'] == 'Hello'
    assert set(sms[0].keys()) == {
        'id',
        'created_at',
        'service_id',
        'notify_number',
        'user_number',
        'content'
    }


@pytest.mark.parametrize('user_number', [
    '(07700) 900-001',
    '+4407700900001',
    '447700900001',
])
@pytest.mark.skip(reason="Needs updating for TTS. Don't need to test UK numbers right now")
def test_post_to_get_inbound_sms_filters_user_number(admin_request, sample_service, user_number):
    # user_number in the db is international and normalised
    one = create_inbound_sms(sample_service, user_number='447700900001')
    create_inbound_sms(sample_service, user_number='447700900002')

    data = {
        'phone_number': user_number
    }

    sms = admin_request.post(
        'inbound_sms.post_inbound_sms_for_service',
        service_id=sample_service.id,
        _data=data
    )['data']

    assert len(sms) == 1
    assert sms[0]['id'] == str(one.id)
    assert sms[0]['user_number'] == str(one.user_number)


def test_post_to_get_inbound_sms_filters_international_user_number(admin_request, sample_service):
    # user_number in the db is international and normalised
    one = create_inbound_sms(sample_service, user_number='12025550104')
    create_inbound_sms(sample_service)

    data = {
        'phone_number': '12025550104'
    }

    sms = admin_request.post(
        'inbound_sms.post_inbound_sms_for_service',
        service_id=sample_service.id,
        _data=data
    )['data']

    assert len(sms) == 2
    assert sms[1]['id'] == str(one.id)
    assert sms[1]['user_number'] == str(one.user_number)


def test_post_to_get_inbound_sms_allows_badly_formatted_number(admin_request, sample_service):
    one = create_inbound_sms(sample_service, user_number='ALPHANUM3R1C')

    sms = admin_request.post(
        'inbound_sms.post_inbound_sms_for_service',
        service_id=sample_service.id,
        _data={'phone_number': 'ALPHANUM3R1C'}
    )['data']

    assert len(sms) == 1
    assert sms[0]['id'] == str(one.id)
    assert sms[0]['user_number'] == str(one.user_number)


@freeze_time('Monday 10th April 2017 12:00')
def test_post_to_get_most_recent_inbound_sms_for_service_limits_to_a_week(admin_request, sample_service):
    create_inbound_sms(sample_service, created_at=datetime(2017, 4, 2, 23, 59))
    returned_inbound = create_inbound_sms(sample_service, created_at=datetime(2017, 4, 3, 0, 30))

    sms = admin_request.post('inbound_sms.post_inbound_sms_for_service', service_id=sample_service.id, _data={})

    assert len(sms['data']) == 1
    assert sms['data'][0]['id'] == str(returned_inbound.id)


@pytest.mark.parametrize('days_of_retention, too_old_date, returned_date', [
    (5, datetime(2017, 4, 4, 22, 59), datetime(2017, 4, 5, 12, 0)),
    (14, datetime(2017, 3, 26, 22, 59), datetime(2017, 3, 27, 12, 0)),
])
@freeze_time('Monday 10th April 2017 12:00')
def test_post_to_get_inbound_sms_for_service_respects_data_retention(
    admin_request,
    sample_service,
    days_of_retention,
    too_old_date,
    returned_date
):
    create_service_data_retention(sample_service, 'sms', days_of_retention)
    create_inbound_sms(sample_service, created_at=too_old_date)
    returned_inbound = create_inbound_sms(sample_service, created_at=returned_date)

    sms = admin_request.post('inbound_sms.post_inbound_sms_for_service', service_id=sample_service.id, _data={})

    assert len(sms['data']) == 1
    assert sms['data'][0]['id'] == str(returned_inbound.id)


def test_get_inbound_sms_summary(admin_request, sample_service):
    other_service = create_service(service_name='other_service')
    with freeze_time('2017-01-01'):
        create_inbound_sms(sample_service)
    with freeze_time('2017-01-02'):
        create_inbound_sms(sample_service)
    with freeze_time('2017-01-03'):
        create_inbound_sms(other_service)

        summary = admin_request.get(
            'inbound_sms.get_inbound_sms_summary_for_service',
            service_id=sample_service.id
        )

    assert summary == {
        'count': 2,
        'most_recent': datetime(2017, 1, 2).isoformat()
    }


def test_get_inbound_sms_summary_with_no_inbound(admin_request, sample_service):
    summary = admin_request.get(
        'inbound_sms.get_inbound_sms_summary_for_service',
        service_id=sample_service.id
    )

    assert summary == {
        'count': 0,
        'most_recent': None
    }


def test_get_inbound_sms_by_id_returns_200(admin_request, notify_db_session):
    service = create_service_with_inbound_number(inbound_number='12345')
    inbound = create_inbound_sms(service=service, user_number='447700900001')

    response = admin_request.get(
        'inbound_sms.get_inbound_by_id',
        service_id=service.id,
        inbound_sms_id=inbound.id,
    )

    assert response['user_number'] == '447700900001'
    assert response['service_id'] == str(service.id)


def test_get_inbound_sms_by_id_invalid_id_returns_404(admin_request, sample_service):
    assert admin_request.get(
        'inbound_sms.get_inbound_by_id',
        service_id=sample_service.id,
        inbound_sms_id='bar',
        _expected_status=404
    )


def test_get_inbound_sms_by_id_with_invalid_service_id_returns_404(admin_request, sample_service):
    assert admin_request.get(
        'inbound_sms.get_inbound_by_id',
        service_id='foo',
        inbound_sms_id='2cfbd6a1-1575-4664-8969-f27be0ea40d9',
        _expected_status=404
    )


@pytest.mark.parametrize('page_given, expected_rows, has_next_link', [
    (True, 10, False),
    (False, 50, True)
])
def test_get_most_recent_inbound_sms_for_service(
    admin_request,
    page_given,
    sample_service,
    expected_rows,
    has_next_link
):
    for i in range(60):
        create_inbound_sms(service=sample_service, user_number='44770090000{}'.format(i))

    request_args = {'page': 2} if page_given else {}
    response = admin_request.get(
        'inbound_sms.get_most_recent_inbound_sms_for_service',
        service_id=sample_service.id,
        **request_args
    )

    assert len(response['data']) == expected_rows
    assert response['has_next'] == has_next_link


@freeze_time('Monday 10th April 2017 12:00')
def test_get_most_recent_inbound_sms_for_service_respects_data_retention(
    admin_request,
    sample_service
):
    create_service_data_retention(sample_service, 'sms', 5)
    for i in range(10):
        created = datetime.utcnow() - timedelta(days=i)
        create_inbound_sms(sample_service, user_number='44770090000{}'.format(i), created_at=created)

    response = admin_request.get('inbound_sms.get_most_recent_inbound_sms_for_service', service_id=sample_service.id)

    assert len(response['data']) == 6
    assert [x['created_at'] for x in response['data']] == [
        '2017-04-10T12:00:00.000000Z',
        '2017-04-09T12:00:00.000000Z',
        '2017-04-08T12:00:00.000000Z',
        '2017-04-07T12:00:00.000000Z',
        '2017-04-06T12:00:00.000000Z',
        '2017-04-05T12:00:00.000000Z',
    ]


@freeze_time('Monday 10th April 2017 12:00')
def test_get_most_recent_inbound_sms_for_service_respects_data_retention_if_older_than_a_week(
    admin_request,
    sample_service
):
    create_service_data_retention(sample_service, 'sms', 14)
    create_inbound_sms(sample_service, created_at=datetime(2017, 4, 1, 12, 0))

    response = admin_request.get('inbound_sms.get_most_recent_inbound_sms_for_service', service_id=sample_service.id)

    assert len(response['data']) == 1
    assert response['data'][0]['created_at'] == '2017-04-01T12:00:00.000000Z'


@freeze_time('Monday 10th April 2017 12:00')
def test_get_inbound_sms_for_service_respects_data_retention(
    admin_request,
    sample_service
):
    create_service_data_retention(sample_service, 'sms', 5)
    for i in range(10):
        created = datetime.utcnow() - timedelta(days=i)
        create_inbound_sms(sample_service, user_number='44770090000{}'.format(i), created_at=created)

    response = admin_request.get('inbound_sms.get_most_recent_inbound_sms_for_service', service_id=sample_service.id)

    assert len(response['data']) == 6
    assert [x['created_at'] for x in response['data']] == [
        '2017-04-10T12:00:00.000000Z',
        '2017-04-09T12:00:00.000000Z',
        '2017-04-08T12:00:00.000000Z',
        '2017-04-07T12:00:00.000000Z',
        '2017-04-06T12:00:00.000000Z',
        '2017-04-05T12:00:00.000000Z',
    ]
