# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2019 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 csv
from urllib.parse import urljoin

import requests
from django.db import models
from django.http import HttpResponse
from django.urls import reverse
from django.utils.http import urlencode
from django.utils.timezone import localtime, now
from django.utils.translation import gettext_lazy as _

from passerelle.base.models import BaseResource, HTTPResource
from passerelle.forms import GenericConnectorForm
from passerelle.utils.api import endpoint
from passerelle.utils.json import response_schema
from passerelle.utils.jsonresponse import APIError

OUI_NON_ENUM = {'enum': ['Oui', 'Non']}
DATE_SCHEMA = {'type': 'string', 'format': 'date'}


def parameters(update=None):
    update = update or ()
    d = {
        'email': {
            'description': _('Publik known email'),
            'example_value': 'john.doe@example.com',
        },
        'ip': {
            'description': _('Publik client IP'),
            'example_value': '88.67.23.45',
        },
    }
    d.update(update)
    return d


def dump_csv_columns(columns):
    lines = []
    for column in columns:
        try:
            name, title = columns
            line = f'{name} {title}'
        except ValueError:
            line = column
        lines.append(line)
    return '\n'.join(lines)


class RSA13Form(GenericConnectorForm):
    def __init__(self, *args, **kwargs):
        instance = kwargs.get('instance')
        if instance is None:
            kwargs['initial'] = {}
            for name in RSA13Resource.CSV_EXPORTS:
                field = f'{name}_csv_columns'
                kwargs['initial'][field] = dump_csv_columns(DEFAULTS[field])
        else:
            for name in RSA13Resource.CSV_EXPORTS:
                field = f'{name}_csv_columns'
                if not getattr(instance, field):
                    setattr(instance, field, dump_csv_columns(DEFAULTS[field]))
        super().__init__(*args, **kwargs)


