import base64
import copy

import pytest
import requests

from .conftest import diff, diff_child, diff_family, diff_rlg, link, read_family, unlink

FAMILY_RESET_PAYLOAD = {
    'category': 'AUTR',
    'situation': 'AUTR',
    'rl1': {
        'civility': 'MR',  # no effect
        'firstname': 'Marge',  # must be
        'lastname': 'Simpson',  # must be
        'maidenName': 'reset',  # no effect
        'quality': '25',
        'birth': {'dateBirth': '1950-10-01'},  # must be
        'adresse': {'idStreet': '', 'street1': 'reset', 'town': 'reset', 'zipcode': 'reset'},
    },
    'rl2': {
        'civility': 'MME',  # no effect
        'firstname': 'Homer',  # must be
        'lastname': 'Simpson',  # must be
        'quality': '25',
        'birth': {'dateBirth': '1956-05-12'},  # must be
        'adresse': {
            'num': '42',
            'numComp': 'Q',
            'street1': 'reset',  # E19 : La voie est obligatoire
            'street2': '',
            'town': 'reset',  # E17 : Le nom de la commune est obligatoire'
            'zipcode': 'reset',  # E16 : Le code postal est obligatoire
        },
        'contact': {  # contact is removed (set to None) by the bellow content
            'isContactMail': False,
            'isContactSms': False,
            'isInvoicePdf': False,
            'mail': '',
            'mobile': '',
            'phone': '',
        },
        'profession': {
            'addressPro': {'num': '42', 'street': '', 'town': '', 'zipcode': ''},
            'codeCSP': '91',
            'employerName': '',
            'phone': '',
            'profession': '',
        },
        'CAFInfo': {
            'number': 'reset',  # cannot be removed
            'organ': '',
        },
        'indicatorList': [
            {
                'code': 'AVL',
                'isActive': False,
            },
            {
                'code': 'ETABSPEC',
                'isActive': False,
            },
        ],
    },
    'childList': [
        {
            'num': 'place holder',  # required for update
            'sexe': 'F',
            'firstname': 'Bartolome',  # some side effects, cf test_update_child
            'lastname': 'Simps',
            'birth': {'dateBirth': '1970-01-01'},
            'bPhoto': False,
            'bLeaveAlone': False,
            'dietcode': '',
            'paiInfoBean': {
                'code': 'PAI_03',
                'dateDeb': '1970-01-01',
                'dateFin': '1970-01-01',
                'description': '',
            },
            'medicalRecord': {
                'familyDoctor': {  # familyDoctor is removed (set to None) by the bellow content
                    'name': '',
                    'phone': '',
                    'address': {
                        'street1': '',
                        'zipcode': '',
                        'town': '',
                    },
                },
                'allergy1': '',
                'allergy2': '',
                'comment1': '',
                'comment2': '',
                'observ1': '',
                'observ2': '',
                'isAuthHospital': False,
                'hospital': '',
                'vaccinList': [],
            },
            'indicatorList': [
                {
                    'code': 'LUNETTE',
                    'isActive': False,
                },
                {
                    'code': 'AUTRE',
                    'note': 'rebellious',
                    'isActive': False,
                },
            ],
            # setting authorizedPersonList to None will remove the list
            'authorizedPersonList': [
                {
                    'personInfo': {
                        'civility': None,
                        'firstname': 'reset',  # E704 : Le prénom de la personne est obligatoire
                        'lastname': 'reset',  # E705 : Le nom de la personne est obligatoire
                        'dateBirth': '1970-01-01',
                        'sexe': 'M',
                        'contact': {  # contact is removed (set to None) by the bellow content
                            'phone': '',
                            'mobile': '',
                            'mail': '',
                        },
                    },
                    'personQuality': {
                        'code': '25',
                    },
                },
            ],
        },
    ],
    # setting emergencyPersonList to None will keep the list
    'emergencyPersonList': [
        {
            'civility': None,
            'firstname': 'reset',  # ORA-01400: impossible d'insérer NULL dans ("MAELIS"."H_PERS"."ER_PNOM")
            'lastname': 'reset',  # ORA-01400: impossible d'insérer NULL dans ("MAELIS"."H_PERS"."ER_NOM")
            'dateBirth': '1970-01-01',
            'sexe': 'M',
            'quality': '25',
            'contact': {
                'phone': '',
                'mobile': '',
                'mail': '',
            },
        },
    ],
}


