import json
from unittest import mock

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

import tests.utils
from passerelle.base.models import AccessRight, ApiUser
from passerelle.contrib.gdema.models import Gdema

SERVICES = '''[{"AdminService":"ADMINISTRATEUR DIV - Transports et D\xc3\xa9placements","CommuneService":null,"Id":"16151",
"Label":"DMT - Mobilité et transports","Typology":[]},{"AdminService":"ADMINISTRATEUR DEP ADMINISTRATION","CommuneService":null,"Id":"10173",
"Label":"DESPU - Administration Direction environnement et services publics urbains","Typology":[{"Text":"Maintenance Cie","Value":"13067"},
{"Text":"Sensibilisation en milieu scolaire","Value":"14948"},{"Text":"Demandes diverses","Value":"11532"},
{"Text":"Demande de stage compostage","Value":"12992"},{"Text":"Pr\xc3\xa9sence de d\xc3\xa9chets verts","Value":"20432"}]},
{"AdminService":"ADMINISTRATEUR DED3","CommuneService":null,"Id":"10426","Label":"DEE - Périscolaire et éducatif",
"Typology":[{"Text":"Activités périscolaires","Value":"10804"},{"Text":"Garderie","Value":"10805"},{"Text":"Restauration scolaire","Value":"10806"},
{"Text":"Restauration scolaire \\/ Nutrition","Value":"11180"},{"Text":"Restauration scolaire \\/ Abonnements \\/cantine et r\xc3\xa9gie","Value":"10807"},
{"Text":"Projets éducatifs en temps scolaire","Value":"10808"},{"Text":"Autres","Value":"10809"}]}]'''

CIVILITY = (
    '[{"Text":"Monsieur","Value":"1"},{"Text":"Madame","Value":"2"},{"Text":"Mademoiselle","Value":"3"}]'
)

REQUEST = r'''{"AnswerToProvide":true,"AssigmentServiceName":"DEPE - Projets et maintenance du patrimoine","AssigmentStructure":"Cellule Travaux",
"AssociationId":0,"ClosingDate":"/Date(1306314926000+0200)/","Confidential":false,"DataEntryService":"Education",
"Description":"contrôle de toutes les portes extérieures des classes - gonds faibles pour le poids de la porte(N° 11353 v1)","DesiredResponseDate":null,
"ExpectedDate":null,"ExpectedInterventionDate":null,"Files":[],"Handler":{"CUSStreetCode":null,"Cedex":null,"CellPhone":null,"Civility":null,"CivilityId":0,
"Fax":null,"Firstname":null,"Information":null,"Lastname":"ANONYME","Mail":null,"Organization":0,"Phone":null,"SectionCode":null,"SectionLetter":null,
"Street":null,"StreetLetter":null,"StreetNumber":null,"StructureLabel":null,"StructureShortLabel":null,"Title":null,"TitleId":0,"Town":null,"TownLabel":null,
"ZipCode":null},"Id":1,"InputChannel":"Courrier","Localization":{"AdditionnalInformation":null,"CUSStreetCode":"2075","ElectedDistrict":"006",
"JobSector":null,"Other":"(sous-localisation : Bâtiment)","SectionCode":"1","SectionLetter":"_","Site":"Conseil","SiteId":1790,"Street":"RUE DE LA PLACE",
"StreetLetter":null,"StreetNumber":"2","TerritorialSector":"105","Town":"482","TownLabel":"STRASBOURG","ZipCode":"67000"},"Origin":2,"OriginLabel":"Usager",
"Priority":2,"PriorityLabel":"Normal","ReceptDate":"/Date(1165964400000+0100)/","Refused":false,"ReleaseDate":null,"Response":false,"ResponseFinal":true,
"ResponseIntermediate":false,"Responses":[{"Date":"/Date(1306274400000+0200)/","OutputChannel":"Service X","Resume":"Intervention réalisée",
"SibeliusReference":null,"SignatureName":"UC","Type":2,"TypeLabel":"Finale"}],"SibeliusReference":null,"SiteCode":null,"SiteName":"Conseil","Sleeping":null,
"State":64,"StateLabel":"Cloturée","Structure":"Cellule Travaux","Syscreationdate":"/Date(1165186800000+0100)/",
"Sysmodificationdate":"/Date(1306314926000+0200)/","Typology":{"Id":11168,"Label":"Maintenance"}}'''