class RSA13Resource(BaseResource, HTTPResource):
    category = _('Business Process Connectors')

    webservice_base_url = models.URLField(_('Webservice Base URL'))

    beneficiaire_csv_columns = models.TextField(_('CSV columns for beneficiaires'), blank=True)
    facturation_csv_columns = models.TextField(_('CSV columns for facturation'), blank=True)
    sorti_csv_columns = models.TextField(_('CSV columns for sorti'), blank=True)

    hide_description_fields = ['beneficiaire_csv_columns', 'facturation_csv_columns', 'sorti_csv_columns']
    manager_form_base_class = RSA13Form
    log_requests_errors = False

    class Meta:
        verbose_name = _('RSA CD13')

    def request_raw(self, method, path, **kwargs):
        email = kwargs.pop('email', None)
        ip = kwargs.pop('ip', None)
        headers = kwargs.setdefault('headers', {})
        if email:
            headers['X-CD13-Email'] = email
        if ip:
            headers['X-CD13-IP'] = ip
        full_path = urljoin(self.webservice_base_url, '/api/') + path
        try:
            response = self.requests.request(method, full_path, **kwargs)
            try:
                response.json()
            except ValueError:
                response.raise_for_status()
                raise requests.RequestException('JSON expected', response=response)
        except requests.RequestException as e:
            raise APIError('Server is down: %s' % e)
        return response

    def request(self, method, path, **kwargs):
        response = self.request_raw(method, path, **kwargs)
        content = response.json()
        # CSV endpoint does not return err=
        if 'err' in content and content['err'] != 0:
            err_desc = content.get('err_code') or 'misc-error'
            raise APIError(err_desc, data=content)
        response.raise_for_status()
        return content

    def get(self, path, **kwargs):
        return self.request('get', path, **kwargs)

    def post(self, path, **kwargs):
        return self.request('post', path, **kwargs)

    def put(self, path, **kwargs):
        return self.request('put', path, **kwargs)

    def delete(self, path, **kwargs):
        return self.request('delete', path, **kwargs)

    def check_status(self):
        response = self.request_raw('GET', 'check')
        if response.json().get('ping') != 'pong':
            raise APIError('ping/pong expected received: "%s"' % repr(response)[:1024])

    def get_columns(self, name):
        def parse_csv_columns(content):
            columns = []
            for line in content.splitlines():
                if not line.strip():
                    continue
                row = line.strip().split(' ', 1)
                if not row[0]:
                    continue
                try:
                    json_name, column_name = row
                    columns.append((json_name, column_name.strip()))
                except ValueError:
                    json_name = row[0]
                    columns.append(json_name)
            return columns

        columns = []
        field = f'{name}_csv_columns'
        for column in parse_csv_columns(getattr(self, field)) or DEFAULTS[field]:
            if isinstance(column, str):
                columns.append((column, column))
            else:
                columns.append(tuple(column))
        return columns

    CSV_EXPORTS = ['beneficiaire', 'facturation', 'sorti']

    @property
    def description_csv_tables(self):
        for name in self.CSV_EXPORTS:
            yield (name.title(), self.get_columns(name))

    @endpoint(
        description=_('Get nomenclature'),
        long_description=_('Domain can be: MOTICLODAC, MOTIF_FIN_ACC, RESULTAT_RDV, RELANCE_RDV'),
        perm='can_access',
        pattern=r'^(?P<domain>[A-Z_]{1,30})/$',
        example_pattern='{domain}/',
        parameters=parameters(
            {
                'domain': {
                    'description': _('Nomenclature domain'),
                    'example_value': 'MOTICLODAC',
                }
            }
        ),
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'required': ['id', 'text'],
                    'properties': {
                        'id': {
                            'type': 'string',
                        },
                        'text': {
                            'type': 'string',
                        },
                    },
                },
            }
        ),
    )
    def nomenclature(self, request, domain, email, ip=None):
        return self.get('cg_ref_code/domain/%s/' % domain, email=email, ip=ip)

    @endpoint(
        description=_('List of platforms'),
        perm='can_access',
        parameters=parameters(),
        display_category=_('Platform'),
        display_order=1,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'required': ['id', 'dsp', 'name', 'role'],
                    'properties': {
                        'id': {
                            'type': 'integer',
                        },
                        'name': {
                            'type': 'string',
                        },
                        'dsp': {
                            'type': 'string',
                        },
                        'role': {
                            'enum': ['Coordonnateur', 'Accompagnateur'],
                        },
                    },
                },
            }
        ),
    )
    def platform(self, request, email, ip=None):
        return self.get('platform/', email=email, ip=ip)

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/$',
        example_pattern='{platform_id}/',
        description=_('Platform details'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                }
            }
        ),
        display_category=_('Platform'),
        display_order=2,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'required': [
                        'id',
                        'dsp',
                        'name',
                        'adr1',
                        'adr2',
                        'adr3',
                        'adr4',
                        'adr5',
                        'adr6',
                        'tel',
                        'queries',
                    ],
                    'properties': {
                        'id': {
                            'type': 'integer',
                        },
                        'name': {
                            'type': 'string',
                        },
                        'dsp': {
                            'type': 'string',
                        },
                        'adr1': {
                            'type': 'string',
                        },
                        'adr2': {
                            'type': 'string',
                        },
                        'adr3': {
                            'type': 'string',
                        },
                        'adr4': {
                            'type': 'string',
                        },
                        'adr5': {
                            'type': 'string',
                        },
                        'adr6': {
                            'type': 'string',
                        },
                        'tel': {
                            'type': 'string',
                        },
                        'queries': {
                            'type': 'array',
                            'items': {
                                'type': 'object',
                                'required': ['id', 'name', 'count'],
                                'properties': {
                                    'id': {
                                        'type': 'integer',
                                    },
                                    'name': {
                                        'type': 'string',
                                    },
                                    'count': {
                                        'type': 'integer',
                                    },
                                },
                            },
                        },
                    },
                },
            }
        ),
    )
    def platform_details(self, request, platform_id, email, ip=None):
        return self.get('platform/%s/' % platform_id, email=email, ip=ip)

    @endpoint(
        name='platform',
        methods=['get', 'post'],
        pattern=r'^(?P<platform_id>[0-9]{1,10})/referent/$',
        example_pattern='{platform_id}/referent/',
        description_get=_('Get platform referents'),
        description_post=_('Create platform referent'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'statut': {
                    'description': _('Referent status'),
                    'example_value': 'Actif',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=3,
        post_json_schema={
            'type': 'object',
            'required': ['nom', 'prenom'],
            'properties': {
                'email': {
                    'type': 'string',
                    'maxLength': 78,
                    'pattern': '^(.*@.*)?$',
                },
                'nom': {
                    'type': 'string',
                    'maxLength': 28,
                },
                'prenom': {
                    'type': 'string',
                    'maxLength': 32,
                },
                'tel': {
                    'type': 'string',
                    'maxLength': 10,
                    'pattern': '^[0-9]{0,10}$',
                },
            },
        },
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'required': [
                        'id',
                        'nom',
                        'prenom',
                        'tel',
                        'email',
                        'role',
                        'status',
                    ],
                    'properties': {
                        'id': {
                            'type': 'integer',
                        },
                        'nom': {
                            'type': 'string',
                        },
                        'prenom': {
                            'type': 'string',
                        },
                        'tel': {
                            'type': 'string',
                        },
                        'email': {
                            'type': 'string',
                        },
                        'role': {
                            'enum': ['Coordonnateur', 'Accompagnateur'],
                        },
                        'statut': {
                            'enum': ['Actif', 'Inactif'],
                        },
                    },
                },
            }
        ),
    )
    def platform_referent(self, request, platform_id, email, ip=None, statut=None, post_data=None):
        if request.method == 'GET':
            response = self.get('platform/%s/referent/' % platform_id, email=email, ip=ip)
            if statut:
                data = []
                for referent in response.get('data', []):
                    if referent.get('statut') != statut:
                        continue
                    data.append(referent)
                response['data'] = data
            return response
        else:
            return self.post('platform/%s/referent/' % platform_id, email=email, ip=ip, json=post_data)

    # BUG, methods and post are incompatible
    platform_referent.endpoint_info.methods.append('get')

    @endpoint(
        name='platform',
        methods=['post'],
        pattern=r'^(?P<platform_id>[0-9]{1,10})/referent/(?P<referent_id>[0-9]{1,10})/$',
        example_pattern='{platform_id}/referent/{referent_id}/',
        description=_('Update platform referent'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'referent_id': {
                    'description': _('Referent numeric identifier'),
                    'example_value': '9',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=3.5,
        post_json_schema={
            'type': 'object',
            'required': ['nom', 'prenom', 'statut'],
            'properties': {
                'email': {
                    'type': 'string',
                    'maxLength': 78,
                    'pattern': '^(.*@.*)?$',
                },
                'nom': {
                    'type': 'string',
                    'maxLength': 28,
                },
                'prenom': {
                    'type': 'string',
                    'maxLength': 32,
                },
                'tel': {
                    'type': 'string',
                    'maxLength': 10,
                    'pattern': '^[0-9]{0,10}$',
                },
                'statut': {'enum': ['C', 'A']},
            },
        },
        json_schema_response=response_schema(),
    )
    def platform_referent_update(self, request, platform_id, referent_id, email, ip=None, post_data=None):
        return self.put(
            'platform/%s/referent/%s/' % (platform_id, referent_id), email=email, ip=ip, json=post_data
        )

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/$',
        example_pattern='{platform_id}/beneficiaire/',
        description_get=_('Get platform beneficiaries'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'page': {
                    'description': _('Page number'),
                    'example_value': '1',
                },
                'query': {
                    'description': _('Query numeric identifier'),
                    'example_value': '2',
                },
                'nom': {
                    'description': _('Beneficiary last name'),
                    'example_value': 'Doe',
                },
                'prenom': {
                    'description': _('Beneficiary last name'),
                    'example_value': 'John',
                },
                'matricule': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '1234',
                },
                'referent': {
                    'description': _('Referent numeric identifier'),
                    'example_value': '5678',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=4,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'required': [
                        'id',
                        'civilite',
                        'nom',
                        'prenom',
                        'date_naissance',
                        'actif',
                        'matricule',
                        'commune',
                        'code_pi',
                        'referent',
                        'date_deb_affectation',
                        'consulte',
                        'toppersdrodevorsa',
                    ],
                    'properties': {
                        'id': {
                            'type': 'integer',
                        },
                        'civilite': {
                            'enum': ['MR', 'MME'],
                        },
                        'nom': {
                            'type': 'string',
                        },
                        'prenom': {
                            'type': 'string',
                        },
                        'date_naissance': {
                            'type': 'string',
                            'format': 'date',
                        },
                        'actif': OUI_NON_ENUM,
                        'matricule': {
                            'type': 'string',
                        },
                        'code_postal': {
                            'type': 'string',
                        },
                        'commune': {
                            'type': 'string',
                        },
                        'communcode_pi': {
                            'type': 'string',
                        },
                        'referent': {
                            'type': 'string',
                        },
                        'date_deb_affectation': DATE_SCHEMA,
                        'consulte': OUI_NON_ENUM,
                        'toppersdrodevorsa': OUI_NON_ENUM,
                    },
                },
            }
        ),
    )
    def platform_beneficiaire(
        self,
        request,
        platform_id,
        email,
        ip=None,
        page=None,
        query=None,
        nom=None,
        prenom=None,
        matricule=None,
        referent=None,
        id=None,
    ):
        params = {}
        for key in ['page', 'query', 'nom', 'prenom', 'matricule', 'referent', 'id']:
            if key in locals():
                params[key] = locals()[key]
        return self.get('platform/%s/beneficiaire/' % platform_id, email=email, ip=ip, params=params)

    def csv_response(self, name, data, filename):
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = f'attachment; filename="{filename}"'
        # write Unicode BOM to the response stream
        response.write(b'\xef\xbb\xbf')
        csv_columns = self.get_columns(name)
        names = [name for name, title in csv_columns]
        titles = [title for name, title in csv_columns]
        writer = csv.writer(response, delimiter=';')
        writer.writerow(titles)
        for row in data:
            writer.writerow(str(row.get(name) or '') for name in names)
        return response

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/csv/$',
        example_pattern='{platform_id}/beneficiaire/csv/',
        description_get=_('Get platform beneficiaries as CSV'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'page': {
                    'description': _('Page number'),
                    'example_value': '1',
                },
                'query': {
                    'description': _('Query numeric identifier'),
                    'example_value': '2',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=4.5,
    )
    def platform_beneficiaire_csv(
        self,
        request,
        platform_id,
        email,
        ip=None,
        page=None,
        query=None,
        nom=None,
        prenom=None,
        matricule=None,
        referent=None,
    ):
        params = {}
        if query:
            params['query'] = query
        if query == '0':
            for key in ['nom', 'prenom', 'matricule', 'referent']:
                if locals().get(key):
                    params[key] = locals()[key]
        content = self.get('platform/%s/beneficiaire/csv/' % platform_id, email=email, ip=ip, params=params)
        date = localtime(now()).strftime('%Y-%m-%d_%H:%M')
        return self.csv_response('beneficiaire', data=content['data'], filename=f'beneficiaire-{date}.csv')

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/',
        description=_('Get beneficiary details'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=5,
        json_schema_response=response_schema(
            {
                'type': 'object',
                'required': [
                    'id',
                    'civilite',
                    'nom',
                    'prenom',
                    'date_naissance',
                    'actif',
                    'matricule',
                    'code_pi',
                    'referent',
                    'adresse',
                    'age',
                    'commentaire_ref',
                    'conjoint',
                    'droit',
                    'enfants',
                    'lib_code_pi',
                    'nomnaiss',
                    'numdemrsa',
                    'situation_familiale',
                ],
                'properties': {
                    'id': {'type': 'integer'},
                    'civilite': {'enum': ['MR', 'MME']},
                    'nom': {'type': 'string'},
                    'prenom': {'type': 'string'},
                    'date_naissance': DATE_SCHEMA,
                    'actif': OUI_NON_ENUM,
                    'matricule': {'type': 'string'},
                    'code_pi': {'type': 'string'},
                    'referent': {
                        'type': 'object',
                        'required': ['id', 'nom', 'prenom'],
                        'properties': {
                            'id': {'type': 'integer'},
                            'nom': {'type': 'string'},
                            'prenom': {'type': 'string'},
                        },
                    },
                    'adresse': {
                        'type': 'object',
                        'required': ['adr2', 'adr3', 'adr4', 'adr5', 'adr6'],
                        'properties': {
                            'adr2': {'type': 'string'},
                            'adr3': {'type': 'string'},
                            'adr4': {'type': 'string'},
                            'adr5': {'type': 'string'},
                            'adr6': {'type': 'string'},
                        },
                    },
                    'age': {'type': 'string'},
                    'commentaire_ref': {'type': 'string'},
                    'conjoint': {
                        'type': 'object',
                        'required': ['id', 'age', 'prenom', 'nom', 'plateforme'],
                        'properties': {
                            'id': {'type': 'integer'},
                            'age': {'type': 'string'},
                            'nom': {'type': 'string'},
                            'prenom': {'type': 'string'},
                            'plateforme': {'type': 'string'},
                        },
                    },
                    'droit': {
                        'type': 'object',
                        'required': ['date_demande', 'etat', 'motif', 'toppersdrodevorsa'],
                        'properties': {
                            'date_demande': {'type': 'string', 'format': 'date'},
                            'etat': {'type': 'string'},
                            'motif': {'type': 'string'},
                            'toppersdrodevorsa': OUI_NON_ENUM,
                        },
                    },
                    'enfants': {
                        'type': 'array',
                        'items': {
                            'type': 'object',
                            'required': ['nom', 'prenom', 'age'],
                            'properties': {
                                'age': {'type': 'string'},
                                'nom': {'type': 'string'},
                                'prenom': {'type': 'string'},
                            },
                        },
                    },
                    'lib_code_pi': {'type': 'string'},
                    'nomnaiss': {'type': 'string'},
                    'numdemrsa': {'type': 'string'},
                    'situation_familiale': {
                        'type': 'object',
                        'required': ['date_debut', 'libelle'],
                        'properties': {
                            'date_debut': {'type': 'string', 'format': 'date'},
                            'libelle': {'type': 'string'},
                        },
                    },
                },
            }
        ),
    )
    def platform_beneficiaire_detail(self, request, platform_id, beneficiary_id, email, ip=None):
        return self.get('platform/%s/beneficiaire/%s/' % (platform_id, beneficiary_id), email=email, ip=ip)

    @endpoint(
        name='platform',
        methods=['post'],
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/telephone/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/telephone/',
        description=_('Create beneficiary\'s telephone'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=5.1,
        post_json_schema={
            'type': 'object',
            'required': ['tel'],
            'properties': {
                'tel': {
                    'type': 'string',
                    'maxLength': 10,
                    'pattern': '^[0-9]{0,10}$',
                },
                'commentaire': {
                    'type': 'string',
                },
            },
        },
        json_schema_response=response_schema(),
    )
    def platform_beneficiaire_telephone(
        self, request, platform_id, beneficiary_id, email, post_data, ip=None
    ):
        return self.post(
            'platform/%s/beneficiaire/%s/telephone/' % (platform_id, beneficiary_id),
            email=email,
            ip=ip,
            json=post_data,
        )

    @endpoint(
        name='platform',
        methods=['post', 'delete'],
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        'telephone/(?P<numtel>[0-9]{1,10})/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/telephone/{numtel}/',
        description_post=_('Update beneficiary\'s telephone comment'),
        description_delete=_('Delete beneficiary\'s telephone'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
                'numtel': {
                    'description': _('Beneficiary\'s telephone number'),
                    'example_value': '0699999999',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=5.2,
        post_json_schema={
            'type': 'object',
            'required': ['commentaire'],
            'properties': {
                'commentaire': {
                    'type': 'string',
                },
            },
        },
        json_schema_response=response_schema(),
    )
    def platform_beneficiaire_telephone_update_or_delete(
        self, request, platform_id, beneficiary_id, numtel, email, post_data=None, ip=None
    ):
        if request.method == 'POST':
            return self.put(
                'platform/%s/beneficiaire/%s/telephone/%s/' % (platform_id, beneficiary_id, numtel),
                email=email,
                ip=ip,
                json=post_data,
            )
        if request.method == 'DELETE':
            return self.delete(
                'platform/%s/beneficiaire/%s/telephone/%s/' % (platform_id, beneficiary_id, numtel),
                email=email,
                ip=ip,
            )

    # BUG, methods and post are incompatible
    platform_beneficiaire_telephone_update_or_delete.endpoint_info.methods.append('delete')

    @endpoint(
        name='platform',
        methods=['post'],
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/email/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/email/',
        description=_('Create beneficiary\'s email'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=5.1,
        post_json_schema={
            'request_body': {
                'schema': {
                    'application/json': {
                        'type': 'object',
                        'required': ['courriel'],
                        'properties': {
                            'courriel': {
                                'type': 'string',
                                'pattern': '^(.*@.*)?$',
                            },
                            'commentaire': {
                                'type': 'string',
                            },
                        },
                    },
                },
            }
        },
        json_schema_response=response_schema(),
    )
    def platform_beneficiaire_email(self, request, platform_id, beneficiary_id, email, post_data, ip=None):
        return self.post(
            'platform/%s/beneficiaire/%s/email/' % (platform_id, beneficiary_id),
            email=email,
            ip=ip,
            json=post_data,
        )

    @endpoint(
        name='platform',
        methods=['post', 'delete'],
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        'email/(?P<courriel>[^/]+)/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/email/{courriel}/',
        description_post=_('Update beneficiary\'s email comment'),
        description_delete=_('Delete beneficiary\'s email'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
                'courriel': {
                    'description': _('Beneficiary\'s email number'),
                    'example_value': '0699999999',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=5.2,
        post_json_schema={
            'type': 'object',
            'required': ['commentaire'],
            'properties': {
                'commentaire': {
                    'type': 'string',
                },
            },
        },
        json_schema_response=response_schema(),
    )
    def platform_beneficiaire_email_update_or_delete(
        self, request, platform_id, beneficiary_id, courriel, email, post_data=None, ip=None
    ):
        if request.method == 'POST':
            return self.put(
                'platform/%s/beneficiaire/%s/email/%s/' % (platform_id, beneficiary_id, courriel),
                email=email,
                ip=ip,
                json=post_data,
            )
        if request.method == 'DELETE':
            return self.delete(
                'platform/%s/beneficiaire/%s/email/%s/' % (platform_id, beneficiary_id, courriel),
                email=email,
                ip=ip,
            )

    # BUG, methods and post are incompatible
    platform_beneficiaire_email_update_or_delete.endpoint_info.methods.append('delete')

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/transport/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/transport/',
        description=_('Get beneficiary transport details'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=6,
        json_schema_response=response_schema(
            {
                'type': 'object',
                'required': ['cumuls'],
                'properties': {
                    'cumuls': {
                        'type': 'array',
                        'items': {
                            'type': 'object',
                            'required': ['duree', 'type'],
                            'properties': {
                                'duree': {'type': 'integer'},
                                'type': {'type': 'string'},
                            },
                        },
                    }
                },
            }
        ),
    )
    def platform_beneficiaire_transport(self, request, platform_id, beneficiary_id, email, ip=None):
        return self.get(
            'platform/%s/beneficiaire/%s/transport/' % (platform_id, beneficiary_id), email=email, ip=ip
        )

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/contrat/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/contrat/',
        description=_('Get beneficiary contracts'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=7,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'required': [
                        'id',
                        'clos',
                        'date_deb',
                        'date_fin',
                        'decision',
                        'duree',
                        'operateur',
                        'plateform',
                        'referent',
                        'retab',
                    ],
                    'properties': {
                        'id': {'type': 'integer'},
                        'clos': OUI_NON_ENUM,
                        'date_deb': DATE_SCHEMA,
                        'date_fin': DATE_SCHEMA,
                        'decision': {'type': 'string'},
                        'duree': {'type': 'integer'},
                        'operateur': {'type': 'string'},
                        'plateforme': {'type': 'string'},
                        'retab': OUI_NON_ENUM,
                    },
                },
            }
        ),
    )
    def platform_beneficiaire_contrat(self, request, platform_id, beneficiary_id, email, ip=None):
        return self.get(
            'platform/%s/beneficiaire/%s/contrat/' % (platform_id, beneficiary_id), email=email, ip=ip
        )

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/'
        r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        r'contrat/(?P<contract_id>[0-9]{1,10})/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/contrat/{contract_id}/',
        description=_('Get beneficiary contract details'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
                'contract_id': {
                    'description': _('Contract numeric identifier'),
                    'example_value': '7',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=8,
        json_schema_response=response_schema(
            {
                'type': 'object',
                'required': [
                    'id',
                    'commentaire',
                    'date_clos',
                    'date_cvs',
                    'date_deb',
                    'date_fin',
                    'date_retab',
                    'date_sign',
                    'decision',
                    'duree',
                    'motif_cvs',
                    'operateur',
                    'plateforme',
                    'referent',
                    'type_contrat',
                ],
                'properties': {
                    'id': {'type': 'integer'},
                    'commentaire': {'type': 'string'},
                    'date_clos': DATE_SCHEMA,
                    'date_cvs': DATE_SCHEMA,
                    'date_deb': DATE_SCHEMA,
                    'date_fin': DATE_SCHEMA,
                    'date_retab': DATE_SCHEMA,
                    'date_sign': DATE_SCHEMA,
                    'decision': {'type': 'string'},
                    'duree': {'type': 'integer'},
                    'motif_cvs': {'type': 'string'},
                    'operateur': {'type': 'string'},
                    'plateforme': {'type': 'string'},
                    'referent': {
                        'type': 'object',
                        'required': ['commentaire', 'nom', 'prenom'],
                        'properties': {
                            'commentaire': {'type': 'string'},
                            'nom': {'type': 'string'},
                            'prenom': {'type': 'string'},
                        },
                    },
                    'type_contrat': {'type': 'string'},
                },
            }
        ),
    )
    def platform_beneficiaire_contrat_detail(
        self, request, platform_id, beneficiary_id, contract_id, email, ip=None
    ):
        return self.get(
            'platform/%s/beneficiaire/%s/contrat/%s/' % (platform_id, beneficiary_id, contract_id),
            email=email,
            ip=ip,
        )

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/'
        r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        r'action/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/action/',
        description=_('Get beneficiary actions'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
                'clos': {
                    'description': _('Filter on closed status'),
                    'example_value': 'non',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=9,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'required': [
                        'id',
                        'contrat_id',
                    ],
                    'properties': {
                        'id': {'type': 'integer'},
                        'contrat_id': {'type': 'integer'},
                        'libelle': {'type': 'string'},
                        'date_preconisation': DATE_SCHEMA,
                        'date_deb': DATE_SCHEMA,
                        'date_fin': DATE_SCHEMA,
                        'validation': {
                            'enum': ['En cours', 'Oui', 'Non'],
                        },
                        'clos': OUI_NON_ENUM,
                    },
                },
            }
        ),
    )
    def platform_beneficiaire_action(self, request, platform_id, beneficiary_id, email, ip=None, clos=None):
        if clos and clos.lower() not in ['oui', 'non']:
            raise APIError(_('clos must be "oui" or "non"'))
        return self.get(
            'platform/%s/beneficiaire/%s/action/' % (platform_id, beneficiary_id),
            email=email,
            ip=ip,
            params={'clos': clos},
        )

    @endpoint(
        name='platform',
        methods=['get', 'post'],
        pattern=r'^(?P<platform_id>[0-9]{1,10})/'
        r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        r'action/(?P<action_id>[0-9]{1,10})/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/action/{action_id}/',
        description_get=_('Get beneficiary action details'),
        description_post=_('Update beneficiary action details'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
                'action_id': {
                    'description': _('Action numeric identifier'),
                    'example_value': '7',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=10,
        post_json_schema={
            'type': 'object',
            'properties': {
                'date_debut': DATE_SCHEMA,
                'date_fin': DATE_SCHEMA,
                'moticlodac': {'type': 'string'},
                'commentaire_ref': {'type': 'string', 'maxLength': 1000},
            },
        },
        json_schema_response=response_schema(
            {
                'type': 'object',
                'required': [
                    'id',
                    'contrat_id',
                ],
                'properties': {
                    'id': {'type': 'integer'},
                    'contrat_id': {'type': 'integer'},
                    'sac': {'type': 'string'},
                    'libelle': {'type': 'string'},
                    'date_preconisation': DATE_SCHEMA,
                    'date_deb': DATE_SCHEMA,
                    'date_fin': DATE_SCHEMA,
                    'date_cloture': DATE_SCHEMA,
                    'moticlodac': {'type': 'string'},
                    'lib_moticlodac': {'type': 'string'},
                    'validation': {
                        'enum': ['En cours', 'Oui', 'Non'],
                    },
                    'financement': {
                        'properties': {
                            'montant_demande': {'type': 'integer'},
                            'montant_accorde': {'type': 'integer'},
                        }
                    },
                    'commentaire_ref': {'type': 'string'},
                },
            }
        ),
    )
    def platform_beneficiaire_action_detail(
        self, request, platform_id, beneficiary_id, action_id, email, post_data=None, ip=None
    ):
        if request.method == 'POST':
            return self.put(
                'platform/%s/beneficiaire/%s/action/%s/' % (platform_id, beneficiary_id, action_id),
                email=email,
                ip=ip,
                json=post_data,
            )
        else:
            return self.get(
                'platform/%s/beneficiaire/%s/action/%s/' % (platform_id, beneficiary_id, action_id),
                email=email,
                ip=ip,
            )

    # bug
    platform_beneficiaire_action_detail.endpoint_info.methods.insert(0, 'get')

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/'
        r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        r'fondsaide/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/fondsaide/',
        description=_('Get beneficiary help funds'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=11,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'properties': {
                        'id': {'type': 'integer'},
                        'cod_tfi': {'type': 'string'},
                        'lib_tfi': {'type': 'string'},
                        'demande': {
                            'type': 'object',
                            'properties': {
                                'montant': {'type': 'number'},
                                'date': DATE_SCHEMA,
                            },
                        },
                        'avis_pi': {
                            'type': 'object',
                            'properties': {
                                'montant': {'type': 'number'},
                                'date': DATE_SCHEMA,
                                'avis': {'type': 'string'},
                            },
                        },
                        'avis_sai': {
                            'type': 'object',
                            'properties': {
                                'montant': {'type': 'number'},
                                'date': DATE_SCHEMA,
                            },
                        },
                        'clos': OUI_NON_ENUM,
                    },
                },
            }
        ),
    )
    def platform_beneficiaire_fondsaide(self, request, platform_id, beneficiary_id, email, ip=None):
        return self.get(
            'platform/%s/beneficiaire/%s/fondsaide/' % (platform_id, beneficiary_id),
            email=email,
            ip=ip,
        )

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/'
        r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        r'fondsaide/(?P<fondsaide_id>[0-9]{1,10})/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/fondsaide/{fondsaide_id}/',
        description=_('Get beneficiary help fund details'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
                'fondsaide_id': {
                    'description': _('Help fund numeric identifier'),
                    'example_value': '7',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=12,
        json_schema_response=response_schema(
            {
                "type": "object",
                "properties": {
                    "avis_pi": {
                        "type": "object",
                        "properties": {
                            "avis": {"type": "string"},
                            "date": DATE_SCHEMA,
                            "montant": {"type": "number"},
                        },
                    },
                    "budget": {
                        "type": "object",
                        "properties": {
                            "date_reception": {"type": "string"},
                            "justificatifs": {
                                "type": "array",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "conforme": {"type": "string"},
                                        "date_reception": DATE_SCHEMA,
                                        "date_relance": DATE_SCHEMA,
                                        "num_versement": {"type": "integer"},
                                        "reception": {"type": "string"},
                                        "type": {"type": "string"},
                                    },
                                },
                            },
                            "nombre_versements": {"type": "integer"},
                        },
                    },
                    "cloture": {
                        "type": "object",
                        "properties": {
                            "date_cloture": DATE_SCHEMA,
                            "date_relance": DATE_SCHEMA,
                        },
                    },
                    "code_tfi": {"type": "string"},
                    "decision_sai": {
                        "type": "object",
                        "properties": {
                            "date": DATE_SCHEMA,
                            "decision": {"type": "string"},
                            "montant": {"type": "number"},
                        },
                    },
                    "demande": {
                        "type": "object",
                        "properties": {
                            "date": DATE_SCHEMA,
                            "montant": {"type": "number"},
                        },
                    },
                    "id": {"type": "integer"},
                    "lib_tfi": {"type": "string"},
                    "recours": {
                        "type": "object",
                        "properties": {
                            "date_decision": DATE_SCHEMA,
                            "date_demande": DATE_SCHEMA,
                            "decision": {"type": "string"},
                            "montant": {"type": "string"},
                        },
                    },
                },
            }
        ),
    )
    def platform_beneficiaire_fondsaide_detail(
        self, request, platform_id, beneficiary_id, fondsaide_id, email, ip=None
    ):
        return self.get(
            'platform/%s/beneficiaire/%s/fondsaide/%s/' % (platform_id, beneficiary_id, fondsaide_id),
            email=email,
            ip=ip,
        )

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/'
        r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        r'affectation/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/affectation/',
        description=_('Get beneficiary affectations'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=13,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'properties': {
                        'id': {'type': 'integer'},
                        'dispositif': {'type': 'string'},
                        'plateforme': {'type': 'string'},
                        'code_pi': {'type': 'string'},
                        'referent': {'type': 'string'},
                        'date_deb': DATE_SCHEMA,
                        'origine': {'type': 'string'},
                    },
                },
            }
        ),
    )
    def platform_beneficiaire_affectation(self, request, platform_id, beneficiary_id, email, ip=None):
        return self.get(
            'platform/%s/beneficiaire/%s/affectation/' % (platform_id, beneficiary_id),
            email=email,
            ip=ip,
        )

    @endpoint(
        name='platform',
        methods=['post'],
        pattern=r'^(?P<platform_id>[0-9]{1,10})/'
        r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        r'reaffectation/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/reaffectation/',
        description=_('Reassign beneficiary'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=13.5,
        post_json_schema={
            'type': 'object',
            'properties': {
                'motif': {'type': 'string'},
                'commentaire_ref': {'type': 'string'},
            },
        },
        json_schema_response=response_schema(),
    )
    def platform_beneficiaire_reaffectation(
        self, request, platform_id, beneficiary_id, email, post_data, ip=None
    ):
        return self.post(
            'platform/%s/beneficiaire/%s/reaffectation/' % (platform_id, beneficiary_id),
            email=email,
            ip=ip,
            json=post_data,
        )

    @endpoint(
        name='platform',
        methods=['get', 'post'],
        pattern=r'^(?P<platform_id>[0-9]{1,10})/'
        r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        r'affectation/(?P<affectation_id>[0-9]{1,10})/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/affectation/{affectation_id}/',
        description_get=_('Get beneficiary affectation details'),
        description_post=_('Update beneficiary affectation details'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
                'affectation_id': {
                    'description': _('Help fund numeric identifier'),
                    'example_value': '7',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=14,
        post_json_schema={
            'type': 'object',
            'properties': {
                'rendezvous': {
                    'type': 'object',
                    'properties': {
                        'date_prise': DATE_SCHEMA,
                        'relance': {
                            'type': 'object',
                            'properties': {
                                'date': DATE_SCHEMA,
                                'motif': {'type': 'string'},
                            },
                        },
                        'date_reelle': DATE_SCHEMA,
                        'resultat': {'type': 'string'},
                    },
                },
                'commentaire_ref': {'type': 'string'},
            },
            'unflatten': True,
        },
        json_schema_response=response_schema(
            {
                'type': 'object',
                'properties': {
                    'id': {'type': 'integer'},
                    'dispositif': {'type': 'string'},
                    'plateforme': {'type': 'string'},
                    'referent': {
                        'type': 'object',
                        'properties': {
                            'nom': {'type': 'string'},
                            'prenom': {'type': 'string'},
                        },
                    },
                    'code_pi': {'type': 'string'},
                    'date_deb': DATE_SCHEMA,
                    'origin': {'type': 'string'},
                    'origine': {'type': 'string'},
                    'erreur': OUI_NON_ENUM,
                    'prescripteur': {
                        'type': 'object',
                        'properties': {
                            'type': {'type': 'string'},
                            'dispositif': {'type': 'string'},
                            'plateforme': {'type': 'string'},
                        },
                    },
                    'rendezvous': {
                        'type': 'object',
                        'properties': {
                            'date_prise': DATE_SCHEMA,
                            'relance': {
                                'type': 'object',
                                'properties': {
                                    'date': DATE_SCHEMA,
                                    'motif': {'type': 'string'},
                                    'lib_motif': {'type': 'string'},
                                },
                            },
                            'date_reelle': DATE_SCHEMA,
                            'resultat': {'type': 'string'},
                            'lib_resultat': {'type': 'string'},
                        },
                    },
                    'fin': {
                        'type': 'object',
                        'properties': {
                            'date': DATE_SCHEMA,
                            'motif': {'type': 'string'},
                            'lib_motif': {'type': 'string'},
                        },
                    },
                    'commentaire_ref': {'type': 'string'},
                },
            }
        ),
    )
    def platform_beneficiaire_affectation_detail(
        self, request, platform_id, beneficiary_id, affectation_id, email, post_data=None, ip=None
    ):
        if request.method == 'POST':
            return self.put(
                'platform/%s/beneficiaire/%s/affectation/%s/' % (platform_id, beneficiary_id, affectation_id),
                email=email,
                ip=ip,
                json=post_data,
            )
        else:
            return self.get(
                'platform/%s/beneficiaire/%s/affectation/%s/' % (platform_id, beneficiary_id, affectation_id),
                email=email,
                ip=ip,
            )

    platform_beneficiaire_affectation_detail.endpoint_info.methods.insert(0, 'get')

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/' r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/' r'convo/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/convo/',
        description=_('Get beneficiary convocations'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=15,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    "type": "object",
                    "properties": {
                        "convos_par_motif": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "nombre": {"type": "integer"},
                                    "motif": {"type": "string"},
                                },
                            },
                        },
                        "derniere_consequence": {
                            "type": "object",
                            "properties": {
                                "date": DATE_SCHEMA,
                                "consequence": {"type": "string"},
                            },
                        },
                    },
                },
            }
        ),
    )
    def platform_beneficiaire_convo(self, request, platform_id, beneficiary_id, email, ip=None):
        return self.get(
            'platform/%s/beneficiaire/%s/convo/' % (platform_id, beneficiary_id),
            email=email,
            ip=ip,
        )

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/'
        r'beneficiaire/(?P<beneficiary_id>[0-9]{1,10})/'
        r'emploi/$',
        example_pattern='{platform_id}/beneficiaire/{beneficiary_id}/emploi/',
        description=_('Get beneficiary employments'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'beneficiary_id': {
                    'description': _('Beneficiary numeric identifier'),
                    'example_value': '12',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=16,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    "type": "object",
                    "properties": {
                        "id": {"type": "string"},
                        "code_axe": {"type": "string"},
                        "lib_axe": {"type": "string"},
                        "code_rome": {"type": "string"},
                        "lib_rome": {"type": "string"},
                        "code_categorie": {"type": "string"},
                        "lib_categorie": {"type": "string"},
                        "lib_secteur": {"type": "string"},
                        "lib_niveau": {"type": "string"},
                        "lib_modalite": {"type": "string"},
                        "date_inscription": DATE_SCHEMA,
                        "date_sortie": DATE_SCHEMA,
                        "motif_sortie": {"type": "string"},
                        "date_dernier_ent": DATE_SCHEMA,
                    },
                },
            }
        ),
    )
    def platform_beneficiaire_emploi(self, request, platform_id, beneficiary_id, email, ip=None):
        return self.get(
            'platform/%s/beneficiaire/%s/emploi/' % (platform_id, beneficiary_id),
            email=email,
            ip=ip,
        )

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/' r'facturation/periodes/',
        example_pattern='{platform_id}/facturation/periodes/',
        description=_('Get invoicing periods'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=17,
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    "type": "object",
                    "properties": {
                        "id": {"type": "string"},
                        "text": {"type": "string"},
                        "date_deb": {"type": "string"},
                        "date_fin": {"type": "string"},
                    },
                },
            }
        ),
    )
    def platform_facturation_periodes(self, request, platform_id, email, ip=None):
        response = self.get(
            'platform/%s/facturation/periods/' % platform_id,
            email=email,
            ip=ip,
        )
        for period in response.get('data') or []:
            period.setdefault('id', period['text'])
            period['csv_url'] = (
                request.build_absolute_uri(
                    reverse(
                        'generic-endpoint',
                        kwargs={
                            'slug': self.slug,
                            'connector': self.get_connector_slug(),
                            'endpoint': 'platform',
                            'rest': '%s/facturation/csv/' % platform_id,
                        },
                    )
                )
                + '?'
                + urlencode({'date_deb': period['date_deb'], 'date_fin': period['date_fin']})
            )
        return response

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/facturation/csv/$',
        example_pattern='{platform_id}/facturation/csv/',
        description_get=_('Get platform invoicing as CSV'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
                'date_deb': {
                    'description': _('Start date'),
                    'example_value': '2021-10-01',
                    'type': 'string',
                    'format': 'date',
                },
                'date_fin': {
                    'description': _('End date'),
                    'example_value': '2021-12-31',
                    'type': 'string',
                    'format': 'date',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=4.8,
    )
    def platform_facturation_csv(
        self,
        request,
        date_deb,
        date_fin,
        platform_id,
        email,
        ip=None,
    ):
        url = 'platform/%s/facturation/csv' % platform_id
        content = self.get(url, email=email, ip=ip, params={'date_deb': date_deb, 'date_fin': date_fin})
        filename = f'facturation-{date_deb}-{date_fin}.csv'
        return self.csv_response('facturation', content.get('data') or [], filename=filename)

    @endpoint(
        name='platform',
        pattern=r'^(?P<platform_id>[0-9]{1,10})/beneficiaire/sorti/csv/$',
        example_pattern='{platform_id}/beneficiaire/sorti/csv/',
        description_get=_('Get platform beneficiaries removed in the last 90 days'),
        perm='can_access',
        parameters=parameters(
            {
                'platform_id': {
                    'description': _('Platform numeric identifier'),
                    'example_value': '11',
                },
            }
        ),
        display_category=_('Platform'),
        display_order=4.9,
    )
    def platform_beneficiaire_sorti_csv(
        self,
        request,
        platform_id,
        email,
        ip=None,
    ):
        url = 'platform/%s/beneficiaire/sorti/csv' % platform_id
        content = self.get(url, email=email, ip=ip)
        date = localtime(now()).strftime('%Y-%m-%d_%H:%M')
        return self.csv_response(
            'sorti', data=content.get('data') or [], filename=f'beneficiaire-sorti-{date}.csv'
        )

    @endpoint(
        name='sous-action',
        description=_('Get sub-actions'),
        perm='can_access',
        parameters=parameters(),
        json_schema_response=response_schema(
            {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'required': ['id', 'text'],
                    'properties': {
                        'id': {
                            'type': 'string',
                        },
                        'text': {
                            'type': 'string',
                        },
                        'description': {
                            'type': 'string',
                        },
                    },
                },
            }
        ),
    )
    def sous_action(self, request, email, ip=None):
        return self.get('sousaction/', email=email, ip=ip)