def test_update_family(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)
    url = conn + '/update-family?NameID=%s' % update_data['name_id']

    # reset fields
    family_reset_payload = copy.deepcopy(FAMILY_RESET_PAYLOAD)
    family_reset_payload['rl1']['lastname'] = update_data['lastname']
    family_reset_payload['rl2']['lastname'] = update_data['lastname']
    for child in family_reset_payload['childList']:
        child['lastname'] = update_data['lastname']

    family_reset_payload['childList'][0]['num'] = update_data['family_payload']['childList'][0]['num']
    resp = requests.post(url, json=family_reset_payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = diff_family(conn, update_data['name_id'], 'test_update_family_ras.json')

    # unchanged values
    assert data['RL1']['civility'] != family_reset_payload['rl1']['civility']
    assert data['RL2']['civility'] != family_reset_payload['rl2']['civility']
    assert data['RL1']['maidenName'] != family_reset_payload['rl1']['maidenName']

    # changed values
    assert data['RL1']['quality'] == family_reset_payload['rl1']['quality']
    assert data['RL2']['quality'] == family_reset_payload['rl2']['quality']

    # without passing emergencyPersonList the list is keept
    assert len(data['emergencyPersonList']) == 1
    del family_reset_payload['emergencyPersonList']
    resp = requests.post(url, json=family_reset_payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, update_data['name_id'])
    assert len(data['emergencyPersonList']) == 1

    # without passing authorizedPersonList the list is removed
    assert len(data['childList'][0]['authorizedPersonList']) == 1
    del family_reset_payload['childList'][0]['authorizedPersonList']
    resp = requests.post(url, json=family_reset_payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, update_data['name_id'])
    assert data['childList'][0]['authorizedPersonList'] == []

    # update root fields
    payload = {
        'category': 'BI',
        'situation': 'MARI',
    }
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, update_data['name_id'])
    assert data['category'] == 'BI'
    assert data['situation'] == 'MARI'
    assert data['category_text'] == 'BIPARENTALE'
    assert data['situation_text'] == 'MARIE(E)'

    # restore family
    resp = requests.post(url, json=update_data['family_payload'])
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')


def test_create_family(conn, create_data, update_data):
    unlink(conn, create_data['name_id'])
    link(conn, create_data)
    url = conn + '/create-family?NameID=%s' % create_data['name_id']

    # RL1 already exists (on update_data) error
    unlink(conn, create_data['name_id'])
    payload = copy.deepcopy(create_data['family_payload'])
    payload['rl1']['lastname'] = 'Simpson'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert 'E54a' in res['err']
    assert 'Il existe déjà un Responsable Légal correspondant' in res['err_desc']
    assert res['err_class'] == 'passerelle.utils.jsonresponse.APIError'

    # RL1 already exists (on update_data, as RL2) error
    payload['rl1']['firstname'] = 'Homer'
    payload['rl1']['birth']['dateBirth'] = '1956-05-12'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert 'E54a' in res['err']
    assert 'Il existe déjà un Responsable Légal correspondant' in res['err_desc']
    assert res['err_class'] == 'passerelle.utils.jsonresponse.APIError'


def test_is_rl_exists(conn, update_data):
    url = conn + '/is-rl-exists'
    payload = {'firstname': 'Marge', 'lastname': 'Simpson', 'dateBirth': '1950-10-01'}
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json() == {'err': 0, 'data': True}

    payload['firstname'] = payload['firstname'].upper()
    payload['lastname'] = payload['lastname'].lower()
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json() == {'err': 0, 'data': True}

    payload['dateBirth'] = '1970-01-01'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json() == {'err': 0, 'data': False}

    # test on rl2
    payload = {'firstname': 'Homer', 'lastname': 'Simpson', 'dateBirth': '1956-05-12'}
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json() == {'err': 0, 'data': True}


