"""Module contains class Neo4j responsible for storing CVE data to Neo4j database."""

from neo4jclient.CveConnectorClient import CVEConnectorClient
from cve_connector.vendor_cve.implementation.utilities.utility_functions import string_to_date


class Neo4j:
    """
    Class responsible for storing CVE data to Neo4j database.
    """
    def __init__(self, neo4jpasswd):
        self.password = neo4jpasswd
        self.client = CVEConnectorClient(password=neo4jpasswd)

    def store_data_from_vendor(self, entries_list, logger):
        """
        Stores CVEs in the database.

        :param entries_list: list of CVEs
        :param logger: logger for the method
        :return: number of CVEs created in the database
        """
        cve_count_updated = 0
        for entry in entries_list:
            cve_count_updated += self.store_node_by_cve_id(entry, logger)
        return cve_count_updated

    def store_node_by_cve_id(self, node, logger):
        """
        Stores specific CVE in the database.

        :param node: CVE entry
        :param logger: logger for the method
        :return: count of updated CVEs
        """
        res = self.client.get_cve_patch(node.cve_id)

        # res might be None
        patch = res or node.patch_available

        nvd_published_date = None
        cve_count_updated = 0

        data = self.client.get_cve(node.cve_id).single()
        if data:
            if 'cve' in data:
                cve_record = data['cve']
                if 'published_date' in cve_record:
                    nvd_published_date = cve_record['published_date']

        if self.client.cve_exists(node.cve_id):
            earlier_date = self.get_earlier_date(node.published, nvd_published_date)
            if earlier_date is not None:
                earlier_date = earlier_date.isoformat()
            self.client.update_cve_from_vendor(
                CVE_id=node.cve_id,
                patched=str(patch),
                description=node.description,
                published_date=earlier_date
            )
            cve_count_updated += 1
            logger.info("CVE updated: {}".format(node.cve_id))

        return cve_count_updated

    def get_earlier_date(self, date1, date2):
        """
        Compares two dates and returns the earlier.

        :param date1: date
        :param date2: date
        :return: earlier date
        """
        date_format = "%Y-%m-%d"
        if not date1:
            return date2
        if not date2:
            return date1
        if isinstance(date1, str):
            date1 = string_to_date(date1, date_format)
        if isinstance(date2, str):
            date2 = string_to_date(date2, date_format)
        min_date = min(date1, date2)
        return min_date.strftime(date_format)
