from unittest.mock import Mock

import pytest
from django.contrib.contenttypes.models import ContentType

from passerelle.base.models import AccessRight, ApiUser
from passerelle.contrib.iws.models import IWSConnector


@pytest.fixture()
def setup(db):
    api = ApiUser.objects.create(username='all', keytype='', key='')
    conn = IWSConnector.objects.create(
        wsdl_url='http://example.com/iws?wsdl',
        operation_endpoint='http://example.com/iws',
        username='admin',
        password='admin',
        database='somedb',
        slug='slug-iws',
    )
    obj_type = ContentType.objects.get_for_model(conn)
    AccessRight.objects.create(
        codename='can_access', apiuser=api, resource_type=obj_type, resource_pk=conn.pk
    )
    return conn


def create_params(**kwargs):
    res = {
        "firstname": "John",
        "lastname": "Doe",
        "description": "four : 1",
        "date": "28/10/2018",
        "token": "token",
        "email_notif": True,
    }
    res.update(kwargs)
    return res


def mock_soap_call(monkeypatch, return_value):
    mock_soap_call = Mock(return_value=return_value)
    import passerelle.contrib.iws.models

    monkeypatch.setattr(passerelle.contrib.iws.models.IWSConnector, '_soap_call', mock_soap_call)
    return mock_soap_call


def test_checkdate_dechet_or_encombrant(app, setup, endpoint_dummy_cache):
    response = app.get(
        '/iws/slug-iws/checkdate/3155570464130003/error/3/?city=toulouse&session_id=7a896f464ede7b4e',
        expect_errors=True,
    )
    json_result = response.json_body
    assert json_result['err'] == 1
    assert 'DECHET' in json_result['err_desc']
    assert 'ENCOMBRANT' in json_result['err_desc']


def test_checkdate_sti_code_optionnal_last_char(app, setup, endpoint_dummy_cache, monkeypatch):
    mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': 'Aucune dates disponibles'},
        },
    )
    response = app.get(
        '/iws/slug-iws/checkdate/3155570464130003B/DECHET/3/?city=toulouse&session_id=7a896f464ede7b4e'
    )
    json_result = response.json_body
    assert json_result['err'] == 0


def test_checkdate_iws_error_status(app, setup, monkeypatch, endpoint_dummy_cache):
    mock_soap_call(monkeypatch, {'status': 'KO', 'trace': 'some trace'})
    response = app.get(
        '/iws/slug-iws/checkdate/3155570464130003/DECHET/3/?city=toulouse&session_id=7a896f464ede7b4e',
        expect_errors=True,
    )
    json_result = response.json_body
    assert json_result['err'] == 1
    assert json_result['err_desc'] == 'iws error, status: "KO", trace: "some trace"'


def test_checkdate_iws_error_no_appel(app, setup, monkeypatch, endpoint_dummy_cache):
    mock_soap_call(monkeypatch, {'status': 'responseOk', 'trace': '', 'fields': {'NO_APPEL': ''}})
    response = app.get(
        '/iws/slug-iws/checkdate/3155570464130003/DECHET/3/?city=toulouse&session_id=7a896f464ede7b4e',
        expect_errors=True,
    )
    json_result = response.json_body
    assert json_result['err'] == 1
    assert json_result['err_desc'] == 'iws error, missing token'


def test_checkdate_iws_no_dates(app, setup, monkeypatch, endpoint_dummy_cache):
    mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': 'Aucune dates disponibles'},
        },
    )
    response = app.get(
        '/iws/slug-iws/checkdate/3155570464130003/DECHET/3/?city=toulouse&session_id=7a896f464ede7b4e'
    )
    json_result = response.json_body
    assert json_result['err'] == 0
    assert json_result['data'] == []


def test_checkdate_iws_has_dates(app, setup, monkeypatch, settings, endpoint_dummy_cache):
    settings.LANGUAGE_CODE = 'fr-fr'
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018; 19/06/2018'},
        },
    )
    response = app.get(
        '/iws/slug-iws/checkdate/3155570464130003/DECHET/3/?city=toulouse&session_id=7a896f464ede7b4e'
    )
    json_result = response.json_body
    assert json_result['err'] == 0
    dates = json_result['data']
    assert len(dates) == 2
    assert dates[0] == {"id": "18/06/2018", "text": "lundi 18 juin 2018", "token": "sometoken"}
    assert dates[1] == {"id": "19/06/2018", "text": "mardi 19 juin 2018", "token": "sometoken"}

    soap_args = soap_call.call_args[0][0]
    assert soap_args['C_STAPPEL'] == 'B'