def test_create_rl2(conn, create_data, update_data):
    unlink(conn, create_data['name_id'])
    link(conn, create_data)

    data = read_family(conn, create_data['name_id'])
    assert data['RL2'] is None

    # no unicity restriction on RL2 (duplicate RL2 from update_data)
    url = conn + '/create-rl2?NameID=%s' % create_data['name_id']
    payload = copy.deepcopy(update_data['family_payload']['rl2'])
    for key in 'contact', 'profession', 'CAFInfo', 'indicatorList':
        del payload[key]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_rlg(conn, create_data['name_id'], 2, 'test_create_rl2.json')


@pytest.mark.parametrize("rl", ['1', '2'])
def test_update_rlg(conn, update_data, rl):
    rlg = 'rl' + rl
    RLG = 'RL' + rl
    unlink(conn, update_data['name_id'])
    link(conn, update_data)
    url = conn + '/update-rl%s?NameID=%s' % (rl, update_data['name_id'])

    # reset responsable legal
    payload = copy.deepcopy(FAMILY_RESET_PAYLOAD[rlg])
    payload['lastname'] = update_data['lastname']
    for key in 'adresse', 'contact', 'profession', 'CAFInfo', 'indicatorList':
        if key in payload:
            del payload[key]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = diff_rlg(conn, update_data['name_id'], rl, 'test_update_rl%s.json' % rl)

    # unchanged values
    assert data[RLG]['civility'] != FAMILY_RESET_PAYLOAD[rlg]['civility']
    if rl == 1:
        assert data[RLG]['maidenName'] != FAMILY_RESET_PAYLOAD[rlg]['maidenName']

    # changed values
    assert data[RLG]['quality'] == FAMILY_RESET_PAYLOAD[rlg]['quality']

    # update firstname is refused
    payload['firstname'] = 'plop'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 'Family-updateFamily-soap:Server'
    assert (
        "Le Responsable légal %s transmis n'est pas celui qui existe pour la famille" % rl in res['err_desc']
    )

    # update lastname is refused
    payload['firstname'] = update_data['family_payload'][rlg]['firstname']
    payload['lastname'] = 'plop'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 'Family-updateFamily-soap:Server'
    assert (
        "Le Responsable légal %s transmis n'est pas celui qui existe pour la famille" % rl in res['err_desc']
    )

    # update birtday is refused
    payload['lastname'] = update_data['lastname']
    payload['birth']['dateBirth'] = '1970-01-01'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 'Family-updateFamily-soap:Server'
    if rl == 1:
        assert (
            "Le Responsable légal %s transmis n'est pas celui qui existe pour la famille" % rl
            in res['err_desc']
        )
    else:
        assert "La date de naissance ne peut pas être modifiée" in res['err_desc']

    # restore RL1
    payload = copy.deepcopy(update_data['family_payload'][rlg])
    for key in 'adresse', 'contact', 'profession', 'CAFInfo', 'indicatorList':
        if payload.get(key):
            del payload[key]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = diff_family(conn, update_data['name_id'], 'test_update_family.json')


def test_update_coordinate(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)

    # reset RL2 coordinates
    url = conn + '/update-coordinate?NameID=%s&rl_id=%s' % (update_data['name_id'], update_data['rl2_num'])
    payload = {}
    for key in 'adresse', 'contact', 'profession', 'CAFInfo':
        payload[key] = FAMILY_RESET_PAYLOAD['rl2'][key]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    for key in 'adresse', 'contact', 'profession', 'CAFInfo':
        assert diff_rlg(conn, update_data['name_id'], 2, 'test_update_coordinate_%s.json' % key, key)

    # restore RL2 coordinates
    payload = {}
    for key in 'adresse', 'contact', 'profession', 'CAFInfo':
        payload[key] = update_data['family_payload']['rl2'][key]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')


