#!/usr/bin/env python3
import pytest
from numpy import isnan
from hashlib import sha256

from rdflib import Namespace
from probs_runner import PROBS, QUANTITYKIND, answer_queries
from numpy.testing import assert_allclose
from decimal import Decimal
#from uuid import uuid4


PRODCOM2016 = Namespace("http://w3id.org/probs-lab/data/prodcom/2016/")
PRODCOM2017 = Namespace("http://w3id.org/probs-lab/data/prodcom/2017/")
GEONAMES = Namespace("https://sws.geonames.org/")


def assert_exact_results(result, expected_value):
    assert len(result) == 1
    assert result[0].bound == PROBS.ExactBound
    assert_allclose(result[0].measurement, expected_value, rtol=1e-3)


def assert_no_measurement(result):
    assert len(result) == 1
    assert isnan(result[0].measurement)



class TestProdcomList2016:
    """Test PRODCOM List 2016 file conversion"""

    endpoint_data = [ "outputs/PRD_2016_20200617_185122.nt.gz" ]

    @pytest.mark.parametrize("code,parent,description", [
        ("20136700", "201367", "Roasted iron pyrites"),
        ("23121150", "231211", "Optical glass of HS 7003, 7004 or 7005, bent, edge-worked, engraved, etc."),
        ("271232", "2712", \
         "Boards and other bases, equipped with electrical switching or protecting apparatus, for a voltage > 1 000 V")
    ])
    
    def test_object_attributes(self, rdfox, code, parent, description):
        # test object with parent from PRODCOM 2016 list has correct attributes
        obj_name = "\"PRODCOM Object from Code " + code + "\""
        code_name = "\"" + code + "\""
        code_description = "\"" + description + "\""
        parent_name = "\"PRODCOM Object from Code " + parent + "\""
        query = r""" PREFIX ufpc: <http://w3id.org/probs-lab/data/prodcom/>
                     SELECT ?a WHERE {
                         ?a rdfs:label %s ;
                            :hasClassificationCode ?b .
                         ?b rdfs:label %s ;
                            :codeDescription %s ;
                            :partOfList ufpc:Prodcom2016List .
                         ?c rdfs:label %s ;
                            :objectComposedOf ?a .
                     } """ % (obj_name, code_name, code_description, parent_name)
        result = rdfox.query_records(query)
        assert len(result) == 1



    @pytest.mark.parametrize("code,description", [
        ("0710", "Mining of iron ores"), 
        ("1020", "Processing and preserving of fish, crustaceans and molluscs"),
        ("3230", "Manufacture of sports goods") 
    ])
    
    def test_object_no_parent(self, rdfox, code, description):
        # test object not having a parent from PRODCOM 2016 list has correct attributes
        obj_name = "\"PRODCOM Object from Code " + code + "\""
        code_name = "\"" + code + "\""
        code_description = "\"" + description + "\""
        query = r""" PREFIX ufpc: <http://w3id.org/probs-lab/data/prodcom/>
                     SELECT ?a WHERE {
                         ?a rdfs:label %s ;
                            :hasClassificationCode ?b .
                         ?b rdfs:label %s ;
                            :codeDescription %s ;
                            :partOfList ufpc:Prodcom2016List .
                         FILTER NOT EXISTS {
                            ?c :objectComposedOf ?a .
                         }
                     } """ % (obj_name, code_name, code_description)
        result = rdfox.query_records(query)
        assert len(result) == 1



class TestProdcomList2017:
    """Test PRODCOM List 2017 file conversion"""

    endpoint_data = [ "outputs/PRD_2017_20200617_185035.nt.gz" ]

    @pytest.mark.parametrize("code,parent,description", [
        ("104125", "1041", "Palm oil, crude"),
        ("20121973", "201219", "Molybdenum oxides and hydroxides"),
        ("26601300", "266013", "Ultraviolet or infrared apparatus used in medical, surgical, dental or veterinary sciences")
    ])
    
    def test_object_attributes(self, rdfox, code, parent, description):
        # test object with parent from PRODCOM 2017 list has correct attributes
        obj_name = "\"PRODCOM Object from Code " + code + "\""
        code_name = "\"" + code + "\""
        code_description = "\"" + description + "\""
        parent_name = "\"PRODCOM Object from Code " + parent + "\""
        query = r""" PREFIX ufpc: <http://w3id.org/probs-lab/data/prodcom/>
                     SELECT ?a WHERE {
                         ?a rdfs:label %s ;
                            :hasClassificationCode ?b .
                         ?b rdfs:label %s ;
                            :codeDescription %s ;
                            :partOfList ufpc:Prodcom2017List .
                         ?c rdfs:label %s ;
                            :objectComposedOf ?a .
                     } """ % (obj_name, code_name, code_description, parent_name)
        result = rdfox.query_records(query)
        assert len(result) == 1



    @pytest.mark.parametrize("code,description", [
        ("1083", "Processing of tea and coffee"), 
        ("1723", "Manufacture of paper stationery"),
        ("0099t", "T-Codes") 
    ])
    
    def test_object_no_parent(self, rdfox, code, description):
        # test object not having a parent from PRODCOM 2017 list has correct attributes
        obj_name = "\"PRODCOM Object from Code " + code + "\""
        code_name = "\"" + code + "\""
        code_description = "\"" + description + "\""
        query = r""" PREFIX ufpc: <http://w3id.org/probs-lab/data/prodcom/>
                     SELECT ?a WHERE {
                         ?a rdfs:label %s ;
                            :hasClassificationCode ?b .
                         ?b rdfs:label %s ;
                            :codeDescription %s ;
                            :partOfList ufpc:Prodcom2017List .
                         FILTER NOT EXISTS {
                            ?c :objectComposedOf ?a .
                         }
                     } """ % (obj_name, code_name, code_description)
        result = rdfox.query_records(query)
        assert len(result) == 1


 
