"""_____________________________________________________________________

:PROJECT: LARAsuite

*lara_django_base celery tasks*

:details: lara_django_base celery tasks.
         -
:authors: mark doerr <mark.doerr@uni-greifswald.de>

.. note:: -
.. todo:: -
________________________________________________________________________
"""

from celery import shared_task
from celery.utils.log import get_task_logger
from django.apps import apps
from rdflib import Graph
from rdflib import URIRef
# from scidats import SciDatS

logger = get_task_logger(__name__)

def insert_query(query):
    """Insert metadata into triple store using SPARQL."""
    sparql = apps.get_app_config("lara_django_base").sparql

    sparql.setMethod("POST")

    try:
        sparql.setQuery(query)
        qres = sparql.query().convert()
        logger.debug("+++ insert result: %s", qres)

    except Exception:
        logger.exception("Exception occurred while inserting query: %s", query)


@shared_task
def semantic_data_to_triplestore(instance_name: str | None = None,
                                 data_model: str | None = None,
                                 attributes: dict | None = None,
                                 graph_urn: str | None = None):
    """
    Semantic data to triplestore celery task.

    Metadata is converted to semantic data (= owlready2 data) object,
    then triples are extracted from RDF graph
    and written to triple store using SPARQL.
    """
    # insert_semantics(sender, instance, **kwargs)
    # print(f"semantic_data_to_triplestore: {current_task.request.id}")
    # print(f"semantic_data_to_triplestore: {attributes}")

    lara_onto = apps.get_app_config("lara_django_base").lara_onto
    lara_onto_graph = apps.get_app_config("lara_django_base").lara_onto_graph

    data_model_class = getattr(lara_onto, data_model, None)
    if data_model_class is None:
        logger.error("Data model %s not found in lara_onto.", data_model)
        return
    semantic_data_class_instance = data_model_class(instance_name, **attributes)

    triples_str = ""
    for triple in lara_onto_graph.triples((URIRef(semantic_data_class_instance.iri), None, None)):
        triples_str += (
            triple[0].n3() + " " + triple[1].n3() + " " + triple[2].n3() + " .\n"
        )

    query = f"""INSERT INTO <{graph_urn}> {{ {triples_str} }}"""

    # logger.debug(f"+++ insert query:\n {query}")

    insert_query(query)


@shared_task
def extract_metadata_from_parquet_file(parquet_file_str : bytes | None = None) :
   """
      Extract metadata from parquet file.

      1. read parquet file
      2. extract metadata
      3. write metadata to triple store
      4. return metadata
   """
   graph_urn = "urn:sparql:lara:data"

   logger.debug("+++ BASE - extract_metadata_from_parquet_file:")
   return

   data_scidats = None #SciDatS()
   data_scidats.read_parquet(input_stream=parquet_file_str, base64encoding=False)

   # logger.debug("****** scidatas metadata:", data_scidats.metadata_core)

   # use rdflib to convert JSON-LD to RDF
   g = Graph()
   g.parse(data=data_scidats.metadata_jsonld, format="json-ld")

   # insert metadata into triple store using SPARQL
   logger.debug("****** insert metadata into triple store using SPARQL")

   #triples_str = g.serialize(format="turtle")
   #query = f"""INSERT INTO <{graph_urn}> {{ {triples_str} }}"""

   query = f"INSERT INTO <{graph_urn}> {{\n"
   for s, p, o in g:
      query += f"""    <{s}> <{p}> {f'<{o}>' if isinstance(o, URIRef) else f'"{o}"^^<{o.datatype}>' if hasattr(o, 'datatype') else f'"{o}"'} .\n"""  # noqa: E501
   query += "}"

   logger.debug("+++ insert query: \n%s\n", query)

   insert_query(query)

   return data_scidats.metadata_jsonld