def test_is_child_exists(conn, create_data):
    url = conn + '/is-child-exists'
    payload = {
        'firstname': 'Maggie',
        'lastname': create_data['lastname'],
        'dateBirth': create_data['family_payload']['childList'][1]['birth']['dateBirth'],
    }
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json() == {'err': 0, 'data': True}

    payload['firstname'] = payload['firstname'].upper()
    payload['lastname'] = payload['lastname'].lower()
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json() == {'err': 0, 'data': True}

    payload['firstname'] = 'plop'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json() == {'err': 0, 'data': False}


def test_create_child(conn, create_data, update_data):
    unlink(conn, create_data['name_id'])
    link(conn, create_data)

    data = read_family(conn, create_data['name_id'])
    assert len(data['childList']) == 3

    url = conn + '/create-child?NameID=%s' % create_data['name_id']
    payload = {
        'sexe': 'M',
        'firstname': 'Lisa',
        'lastname': create_data['lastname'],
        'birth': {'dateBirth': update_data['family_payload']['childList'][1]['birth']['dateBirth']},
    }
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_child(conn, create_data['name_id'], 3, 'test_create_child.json')

    # child already exists error (Lisa form same family)
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert 'Il existe déjà un enfant correspondant' in res['err_desc']
    res['err_desc'] = 'N/A'
    assert res == {
        'err': 'Family-createChild-soap:Server',
        'err_class': 'passerelle.utils.jsonresponse.APIError',
        'err_desc': 'N/A',
        'data': None,
    }

    # child already exists error (Lisa form update_data)
    payload['lastname'] = 'Simpson'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert 'Il existe déjà un enfant correspondant' in res['err_desc']
    res['err_desc'] = 'N/A'
    assert res == {
        'err': 'already-child',  # error is return into childErrorList
        'err_class': 'passerelle.utils.jsonresponse.APIError',
        'err_desc': 'N/A',
        'data': None,
    }


def test_update_child(conn, update_data, create_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)

    # renaming using existing child names on same family will in fact target the existing child
    # side effect: the authorized person list is copied by the connector (from Lisa to Maggie)
    url = conn + '/update-child?NameID=%s&child_id=%s' % (update_data['name_id'], update_data['lisa_num'])
    payload = copy.deepcopy(update_data['family_payload']['childList'][2])  # Maggie content
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
        if key in payload:
            del payload[key]
    assert payload['firstname'] == 'Maggie'
    payload['sexe'] = 'M'
    resp = requests.post(url, json=payload)  # use Lisa id in url
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, update_data['name_id'])
    assert data['childList'][1]['num'] == update_data['lisa_num']
    assert data['childList'][1]['firstname'] == 'LISA'  # Lisa unchanged
    assert data['childList'][2]['sexe'] == 'M'  # Maggie updated

    # restore Maggie
    url = conn + '/update-child?NameID=%s&child_id=%s' % (update_data['name_id'], update_data['maggie_num'])
    payload = copy.deepcopy(update_data['family_payload']['childList'][2])
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
        if key in payload:
            del payload[key]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')

    # rename to an existing child on other family
    url = conn + '/update-child?NameID=%s&child_id=%s' % (update_data['name_id'], update_data['bart_num'])
    payload = copy.deepcopy(create_data['family_payload']['childList'][1])
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
        if key in payload:
            del payload[key]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, update_data['name_id'])
    assert data['childList'][0]['num'] == update_data['bart_num']
    assert data['childList'][0]['firstname'] == 'MAGGIE'

    # reset Bart
    payload = copy.deepcopy(FAMILY_RESET_PAYLOAD['childList'][0])
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
        if key in payload:
            del payload[key]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_child(conn, update_data['name_id'], 0, 'test_update_child.json')

    # restore Bart
    payload = copy.deepcopy(update_data['family_payload']['childList'][0])
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
        if key in payload:
            del payload[key]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')

    # update Bart insurance (on create_data as it cannot be reset)
    unlink(conn, create_data['name_id'])
    link(conn, create_data)
    payload = copy.deepcopy(create_data['family_payload']['childList'][0])
    for key in 'dietcode', 'paiInfoBean', 'medicalRecord', 'authorizedPersonList', 'indicatorList':
        if key in payload:
            del payload[key]
    payload['insurance'] = {
        'company': 'Armagedon Colapse',
        'contractNumber': '444',
        'memberNumber': '555',
        'contractStart': '2022-01-02',
        'contractEnd': '2222-12-31',
    }
    url = conn + '/update-child?NameID=%s&child_id=%s' % (create_data['name_id'], create_data['bart_num'])
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    assert diff_child(conn, create_data['name_id'], 0, 'test_update_child_insurance.json', 'insurance')


