import pytest
from src.config.objects import LastFetchDatetime
from src.util.execute_datetime import ExecuteDateTime


class TestLastFetchDatetime():
    def test_constructor(self) -> None:
        """
        Cases:
            インスタンス生成テスト
            辞書型のデータに対して、バリデーションチェックを行いチェックが通ることを確認する
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生しないこと
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
            "last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
        }

        execute_datetime = ExecuteDateTime()

        # Act
        LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        pass

    def test_raise_constructor_last_fetch_datetime_from_no_key(self) -> None:
        """
        Cases:
            インスタンス生成テスト
            辞書型のデータに対して、必要なキー(last_fetch_datetime_from)がない場合、例外が発生すること
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生し期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
        }

        execute_datetime = ExecuteDateTime()

        # Act
        with pytest.raises(Exception) as e:
            LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        assert str(e.value) == '「last_fetch_datetime_from」キーは必須です'

    def test_raise_constructor_last_fetch_datetime_from_no_value(self) -> None:
        """
        Cases:
            インスタンス生成テスト
            辞書型のデータの対象のキー(last_fetch_datetime_from)の値が空文字の場合、例外が発生すること
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生し期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "",
            "last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
        }

        execute_datetime = ExecuteDateTime()

        # Act
        with pytest.raises(Exception) as e:
            LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        assert str(e.value) == '「last_fetch_datetime_from」キーは必須です'

    def test_raise_constructor_last_fetch_datetime_from_none_value(self) -> None:
        """
        Cases:
            インスタンス生成テスト
            辞書型のデータの対象のキー(last_fetch_datetime_from)の値がNoneの場合、例外が発生すること
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生し期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": None,
            "last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
        }

        execute_datetime = ExecuteDateTime()

        # Act
        with pytest.raises(Exception) as e:
            LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        assert str(e.value) == '「last_fetch_datetime_from」キーは必須です'

    def test_raise_constructor_last_fetch_datetime_from_other_type(self) -> None:
        """
        Cases:
            インスタンス生成テスト
            辞書型のデータの対象のキー(last_fetch_datetime_from)の値の型が想定と違う場合、例外が発生すること
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生し期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": 1,
            "last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
        }

        execute_datetime = ExecuteDateTime()

        # Act
        with pytest.raises(Exception) as e:
            LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        assert str(e.value) == '「last_fetch_datetime_from」キーの値は「<class \'str\'>」でなければなりません'

    def test_raise_constructor_last_fetch_datetime_from_other_string(self) -> None:
        """
        Cases:
            インスタンス生成テスト
            辞書型のデータの対象のキー(last_fetch_datetime_from)の値が正規表現と違う場合、例外が発生すること
        Arranges:
            - 辞書型のオブジェクト情報を準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生し期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "aaa",
            "last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
        }

        execute_datetime = ExecuteDateTime()

        # Act
        with pytest.raises(Exception) as e:
            LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        assert str(
            e.value) == '「last_fetch_datetime_from」キーの値の正規表現チェックに失敗しました 「YYYY-MM-DDTHH:MM:SS.000Z」形式である必要があります'

    def test_raise_constructor_last_fetch_datetime_to_no_key(self) -> None:
        """
        Cases:
            インスタンス生成テスト
            辞書型のデータに対して、キー(last_fetch_datetime_to)がない場合、例外が発生しないこと
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生しないこと
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z"
        }

        execute_datetime = ExecuteDateTime()

        # Act
        LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        pass

    def test_constructor_last_fetch_datetime_to_no_value(self) -> None:
        """
        Cases:
            辞書型のデータの対象のキー(last_fetch_datetime_to)の値の型が空文字の場合、例外が発生しないこと
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生しないこと
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
            "last_fetch_datetime_to": ""
        }

        execute_datetime = ExecuteDateTime()

        # Act
        LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        None

    def test_constructor_last_fetch_datetime_to_none__value(self) -> None:
        """
        Cases:
            辞書型のデータの対象のキー(last_fetch_datetime_to)の値の型がNoneの場合、例外が発生しないこと
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生しないこと
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
            "last_fetch_datetime_to": None
        }

        execute_datetime = ExecuteDateTime()

        # Act
        LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        pass

    def test_raise_constructor_last_fetch_datetime_to_other_type(self) -> None:
        """
        Cases:
            インスタンス生成テスト
            辞書型のデータの対象のキー(last_fetch_datetime_to)の値の型が想定と違う場合、例外が発生すること
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生し期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
            "last_fetch_datetime_to": 1
        }

        execute_datetime = ExecuteDateTime()

        # Act
        with pytest.raises(Exception) as e:
            LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        assert str(e.value) == '「last_fetch_datetime_to」キーの値は「<class \'str\'>」でなければなりません'

    def test_raise_constructor_last_fetch_datetime_to_other_string(self) -> None:
        """
        Cases:
            インスタンス生成テスト
            辞書型のデータの対象のキー(last_fetch_datetime_to)の値が正規表現と違う場合、例外が発生すること
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
        Expects:
            - 例外が発生し期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
            "last_fetch_datetime_to": "aaa"
        }

        execute_datetime = ExecuteDateTime()

        # Act
        with pytest.raises(Exception) as e:
            LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Expects
        assert str(
            e.value) == '「last_fetch_datetime_to」キーの値の正規表現チェックに失敗しました 「YYYY-MM-DDTHH:MM:SS.000Z」形式である必要があります'

    def test_last_fetch_datetime_from(self) -> str:
        """
        Cases:
            オブジェクト情報から対象の値を返すこと
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
            - 前回取得日時インスタンスを生成する
        Expects:
            - 戻り値が期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
            "last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
        }

        execute_datetime = ExecuteDateTime()

        sut = LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Act
        actual = sut.last_fetch_datetime_from

        # Expects
        assert actual == '1900-01-01T00:00:00.000Z'

    def test_last_fetch_datetime_to(self) -> str:
        """
        Cases:
            オブジェクト情報から対象の値を返すこと
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
            - 前回取得日時インスタンスを生成する
        Expects:
            - 戻り値が期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
            "last_fetch_datetime_to": "2022-01-01T00:00:00.000Z"
        }

        execute_datetime = ExecuteDateTime()

        sut = LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Act
        actual = sut.last_fetch_datetime_to

        # Expects
        assert actual == '2022-01-01T00:00:00.000Z'

    def test_last_fetch_datetime_to_default(self) -> str:
        """
        Cases:
            オブジェクト情報から対象の値を返すこと
        Arranges:
            - 辞書型の前回取得日時データを準備する
            - 実行日時インスタンスを生成する
            - 前回取得日時インスタンスを生成する
        Expects:
            - 戻り値が期待値と一致する
        """

        # Arranges
        last_fetch_datetime_dict = {
            "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z",
            "last_fetch_datetime_to": ""
        }

        execute_datetime = ExecuteDateTime()

        sut = LastFetchDatetime(last_fetch_datetime_dict, execute_datetime)

        # Act
        actual = sut.last_fetch_datetime_to

        # Expects
        assert actual == str(execute_datetime)