REQUEST_STATE = '{"Id":1,"State":64,"StateLabel":"Cloturée"}'

CREATE_INPUT = {  # from Publik system
    'Typology_Id': '21012',
    'Description': 'this is a test',
    'Localization_Town': '482',
    'Localization_TownLabel': 'STRASBOURG',
    'Origin': '2',
    'Priority': '2',
    'ReceptDate': '2006-12-13T00:00:00+01:00',
    'Files_2': {
        'filename': 'test2.txt',
        'content_type': 'text/plain',
        'content': 'ZGV1eA==',
    },
    'Files_1': {
        'filename': 'test1.txt',
        'content_type': 'text/plain',
        'content': 'dW4=',
    },
}

CONVERTED_INPUT = {  # to GDEMA webservice
    "Typology": {
        "Id": "21012",
    },
    "Description": "this is a test",
    "Localization": {"Town": "482", "TownLabel": "STRASBOURG"},
    "Origin": "2",
    "Priority": "2",
    "ReceptDate": "/Date(1165964400000+0100)/",
    "Files": [
        {"Base64Stream": "dW4=", "Name": "test1.txt"},
        {"Base64Stream": "ZGV1eA==", "Name": "test2.txt"},
    ],
}


@pytest.fixture
def gdema(db):
    gdema = Gdema.objects.create(slug='test', service_url='https://gdema.example.net/api/')
    # open access
    api = ApiUser.objects.create(username='all', keytype='', key='')
    obj_type = ContentType.objects.get_for_model(gdema)
    AccessRight.objects.create(
        codename='can_access', apiuser=api, resource_type=obj_type, resource_pk=gdema.pk
    )
    return gdema


def test_gdema_services_and_typologies(app, gdema):
    endpoint = tests.utils.generic_endpoint_url('gdema', 'referentiel', slug=gdema.slug)
    assert endpoint == '/gdema/test/referentiel'
    with mock.patch('passerelle.utils.Request.get') as requests_get:
        requests_get.return_value = tests.utils.FakedResponse(content=SERVICES, status_code=200)
        resp = app.get(endpoint + '/service/', status=200)
        assert requests_get.call_count == 1
        assert requests_get.call_args[0][0] == 'https://gdema.example.net/api/referentiel/service'
        assert 'data' in resp.json
        assert resp.json['err'] == 0
        assert len(resp.json['data']) == 3
        assert resp.json['data'][0]['id'] == '16151'
        assert resp.json['data'][0]['text'] == 'DMT - Mobilité et transports'

        resp = app.get(endpoint + '/typology/', status=200)
        assert requests_get.call_count == 2
        assert 'data' in resp.json
        assert resp.json['err'] == 0
        assert len(resp.json['data']) == 12
        assert resp.json['data'][0]['id'] == '13067'
        assert resp.json['data'][0]['text'] == 'Maintenance Cie'
        assert resp.json['data'][0]['service_id'] == '10173'
        assert (
            resp.json['data'][0]['service_text']
            == 'DESPU - Administration Direction environnement et services publics urbains'
        )

        resp = app.get(endpoint + '/typology/?service_id=10426', status=200)
        assert requests_get.call_count == 3
        assert 'data' in resp.json
        assert resp.json['err'] == 0
        assert len(resp.json['data']) == 7
        assert resp.json['data'][0]['id'] == '10804'
        assert resp.json['data'][0]['text'] == 'Activités périscolaires'
        assert resp.json['data'][0]['service_id'] == '10426'
        assert resp.json['data'][0]['service_text'] == 'DEE - Périscolaire et éducatif'