DEFAULTS = {
    'beneficiaire_csv_columns': [
        "NUM_CAF",
        "CODE_PER",
        "NOM_PER",
        "PRENOM_PER",
        "DTNAI_PER",
        "ACTIF_PER",
        "CODE_PI",
        "LIB_CODE_PI",
        "TOPPERSDRODEVORSA",
        "LIB_ETATDOSRSA",
        "LIB_MOTIF_ETATDOSRSA",
        "NB_JOUR_DEPUIS_ARR",
        "DATE_DEB",
        "DATE_1IERE_CONS",
        "DATE_DERNIERE_CONSULT",
        "DATE_REELLE_RDV",
        "NUM_CINS",
        "DATE_SIGN",
        "DATE_DEB_CI",
        "DATE_FIN_CI",
        "REFERENT_CI",
        "ACTION_EN_COURS",
        "DELAI_REGUL",
        "PROC_EN_COURS",
        "REFERENT_AFFECTATION",
        'COMPL1_ADR',
        'COMPL2_ADR',
        'VOIE_ADR',
        'LIEU_DISTRIB_ADR',
        'CP_ADR',
        'VILLE_ADR',
        'INSEE_ADR',
    ],
    'facturation_csv_columns': [
        "PLATEFORME",
        "MATRICULE",
        "NOM",
        "PRENOM",
        "DTNAI",
        "GENRE",
        "ROLE",
        "CODE_POSTAL",
        "COMMUNE",
        "DATE_SIGN",
        "DATE_DEB",
        "DUREE",
        "DATE_FIN",
        "COEFFICIENT",
    ],
    'sorti_csv_columns': [
        "NUM_CAF",
        "CODE_PER",
        "NOM_PER",
        "PRENOM_PER",
        "DTNAI_PER",
        "CP_PER",
        "COMMUNE_PER",
        "ACTIF_PER",
        "CODE_PI",
        "LIB_CODE_PI",
        "TOPPERSDRODEVORSA",
        "LIB_ETATDOSRSA",
        "LIB_MOTIF_ETATDOSRSA",
        "PLT_DT_DEB_AFF",
        "PLT_DT_FIN_AFF",
        "PLT_MOTIF_FIN_ACC",
        "PLT_COMMENTAIRE_REF",
        "PLT_NUM_CI",
        "PLT_PLATEFORME_CI",
        "PLT_OPERATEUR_CI",
        "PLT_REFERENT_CI",
        "PLT_DECISION_CI",
        "PLT_DUREE_CI",
        "PLT_DATE_DEB_CI",
        "PLT_DATE_FIN_CI",
        "NOUVEAU_DT_DEB_AFF",
        "NOUVEAU_AFF",
        "NOUVEAU_COMMENTAIRE_PI",
        "NOUVEAU_NUM_CI",
        "NOUVEAU_PLATEFORME_CI",
        "NOUVEAU_OPERATEUR_CI",
        "NOUVEAU_REFERENT_CI",
        "NOUVEAU_DECISION_CI",
        "NOUVEAU_DUREE_CI",
        "NOUVEAU_DATE_DEB_CI",
        "NOUVEAU_DATE_FIN_CI",
    ],
}