def test_update_child_dietcode(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)
    url = conn + '/update-child-dietcode?NameID=%s&child_id=%s&dietcode=' % (
        update_data['name_id'],
        update_data['bart_num'],
    )

    data = read_family(conn, update_data['name_id'])
    assert data['childList'][0]['dietcode'] == 'MENU_AV'
    assert data['childList'][0]['dietcode_text'] == 'Avec viande'

    # change dietcode
    resp = requests.post(url + 'MENU_SV')
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, update_data['name_id'])
    assert data['childList'][0]['dietcode'] == 'MENU_SV'
    assert data['childList'][0]['dietcode_text'] == 'Sans viande'

    # empty dietcode
    resp = requests.post(url + '')
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, update_data['name_id'])
    assert data['childList'][0]['dietcode'] == None
    assert 'dietcode_text' not in data['childList'][0]

    # restore dietcode
    resp = requests.post(url + 'MENU_AV')
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')


def test_update_child_pai(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)
    url = conn + '/update-child-pai?NameID=%s&child_id=%s' % (update_data['name_id'], update_data['bart_num'])

    # reset PAI
    payload = FAMILY_RESET_PAYLOAD['childList'][0]['paiInfoBean']
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_child(conn, update_data['name_id'], 0, 'test_update_child_pai.json', key='paiInfoBean')

    # restore PAI
    payload = update_data['family_payload']['childList'][0]['paiInfoBean']
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')


def test_update_child_medical_record(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)
    url = conn + '/update-child-medical-record?NameID=%s&child_id=%s' % (
        update_data['name_id'],
        update_data['bart_num'],
    )

    # reset medical record
    payload = FAMILY_RESET_PAYLOAD['childList'][0]['medicalRecord']
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_child(
        conn, update_data['name_id'], 0, 'test_update_child_medical_record.json', key='medicalRecord'
    )

    # restore medical record
    payload = update_data['family_payload']['childList'][0]['medicalRecord']
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')


def test_person(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)
    data = read_family(conn, update_data['name_id'])
    assert len(data['emergencyPersonList']) == 2

    # delete Patty
    selma_num = data['emergencyPersonList'][1]['numPerson']
    url = conn + '/delete-person?NameID=%s&person_id=%s' % (update_data['name_id'], selma_num)
    resp = requests.post(url)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, update_data['name_id'])
    assert len(data['emergencyPersonList']) == 1

    # re-create Selma
    # last inserted person is added on the tail of the list
    url = conn + '/create-person?NameID=%s' % (update_data['name_id'])
    payload = FAMILY_RESET_PAYLOAD['emergencyPersonList'][0]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = diff_family(conn, update_data['name_id'], 'test_update_person.json', 'emergencyPersonList')

    # update Selma (and restore family person list)
    selma_num = data['emergencyPersonList'][1]['numPerson']
    url = conn + '/update-person?NameID=%s&person_id=%s' % (update_data['name_id'], selma_num)
    payload = update_data['family_payload']['emergencyPersonList'][1]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')


