# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2021  Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import copy
import os

import xmlschema
from django.utils.translation import gettext_lazy as _

from passerelle.contrib.utils import axel

BASE_XSD_PATH = os.path.join(os.path.dirname(__file__), 'xsd')


boolean_type = {
    'oneOf': [
        {'type': 'boolean'},
        {
            'type': 'string',
            'pattern': '[Oo]|[Nn]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|1|0',
            'pattern_description': _(
                'Values "0", "1", "O", "N", "true" or "false" are allowed (case insensitive).'
            ),
        },
    ]
}


def encode_bool(obj):
    if obj is True or str(obj).lower() in ['true', 'o', '1']:
        return 'O'
    if obj is False or str(obj).lower() in ['false', 'n', '0']:
        return 'N'
    return obj


class CaluireAxelSchema(axel.AxelSchema):
    type_map = {
        '{urn:AllAxelTypes}DATEREQUIREDType': 'date',
        '{urn:AllAxelTypes}DATEType': 'date_optional',
        '{urn:AllAxelTypes}ONType': 'bool',
        '{urn:AllAxelTypes}ONEmptyType': 'bool_optional',
    }

    @classmethod
    def schema_bool(cls):
        return copy.deepcopy(boolean_type)

    def encode_bool(self, obj):
        return encode_bool(obj)

    def decode_bool(self, data):
        value = False
        if data.text.lower() == 'o':
            value = True
        return xmlschema.ElementData(
            tag=data.tag, text=value, content=data.content, attributes=data.attributes
        )


class Operation(axel.Operation):
    base_xsd_path = BASE_XSD_PATH
    axel_schema = CaluireAxelSchema


find_individus = Operation('FindIndividus')
get_famille_individus = Operation('GetFamilleIndividus')
get_individu = Operation('GetIndividu')
get_list_ecole = Operation('GetListEcole')
get_list_activites = Operation('GetListActivites')
create_inscription_activite = Operation('CreateInscriptionActivite', data_method='setData')
get_agenda = Operation('GetAgenda')
set_agenda = Operation('SetAgenda', data_method='setData')
get_factures_a_payer = Operation('GetFacturesaPayer')
get_list_factures = Operation('GetListFactures')
get_pdf_facture = Operation('GetPdfFacture')
set_paiement = Operation('SetPaiement', data_method='setData')
set_pieces = Operation('SetPieces', data_method='setData')


LINK_SCHEMA = copy.deepcopy(
    find_individus.request_schema['properties']['PORTAIL']['properties']['FINDINDIVIDU']
)
for key in ['NAISSANCE', 'CODEPOSTAL', 'VILLE', 'TEL', 'MAIL']:
    LINK_SCHEMA['properties'].pop(key)
    LINK_SCHEMA['required'].remove(key)
LINK_SCHEMA['properties']['IDENTFAMILLE'] = {'type': 'string', 'maxLength': 8}
LINK_SCHEMA['required'].append('IDENTFAMILLE')


REGISTER_ACTIVITY_SCHEMA = {
    'type': 'object',
    'properties': {
        'child_id': {
            'type': 'string',
            'minLength': 1,
            'maxLength': 8,
        },
        'activity_id': {
            'type': 'string',
            'minLength': 1,
            'maxLength': 10,
        },
        'registration_start_date': copy.deepcopy(axel.date_type),
        'registration_end_date': copy.deepcopy(axel.date_type),
    },
    'required': [
        'child_id',
        'activity_id',
        'registration_start_date',
        'registration_end_date',
    ],
}

BOOKING_SCHEMA = {
    'type': 'object',
    'properties': {
        'child_id': {
            'type': 'string',
            'minLength': 1,
            'maxLength': 8,
        },
        'booking_list': {
            'type': 'array',
            'items': {
                'type': 'string',
                'pattern': '[A-Za-z0-9]+:[- A-Za-z0-9]+:[0-9]{4}-[0-9]{2}-[0-9]{2}',
            },
        },
        'start_date': copy.deepcopy(axel.date_type),
        'end_date': copy.deepcopy(axel.date_type),
    },
    'required': [
        'child_id',
        'booking_list',
        'start_date',
        'end_date',
    ],
}

CHANGES_SCHEMA = {
    'type': 'object',
    'properties': {
        'child_id': {
            'type': 'string',
            'minLength': 1,
            'maxLength': 8,
        },
        'changes': {
            'type': 'array',
            'items': {
                'type': 'object',
                'properties': {
                    'activity_id': {
                        'type': 'string',
                        'minLength': 1,
                        'maxLength': 10,
                    },
                    'activity_label': {
                        'type': 'string',
                        'minLength': 0,
                        'maxLength': 100,
                    },
                    'day': copy.deepcopy(axel.date_type),
                    'booked': copy.deepcopy(boolean_type),
                },
                'required': [
                    'activity_id',
                    'activity_label',
                    'day',
                    'booked',
                ],
            },
        },
        'start_date': copy.deepcopy(axel.date_type),
        'end_date': copy.deepcopy(axel.date_type),
    },
    'required': [
        'child_id',
        'changes',
        'start_date',
        'end_date',
    ],
}

TYPICAL_WEEK_BOOKING_SCHEMA = {
    'type': 'object',
    'properties': {
        'child_id': {
            'type': 'string',
            'minLength': 1,
            'maxLength': 8,
        },
        'activity_id': {
            'type': 'string',
            'minLength': 1,
            'maxLength': 10,
        },
        'booking_list': {
            'type': 'array',
            'items': {
                'type': 'string',
                'pattern': '(monday|tuesday|thursday|friday)',
            },
        },
        'start_date': copy.deepcopy(axel.date_type),
        'end_date': copy.deepcopy(axel.date_type),
    },
    'required': [
        'child_id',
        'activity_id',
        'booking_list',
        'start_date',
        'end_date',
    ],
}


PAYMENT_SCHEMA = {
    'type': 'object',
    'properties': {
        'transaction_date': copy.deepcopy(axel.datetime_type),
        'transaction_id': {
            'type': 'string',
        },
    },
    'required': ['transaction_date', 'transaction_id'],
}


UPLOAD_ATTACHMENTS_SCHEMA = {
    'type': 'object',
    'properties': {
        'child_id': {
            'type': 'string',
            'minLength': 1,
            'maxLength': 8,
        },
        'reference_date': copy.deepcopy(axel.date_type),
        'attachments': {
            'type': 'array',
            'items': {
                'type': 'object',
                'properties': {
                    'attachment_type': {
                        'type': 'string',
                        'minLength': 4,
                        'maxLength': 4,
                    },
                    'label': {
                        'type': 'string',
                        'maxLength': 100,
                    },
                    'url': {
                        'type': 'string',
                        'maxLength': 250,
                    },
                },
                'required': [
                    'attachment_type',
                    'label',
                ],
            },
        },
    },
    'required': [
        'reference_date',
    ],
}
