"""_____________________________________________________________________

:PROJECT: ChemDataReader

* Main module implementation *

:details:  Main module implementation.

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

from typing import IO

import json
import asyncio
from aiohttp import ClientSession

from chemdatareader import chemdatareader_logger
from chemdatareader.collectors.pubchem_data_models import PubChemRecord

import chemdatareader.chemdatacollector_builder_interface as cdcbi

from chemdatareader.cached_request import CachedRequest


class PubChemCollector(cdcbi.ChemDataCollectorInterface):
    def __init__(self, access_code: str = None) -> None:
        """Implementation of the ChemDatReader Interface"""
        self.logger = chemdatareader_logger.get_logger(__name__)

        self.access_code = access_code

        self.PubChemURL = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/"

        self.cached_request = CachedRequest()

    def test_connection(self) -> str:
        """connection test module

        :param name: person to greet
        :type name: str
        """
        self.logger.debug(f"connection to : {self.PubChemURL}")
        self.logger.debug(f"access code : {self.access_code}")
        return self.PubChemURL

    async def get_compounds_by_name(
        self, name_list: list[str] = [], operation: str = "record", output_format: str = "JSON"
    ):
        """
        get all compounds of a list of names or CAS numbers
        """
        self.compound_list = []
        self.operation = operation
        self.output_format = output_format

        async with ClientSession() as session:
            tasks = []
            for name in name_list:
                # task = asyncio.ensure_future(self._get_compound_by_name(name, session))
                tasks.append(self._get_compound_by_name(name, session))
            await asyncio.gather(*tasks, return_exceptions=True)

    async def _get_compound_by_name(self, name: str = None, session: ClientSession = None):
        """
        get compound by name or CAS number
        """
        self.logger.debug(f"get compound by name / CAS : {name}")
        print(f"get compound by name / CAS --: {name}")

        response = await self.cached_request.get(
            session=session, url="/".join([self.PubChemURL, name, self.operation, self.output_format])
        )
        self.compound_list.append(response)

        if self.output_format == "JSON" and self.operation == "record":
            self.parse_record(response)

    def parse_record(self, record_json: str = None):
        """
        parse record
        """
        # self.logger.debug(f"parse record : {record}")
        # self.compound_list.append(response)
        record = PubChemRecord.model_validate_json(record_json)

        # add to record list

    def properties_to_dict(self, record: PubChemRecord):
        """
        convert properties to dict
        """
        for compound in record.PC_Compounds:
            properties_dict = {}
            for prop in compound.props:
                if prop.urn.name is not None:
                    key = prop.urn.name.replace(" ", "")
                key += prop.urn.label.replace(" ", "")
                value = prop.value.sval or prop.value.fval or prop.value.binary
                properties_dict[key] = value

            # Now you can use the properties_dict
            print(properties_dict)

            # convert properties to JSON

            properties_json = json.dumps(properties_dict)
            print(properties_json)


class PubChemServiceBuilder(cdcbi.ChemDatCollectorBuilderInterface):
    def __init__(self):
        self._instance = None

    def __call__(self, pubchem_client_key, pubchem_client_secret, **_ignored):
        if not self._instance:
            access_code = self.authorize(pubchem_client_key, pubchem_client_secret)
            print(f"authorised access_code : {access_code}")
            self._instance = PubChemCollector(access_code)
        return self._instance

    def authorize(self, key, secret):
        return "MY_PUBCHEM_ACCESS_CODE"


cdcbi.services.register_builder("pubchem", PubChemServiceBuilder())