def test_child_person(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)
    data = read_family(conn, update_data['name_id'])
    assert len(data['childList'][0]['authorizedPersonList']) == 2

    # delete Abraham
    abi_num = data['childList'][0]['authorizedPersonList'][0]['personInfo']['num']
    url = conn + '/delete-child-person?NameID=%s&child_id=%s&person_id=%s' % (
        update_data['name_id'],
        update_data['bart_num'],
        abi_num,
    )
    resp = requests.post(url)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, update_data['name_id'])
    assert len(data['childList'][0]['authorizedPersonList']) == 1

    # re-create Abraham
    # last inserted person is added on the head of the list
    url = conn + '/create-child-person?NameID=%s&child_id=%s' % (
        update_data['name_id'],
        update_data['bart_num'],
    )
    payload = FAMILY_RESET_PAYLOAD['childList'][0]['authorizedPersonList'][0]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = diff_child(
        conn, update_data['name_id'], 0, 'test_update_child_person.json', 'authorizedPersonList'
    )

    # update Abraham (and restore child person list)
    abi_num = data['childList'][0]['authorizedPersonList'][0]['personInfo']['num']
    url = conn + '/update-child-person?NameID=%s&child_id=%s&person_id=%s' % (
        update_data['name_id'],
        update_data['bart_num'],
        abi_num,
    )
    payload = update_data['family_payload']['childList'][0]['authorizedPersonList'][0]
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_family(conn, update_data['name_id'], 'test_update_family.json')


def test_update_rl_indicator(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)
    url = conn + '/update-rl-indicator?NameID=%s&rl_id=%s' % (
        update_data['name_id'],
        update_data['rl2_num'],
    )

    # reset RL indicators
    payload = {'indicatorList': FAMILY_RESET_PAYLOAD['rl2']['indicatorList']}
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_rlg(conn, update_data['name_id'], 1, 'test_rl_indicator.json', key='indicatorList')

    # restore RL indicators
    payload = {'indicatorList': update_data['family_payload']['rl2']['indicatorList']}
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = diff_family(conn, update_data['name_id'], 'test_update_family.json')

    # check indicator dict
    indicators = sorted(data['RL2']['indicators'].values(), key=lambda x: x['id'])
    assert diff(indicators, 'test_rl_indicators.json')


def test_update_child_indicator(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)
    url = conn + '/update-child-indicator?NameID=%s&child_id=%s' % (
        update_data['name_id'],
        update_data['bart_num'],
    )

    # reset Bart indicators
    payload = {'indicatorList': FAMILY_RESET_PAYLOAD['childList'][0]['indicatorList']}
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    assert diff_child(conn, update_data['name_id'], 0, 'test_child_indicator.json', key='indicatorList')

    # restore Bart indicators
    payload = {'indicatorList': update_data['family_payload']['childList'][0]['indicatorList']}
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = diff_family(conn, update_data['name_id'], 'test_update_family.json')

    # check indicator dict
    indicators = sorted(data['childList'][0]['indicators'].values(), key=lambda x: x['id'])
    assert diff(indicators, 'test_child_indicators.json')


def test_update_quotient(conn, create_data):
    unlink(conn, create_data['name_id'])
    link(conn, create_data)

    # add quotient
    url = conn + '/update-quotient?NameID=%s&rl_id=%s' % (create_data['name_id'], create_data['rl1_num'])
    payload = {
        'yearRev': '2021',
        'dateStart': '2022-01-01',
        'dateEnd': '2022-12-31',
        'mtt': '1500.33',
        'cdquo': '1',
    }
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, create_data['name_id'])
    assert data['RL1']['quotientList'] == [
        {
            'yearRev': 2021,
            'dateStart': '2022-01-01T00:00:00+01:00',
            'dateEnd': '2022-12-31T00:00:00+01:00',
            'mtt': 1500.33,
            'cdquo': '1',
            'codeUti': None,
            'cdquo_text': 'Revenus fiscaux',
        }
    ]

    # add quotient
    payload['dateStart'] = '2022-01-02'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = read_family(conn, create_data['name_id'])
    assert len(data['RL1']['quotientList']) == 2

    # add quotient on another income year
    payload['yearRev'] = '2020'
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    assert resp.json()['err'] == 0
    data = diff_rlg(conn, create_data['name_id'], 1, 'test_update_quotient.json', 'quotientList')
    assert len(data['RL1']['quotientList']) == 3

    # test read-family with reference year
    url = conn + '/read-family?NameID=%s&income_year=%s' % (create_data['name_id'], '2020')
    resp = requests.get(url)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    return len(res['data']['RL1']['quotientList']) == 1


