import urllib.request
import os
import re
import logging
from datetime import datetime, timedelta
from functools import lru_cache
import psycopg2

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()

class FdsnExtender:
    """
    Used to manage the correspondance between a short network code and an extended network code.
    Correspondance is made using the metadata
    """
    tempo_network_re = '^[0-9XYZ][0-9A-Z]$'

    def __init__(self, dburi="postgresql://resifinv_ro@resif-pgpreprod.u-ga.fr/resifInv-Preprod"):
        """
        Returns a class instance.
        :param baseurl: The base URL to get the FDSN webservice from. Default is at RESIF.
        :type baseurl: string
        """
        self.resifinv_dburi = os.getenv('RESIFINV_DBURI', dburi)

##    This does not work
##    def cache_clear(self):
##        """
##        To clear LRU cache from functions.
##        This is usefull when the database changed.
##        Not sure I will implement it.
##        The program has no way to determine when the cache should be cleared. A TTL would be an antipattern.
##        """
##        extend.cache_clear()
##        extend_with_station.cache_clear()
##        return True

    @lru_cache(maxsize=10000)
    def extend(self, net, year):
        """
        Use network code and a year to return the extended network name.
        Require access to the resifInv database.
        :param net: the FDSN network code.
        :param year: a given year.
        :type net: string
        :type year: int
        """
        extcode = net
        request = "select start_year from networks where network=%s and %s between start_year and end_year"
        request_params = (net, year)
        # Only extend temporary networks
        if re.match(self.tempo_network_re, extcode):
            try:
                with psycopg2.connect(self.resifinv_dburi) as conn:
                    with conn.cursor() as curs:
                        logger.debug(curs.mogrify(request, request_params))
                        curs.execute(request, request_params)
                        if curs.rowcount > 0 :
                            extcode = f"{net}{curs.fetchone()[0]}"
                        else:
                            raise ValueError("Unable to extend network name %s from year %s", net, year)
            except psycopg2.Error as err:
                logger.error(err)
            except ValueError as err:
                raise err
        return extcode

    @lru_cache(maxsize=10000)
    def extend_with_station(self, net, sta):
        """
        Extend the network code with the short code and a station.
        Require access to the resifInv database.
        :param net: the FDSN network code.
        :param year: a given year.
        :type network_code: string
        :type year: int
        """
        extcode=net
        if sta == "":
            request = "select network,start_year,end_year from networks where network=%s and end_year < 2500"
            request_params = (net,)
        else:
            request = 'select networks.network,networks.start_year,networks.end_year from (select network_id from station where station=%s) as station inner join networks ON station.network_id = networks.network_id'
            request_params = (sta,)
        try:
            with psycopg2.connect(self.resifinv_dburi) as conn:
                with conn.cursor() as curs:
                    logger.debug(curs.mogrify(request, request_params))
                    curs.execute(request, request_params)
                    results = curs.fetchall()
                    for r in results:
                        logger.debug("result : %s",r)
                        if r[0] == net:
                            if r[2] < 2500:
                                extcode = r[0]+str(r[1])
                                break
        except Exception as err:
            logger.error(err)
        logger.info("%s, %s extended to %s",net, sta, extcode)
        return extcode
