# Copyright (c) 2022 CloudZero - ALL RIGHTS RESERVED - PROPRIETARY AND CONFIDENTIAL
# Unauthorized copying of this file and/or project, via any medium is strictly prohibited.
# Direct all questions to legal@cloudzero.com

from datetime import datetime
from decimal import Decimal
from time import sleep

import pytest
from dateutil.tz import tzutc
from freezegun import freeze_time

from czc.timestamped import TimestampContext, timestamped


@pytest.mark.unit
@pytest.mark.parametrize('type', [datetime, int, str, Decimal, float])
def test_timestamped_gets_right_type(type):
    @timestamped(return_type=type)
    def test_function(TIMESTAMP=None):
        return isinstance(TIMESTAMP, type)

    assert test_function()


@pytest.mark.unit
def test_timestamped_datetime_is_utc_aware():
    @timestamped(return_type=datetime)
    def test_function(TIMESTAMP=None) -> datetime:
        return TIMESTAMP

    assert test_function().tzinfo == tzutc()


@pytest.mark.unit
def test_timestamped_gets_isoformat_for_str():
    isotime = '2022-02-05T12:25:33+00:00'
    with freeze_time(isotime):
        @timestamped(return_type=str)
        def test_function(TIMESTAMP=None):
            return TIMESTAMP

        assert test_function() == isotime


@pytest.mark.unit
def test_timestamped_returns_cached_and_uncached_times():
    @timestamped(cached=True, return_type=Decimal)
    def cached_function(TIMESTAMP=None):
        return TIMESTAMP

    @timestamped(cached=False, return_type=Decimal)
    def uncached_function(TIMESTAMP=None):
        return TIMESTAMP

    with TimestampContext(cached=True, return_type=Decimal) as cached_time:
        sleep(1)
        assert cached_function() == cached_time
        assert uncached_function() > cached_time  # type: ignore


@pytest.mark.unit
def test_timestamped_defaults_to_uncached():
    @timestamped(return_type=Decimal)
    def test_function(TIMESTAMP=None):
        return TIMESTAMP

    with TimestampContext(cached=True, return_type=Decimal) as cached_time:
        sleep(1)
        assert test_function() > cached_time  # type: ignore


@pytest.mark.unit
def test_timestamped_defaults_to_decimal():
    @timestamped()
    def test_function(TIMESTAMP=None):
        return TIMESTAMP

    assert isinstance(test_function(), Decimal)