def test_gdema_referentiel(app, gdema):
    endpoint = tests.utils.generic_endpoint_url('gdema', 'referentiel', slug=gdema.slug)
    assert endpoint == '/gdema/test/referentiel'
    with mock.patch('passerelle.utils.Request.get') as requests_get:
        requests_get.return_value = tests.utils.FakedResponse(content=CIVILITY, status_code=200)
        resp = app.get(endpoint + '/civility/', status=200)
        assert requests_get.call_count == 1
        assert requests_get.call_args[0][0] == 'https://gdema.example.net/api/referentiel/civility'
        assert 'data' in resp.json
        assert resp.json['err'] == 0
        assert len(resp.json['data']) == 3
        assert resp.json['data'][0]['id'] == '1'
        assert resp.json['data'][0]['text'] == 'Monsieur'

    with mock.patch('passerelle.utils.Request.get') as requests_get:
        requests_get.return_value = tests.utils.FakedResponse(content='404', status_code=404)
        resp = app.get(endpoint + '/nothing/', status=200)
        assert requests_get.call_count == 1
        assert requests_get.call_args[0][0] == 'https://gdema.example.net/api/referentiel/nothing'
        assert 'data' in resp.json
        assert resp.json['err'] == 1
        assert resp.json['data'] is None
        assert resp.json['err_class'].endswith('.APIError')
        assert '404' in resp.json['err_desc']


def test_gdema_get_request(app, gdema):
    endpoint = tests.utils.generic_endpoint_url('gdema', 'get-request', slug=gdema.slug)
    assert endpoint == '/gdema/test/get-request'
    with mock.patch('passerelle.utils.Request.get') as requests_get:
        requests_get.return_value = tests.utils.FakedResponse(content=REQUEST, status_code=200)
        resp = app.get(endpoint + '/1/', status=200)
        assert requests_get.call_count == 1
        assert requests_get.call_args[0][0] == 'https://gdema.example.net/api/request/1'
        assert 'data' in resp.json
        assert resp.json['err'] == 0
        assert resp.json['data']['Id'] == '1'
        assert resp.json['data']['AnswerToProvide'] is True
        assert resp.json['data']['Description'].startswith('contrôle')
        assert resp.json['data']['ExpectedDate'] is None
        assert resp.json['data']['Files'] == []
        assert resp.json['data']['Handler']['CivilityId'] == '0'
        assert resp.json['data']['ReceptDate'] == '2006-12-13T00:00:00+01:00'

    endpoint = tests.utils.generic_endpoint_url('gdema', 'get-request-state', slug=gdema.slug)
    assert endpoint == '/gdema/test/get-request-state'
    with mock.patch('passerelle.utils.Request.get') as requests_get:
        requests_get.return_value = tests.utils.FakedResponse(content=REQUEST_STATE, status_code=200)
        resp = app.get(endpoint + '/1/', status=200)
        assert requests_get.call_count == 1
        assert requests_get.call_args[0][0] == 'https://gdema.example.net/api/request/1/state'
        assert 'data' in resp.json
        assert resp.json['err'] == 0
        assert resp.json['data'] == {'Id': '1', 'State': '64', 'StateLabel': 'Cloturée'}


def test_gdema_create_request(app, gdema):
    endpoint = tests.utils.generic_endpoint_url('gdema', 'create-request', slug=gdema.slug)
    assert endpoint == '/gdema/test/create-request'
    with mock.patch('passerelle.utils.Request.post') as requests_post:
        requests_post.return_value = tests.utils.FakedResponse(content=REQUEST, status_code=200)
        resp = app.post_json(endpoint + '?raise=1', params=CREATE_INPUT, status=200)
        assert requests_post.call_count == 1
        assert requests_post.call_args[0][0] == 'https://gdema.example.net/api/request/create'
        assert json.loads(requests_post.call_args[1]['data']) == CONVERTED_INPUT
        assert 'data' in resp.json
        assert resp.json['err'] == 0
        assert resp.json['data']['Id'] == '1'
