# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

"""Test Invenio Records."""


import json
import os
import uuid

import pytest
from flask import Flask
from invenio_db.utils import drop_alembic_version_table
from jsonschema.exceptions import ValidationError
from sqlalchemy.orm.exc import NoResultFound

from invenio_records import InvenioRecords, Record
from invenio_records.errors import MissingModelError


def test_version():
    """Test version import."""
    from invenio_records import __version__

    assert __version__


def test_init():
    """Test extension initialization."""
    app = Flask("testapp")
    ext = InvenioRecords(app)
    assert "invenio-records" in app.extensions

    app = Flask("testapp")
    ext = InvenioRecords()
    assert "invenio-records" not in app.extensions
    ext.init_app(app)
    assert "invenio-records" in app.extensions


def test_db(testapp, db):
    """Test database backend."""
    with testapp.app_context():
        assert "records_metadata" in db.metadata.tables
        assert "records_metadata_version" in db.metadata.tables
        assert "transaction" in db.metadata.tables

    schema = {
        "type": "object",
        "properties": {
            "title": {"type": "string"},
            "field": {"type": "boolean"},
            "hello": {"type": "array"},
        },
        "required": ["title"],
    }
    data = {"title": "Test", "$schema": schema}
    from invenio_records.models import RecordMetadata as RM

    # Create a record
    with testapp.app_context():
        assert RM.query.count() == 0

        record_uuid = Record.create(data).id
        db.session.commit()

        assert RM.query.count() == 1
        db.session.commit()

    # Retrieve created record
    with testapp.app_context():
        record = Record.get_record(record_uuid)
        assert record.dumps() == data
        with pytest.raises(NoResultFound):
            Record.get_record(uuid.uuid4())
        record["field"] = True
        record = record.patch([{"op": "add", "path": "/hello", "value": ["world"]}])
        assert record["hello"] == ["world"]
        record.commit()
        db.session.commit()

    with testapp.app_context():
        record2 = Record.get_record(record_uuid)
        assert record2.model.version_id == 2
        assert record2["field"]
        assert record2["hello"] == ["world"]
        db.session.commit()

    # Cannot commit record without model (i.e. Record.create_record)
    with testapp.app_context():
        record3 = Record({"title": "Not possible"})
        with pytest.raises(MissingModelError):
            record3.commit()

    # Check invalid schema values
    with testapp.app_context():
        data = {
            "$schema": "http://json-schema.org/learn/examples/"
            "geographical-location.schema.json",
            "latitude": 42,
            "longitude": 42,
        }

        record_with_schema = Record.create(data).commit()
        db.session.commit()

        record_with_schema["latitude"] = "invalid"
        with pytest.raises(ValidationError):
            record_with_schema.commit()

    # Allow types overriding on schema validation
    with testapp.app_context():
        data = {"title": "Test", "hello": tuple(["foo", "bar"]), "$schema": schema}
        testapp.config["RECORDS_VALIDATION_TYPES"] = {}
        with pytest.raises(ValidationError):
            Record.create(data).commit()

        testapp.config["RECORDS_VALIDATION_TYPES"] = {"array": (list, tuple)}
        record_uuid = Record.create(data).commit()
        db.session.commit()
