import datetime
from dateutil import relativedelta

import requests
from mm_stats.auth import PostgresDb
from mm_stats.definitions import logger


def get_tasking_manager_dump_timestamp():
    """Get unix timestamp of last session in HOT Tasking Manager dump."""
    db = PostgresDb()
    sql = "set schema 'data_preparation';"
    sql += """
        select starttime
        from sessions s
        order by starttime desc
        limit 1
    """

    timestamp = db.retr_query(sql)[0][0]
    return timestamp


def get_oshdb_timestamp():
    """Get unix timestamp of OSHDB from ohsome api."""
    url = "https://api.ohsome.org/v1/metadata"
    r = requests.get(url)
    timestamp_str = str(r.json()["extractRegion"]["temporalExtent"]["toTimestamp"])
    timestamp = datetime.datetime.strptime(timestamp_str, "%Y-%m-%dT%H:%MZ")
    return timestamp


def get_valid_processing_timestamp():
    """Get timestamp for which TM and OSHDB data exists."""
    tm_timestamp = get_tasking_manager_dump_timestamp()
    oshdb_timestamp = get_oshdb_timestamp()
    return min([tm_timestamp, oshdb_timestamp])


def get_user_contributions_per_country_timestamp():
    """Get the latest month for which users stats exist in the postgres DB."""
    db = PostgresDb()
    sql = "set schema 'data_preparation';"
    sql += """
        select
            max(month) as month
        from osm_user_contributions_per_country_per_month;
    """
    timestamp = db.retr_query(sql)[0][0]
    return timestamp


def get_user_contributions_per_project_timestamp():
    """Get the latest month for which users stats exist in the postgres DB."""
    db = PostgresDb()
    sql = "set schema 'data_preparation';"
    sql += """
       select
         max(day) as day
       from osm_user_contributions_per_project_per_day;
    """
    timestamp = db.retr_query(sql)[0][0]
    return timestamp


def get_osm_snapshots_per_country_timestamp():
    """Get the latest month for which users stats exist in the postgres DB."""
    db = PostgresDb()
    sql = "set schema 'data_preparation';"
    sql += """
        select
            max(month) as month
        from osm_stats_per_country_per_month;
    """
    timestamp = db.retr_query(sql)[0][0]
    return timestamp


def check_oshdb_processing_timestamp(oshdb_timestamp, data_timestamp):
    """Check if we should query OSHDB for countries."""
    diff = relativedelta.relativedelta(oshdb_timestamp, data_timestamp)
    if diff.months >= 2:
        # This is a bit confusing, but we need to check if the difference it at least two months
        # e.g. OSHDB: 2021-11-07, data: 2021-10-01 --> False, because we queried until end of October already
        # we need to wait until December to query the stats for November
        # e.g. OSHDB: 2021-12-01, data: 2021-10-01 --> begin_timestamp
        begin_timestamp = data_timestamp + relativedelta.relativedelta(months=1)
        logger.info(
            f"got valid begin timestamp for OSHDB query: {begin_timestamp}, "
            f"data timestamp: {data_timestamp}"
        )
        return begin_timestamp
    else:
        logger.info(
            "got INVALID timestamp for OSHDB query: "
            f"data timestamp: {data_timestamp}, "
            f"OSHDB timestamp: {oshdb_timestamp}"
        )
        return False


def get_valid_export_timestamp(_filter="other"):
    """Get timestamp for which TM and OSHDB data exists."""
    if _filter in ["hot-audacious"]:
        country_data_timestamp = get_user_contributions_per_country_timestamp()
        export_timestamp = country_data_timestamp + relativedelta.relativedelta(months=1) - relativedelta.relativedelta(days=1)
        return export_timestamp.date()
    else:
        tm_timestamp = get_tasking_manager_dump_timestamp()
        oshdb_timestamp = get_oshdb_timestamp()
        return min([tm_timestamp, oshdb_timestamp]).date()