def test_checkdate_dechet(app, setup, monkeypatch, endpoint_dummy_cache):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018; 19/06/2018'},
        },
    )
    app.get('/iws/slug-iws/checkdate/3155570464130003/DECHET/3/?city=toulouse&session_id=7a896f464ede7b4e')
    soap_args = soap_call.call_args[0][0]
    assert soap_args['C_EQUIPE'] == 'VPVIGIE'
    assert soap_args['I_AG_TYPEAGENDA'] == 'DECHETS VERTS'
    assert soap_args['I_APP_TYPEDEM'] == 'DECHET'
    assert soap_args['C_TYPEPB'] == '8006'


def test_checkdate_dechet_syndic(app, setup, monkeypatch, endpoint_dummy_cache):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018; 19/06/2018'},
        },
    )
    app.get(
        '/iws/slug-iws/checkdate/3155570464130003/DECHET/3/?city=toulouse'
        '&session_id=7a896f464ede7b4e&syndic=true'
    )
    soap_args = soap_call.call_args[0][0]
    assert soap_args['C_EQUIPE'] == 'VPVIGIE'
    assert soap_args['I_AG_TYPEAGENDA'] == 'DECHETS VERTS'
    assert soap_args['I_APP_TYPEDEM'] == 'DECHETSYNDIC'
    assert soap_args['C_TYPEPB'] == '8007'


def test_checkdate_encombrant(app, setup, monkeypatch, endpoint_dummy_cache):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018; 19/06/2018'},
        },
    )
    app.get(
        '/iws/slug-iws/checkdate/3155570464130003/ENCOMBRANT/3/?city=toulouse&session_id=7a896f464ede7b4e'
    )
    soap_args = soap_call.call_args[0][0]
    assert soap_args['C_EQUIPE'] == 'VPVIGIE'
    assert soap_args['I_AG_TYPEAGENDA'] == 'ENCOMBRANTS'
    assert soap_args['I_APP_TYPEDEM'] == 'ENCOMBRANT'
    assert soap_args['C_TYPEPB'] == '8008'

    soap_call.reset()
    app.get(
        '/iws/slug-iws/checkdate/3155570464130003/ENCOMBRANT/3/?city=toulouse'
        '&session_id=7a896f464ede7b4e&syndic=false'
    )
    soap_args = soap_call.call_args[0][0]
    assert soap_args['C_EQUIPE'] == 'VPVIGIE'
    assert soap_args['I_AG_TYPEAGENDA'] == 'ENCOMBRANTS'
    assert soap_args['I_APP_TYPEDEM'] == 'ENCOMBRANT'
    assert soap_args['C_TYPEPB'] == '8008'

    # check invalid parameter
    resp = app.get(
        '/iws/slug-iws/checkdate/3155570464130003/ENCOMBRANT/3/?city=toulouse'
        '&session_id=7a896f464ede7b4e&syndic=whatever',
        status=400,
    )
    assert resp.json.get('err') == 1
    assert resp.json.get('err_desc') == 'invalid value for parameter "syndic"'


def test_checkdate_encombrant_syndic(app, setup, monkeypatch, endpoint_dummy_cache):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018; 19/06/2018'},
        },
    )
    app.get(
        '/iws/slug-iws/checkdate/3155570464130003/ENCOMBRANT/3/?city=toulouse'
        '&session_id=7a896f464ede7b4e&syndic=true'
    )
    soap_args = soap_call.call_args[0][0]
    assert soap_args['C_EQUIPE'] == 'VPVIGIE'
    assert soap_args['I_AG_TYPEAGENDA'] == 'ENCOMBRANTS'
    assert soap_args['I_APP_TYPEDEM'] == 'ENCOMBRANTSYNDIC'
    assert soap_args['C_TYPEPB'] == '8009'