def test_read_family_members(conn, update_data):
    unlink(conn, update_data['name_id'])
    link(conn, update_data)

    # list RLs
    text_template = '{{ firstname }}'
    url = conn + '/read-rl-list?NameID=%s&text_template=%s' % (update_data['name_id'], text_template)
    resp = requests.get(url)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    assert len(res['data']) == 2
    assert res['data'][1]['text'] == 'HOMER'

    # get RL
    rl_id = res['data'][1]['id']
    url = conn + '/read-rl?NameID=%s&rl_id=%s' % (update_data['name_id'], rl_id)
    resp = requests.get(url)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    assert res['data']['firstname'] == 'HOMER'

    # list persons
    text_template = '{{ firstname }}'
    url = conn + '/read-person-list?NameID=%s&text_template=%s' % (update_data['name_id'], text_template)
    resp = requests.get(url)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    assert len(res['data']) == 2
    assert res['data'][1]['text'] == 'SELMA'

    # get person
    person_id = res['data'][1]['id']
    url = conn + '/read-person?NameID=%s&person_id=%s' % (update_data['name_id'], person_id)
    resp = requests.get(url)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    assert res['data']['firstname'] == 'SELMA'

    # list childs
    text_template = '{{ firstname }}'
    url = conn + '/read-child-list?NameID=%s&text_template=%s' % (update_data['name_id'], text_template)
    resp = requests.get(url)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    assert len(res['data']) == 4
    assert res['data'][0]['text'] == 'BART'

    # get child
    child_id = res['data'][0]['id']
    url = conn + '/read-child?NameID=%s&child_id=%s' % (update_data['name_id'], child_id)
    resp = requests.get(url)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    assert res['data']['firstname'] == 'BART'

    # list child persons
    text_template = '{{ personInfo.firstname }}'
    url = conn + '/read-child-person-list?NameID=%s&child_id=%s&text_template=%s' % (
        update_data['name_id'],
        child_id,
        text_template,
    )
    resp = requests.get(url)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    assert len(res['data']) == 2
    assert res['data'][0]['text'] == 'ABRAHAM JEBEDIAH'

    # get child person
    person_id = res['data'][0]['id']
    url = conn + '/read-child-person?NameID=%s&child_id=%s&person_id=%s' % (
        update_data['name_id'],
        child_id,
        person_id,
    )
    resp = requests.get(url)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
    assert res['data']['personInfo']['firstname'] == 'ABRAHAM JEBEDIAH'


def test_add_supplied_document(conn, create_data):
    unlink(conn, create_data['name_id'])
    link(conn, create_data)

    # push on family
    payload = {
        'documentList/0/code': '46',
        'documentList/0/depositDate': '2022-12-20',
        'documentList/0/file': {  # w.c.s. file field
            'filename': '201x201.jpg',
            'content_type': 'image/jpeg',
            'content': base64.b64encode(open('data/201x201.jpg', 'rb').read()).decode(),
        },
    }
    url = conn + '/add-supplied-document?NameID=%s' % create_data['name_id']
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0

    # push on RL
    payload['numPerson'] = create_data['rl1_num']
    url = conn + '/add-supplied-document?NameID=%s' % create_data['name_id']
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0

    # push on childe
    payload['numPerson'] = create_data['bart_num']
    url = conn + '/add-supplied-document?NameID=%s' % create_data['name_id']
    resp = requests.post(url, json=payload)
    resp.raise_for_status()
    res = resp.json()
    assert res['err'] == 0
