# passerelle - uniform access to data 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; exclude 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.deepcopy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import inspect

from django.apps import apps
from django.utils import translation
from pyquery import PyQuery as pq

from passerelle.base.templatetags.passerelle import render_body_schemas, render_json_schema


def test_render_body_schemas(db):
    # FIXME: db should be required but the way ProxyLogger is initialized force an access to the DB
    def collect_schemas():
        for app in apps.get_app_configs():
            connector_model = None
            if not hasattr(app, 'get_connector_model'):
                continue
            connector_model = app.get_connector_model()
            if connector_model is None:
                continue
            for _, method in inspect.getmembers(connector_model, inspect.isfunction):
                if not hasattr(method, 'endpoint_info'):
                    continue
                if method.endpoint_info.post and method.endpoint_info.post.get('request_body', {}).get(
                    'schema'
                ):
                    yield method.endpoint_info.post['request_body']['schema'], method

    schemas = list(collect_schemas())
    assert schemas, 'no endpoint with schema found'
    for schema, endpoint in schemas:
        assert render_body_schemas(schema), 'failed for %s' % endpoint


def test_render_json_schema():
    SCHEMA = {
        '$schema': 'http://json-schema.org/draft-04/schema#',
        'type': 'object',
        'required': ['foo'],
        'additionalProperties': False,
        'properties': {
            'foo': {
                'type': 'string',
            },
        },
    }
    # Check that no unicode crash occurs
    with translation.override('fr'):
        render_json_schema(SCHEMA)


def test_render_enum_schema():
    assert (
        str(render_json_schema({'enum': [1, "aaa", [1]]}))
        == '<tt>1</tt> | <tt>&quot;aaa&quot;</tt> | <tt>[1]</tt>'
    )


def test_render_pattern_description():
    schema = {'type': 'object', 'properties': {'filename': {'type': 'string', 'pattern': 'abc'}}}
    assert 'abc' in render_json_schema(schema)

    schema['properties']['filename']['pattern_description'] = 'efg'
    assert 'abc' not in render_json_schema(schema) and 'efg' in render_json_schema(schema)


def test_render_required_properties():
    schema = {'type': 'object', 'required': ['filename'], 'properties': {'filename': {'type': 'string'}}}
    html = render_json_schema(schema)
    assert pq(html)('li span.required')
    assert pq(html)('li').text() == 'filename* : string'


def test_render_oneof_property_required():
    schema = {
        'type': 'object',
        'properties': {
            'a': {'type': 'string'},
            'b': {'type': 'string'},
        },
        'oneOf': [
            {'required': ['a']},
            {'required': ['b']},
        ],
    }
    assert "<b>oneOf</b> [ <em>required 'a'</em> | <em>required 'b'</em> ]" in render_json_schema(schema)