def test_bookdate(app, setup, monkeypatch):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'},
        },
    )
    response = app.post_json('/iws/slug-iws/bookdate/', params=create_params())
    soap_args = soap_call.call_args[0][0]
    assert soap_args['I_AP_SERVICE'] == 'OFFICE'
    assert soap_args['C_ORIGINE'] == 'TELESERVICE'
    assert soap_args['I_AP_SOURCE'] == 'USAGER'
    assert soap_args['C_STAPPEL'] == 'E'
    json_result = response.json_body
    assert json_result['err'] == 0
    assert json_result['data'] == {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'}


def test_bookdate_no_mail(app, setup, monkeypatch):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'},
        },
    )
    response = app.post_json('/iws/slug-iws/bookdate/', params=create_params())
    soap_args = soap_call.call_args[0][0]
    assert not soap_args['I_AP_ADRESSEMAIL']
    json_result = response.json_body
    assert json_result['err'] == 0


def test_bookdate_mail(app, setup, monkeypatch):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'},
        },
    )
    params = create_params()
    params['email'] = 'john.doe@localhost'
    response = app.post_json('/iws/slug-iws/bookdate/', params=params)
    soap_args = soap_call.call_args[0][0]
    assert soap_args['I_AP_ADRESSEMAIL'] == 'john.doe@localhost'
    json_result = response.json_body
    assert json_result['err'] == 0


def test_bookdate_mail_notif(app, setup, monkeypatch):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'},
        },
    )
    params = create_params()
    params['email_notif'] = True
    response = app.post_json('/iws/slug-iws/bookdate/', params=params)
    soap_args = soap_call.call_args[0][0]
    assert soap_args['I_AP_EMAIL'] == 'OUI'
    json_result = response.json_body
    assert json_result['err'] == 0


def test_bookdate_mail_no_notif(app, setup, monkeypatch):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'},
        },
    )
    params = create_params()
    params['email_notif'] = False
    response = app.post_json('/iws/slug-iws/bookdate/', params=params)
    soap_args = soap_call.call_args[0][0]
    assert soap_args['I_AP_EMAIL'] == 'NON'
    json_result = response.json_body
    assert json_result['err'] == 0


def test_bookdate_no_tel(app, setup, monkeypatch):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'},
        },
    )
    response = app.post_json('/iws/slug-iws/bookdate/', params=create_params())
    soap_args = soap_call.call_args[0][0]
    assert not soap_args['I_AP_TEL_DEMANDEU']
    assert soap_args['I_AP_SMS'] == 'NON'
    json_result = response.json_body
    assert json_result['err'] == 0


def test_bookdate_tel_motif(app, setup, monkeypatch):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'},
        },
    )
    params = create_params()
    params['tel_number'] = "0101010101"
    response = app.post_json('/iws/slug-iws/bookdate/', params=params)
    soap_args = soap_call.call_args[0][0]
    assert soap_args['I_AP_TEL_DEMANDEU'] == '0101010101'
    assert soap_args['I_AP_SMS'] == 'NON'
    json_result = response.json_body
    assert json_result['err'] == 0


@pytest.mark.parametrize('sms', [True, 'trUe', 1, '1'])
def test_bookdate_sms_true(app, setup, monkeypatch, sms):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'},
        },
    )
    params = create_params()
    params['tel_number'] = "0101010101"
    params['sms'] = sms
    response = app.post_json('/iws/slug-iws/bookdate/', params=params)
    soap_args = soap_call.call_args[0][0]
    assert soap_args['I_AP_TEL_DEMANDEU'] == '0101010101'
    assert soap_args['I_AP_SMS'] == 'OUI'
    json_result = response.json_body
    assert json_result['err'] == 0


@pytest.mark.parametrize('sms', [False, 'faLse', 0, '0'])
def test_bookdate_sms_false(app, setup, monkeypatch, sms):
    soap_call = mock_soap_call(
        monkeypatch,
        {
            'status': 'responseOk',
            'trace': '',
            'fields': {'NO_APPEL': 'sometoken', 'I_APP_DATESPOSSIBLES': '18/06/2018;'},
        },
    )
    params = create_params()
    params['tel_number'] = "0101010101"
    params['sms'] = sms
    response = app.post_json('/iws/slug-iws/bookdate/', params=params)
    soap_args = soap_call.call_args[0][0]
    assert soap_args['I_AP_TEL_DEMANDEU'] == '0101010101'
    assert soap_args['I_AP_SMS'] == 'NON'
    json_result = response.json_body
    assert json_result['err'] == 0
