from unittest import IsolatedAsyncioTestCase
from unittest.mock import patch

import redis
from django.test import TestCase
from fakeredis import FakeStrictRedis

from tordonate import settings
from tordonate.redis import RedisController


class RedisTests(TestCase):
    def test_is_redis_up(self) -> None:
        def __post_init__(self) -> None:  # type: ignore[no-untyped-def]
            self.connection = redis.Redis(
                host=self.host, port=self.port, db=self.db, password=self.password
            )

        rc = RedisController(
            settings.REDIS_SERVER,
            settings.REDIS_PORT,
            settings.REDIS_DB,
            settings.REDIS_PASSWORD,
            settings.APP_ENV
        )
        rc.connection.ping()
        self.assertTrue(rc.connection.ping())


class AsyncRedisTests(IsolatedAsyncioTestCase):
    async def test_set_get(self) -> None:
        def __post_init__(self) -> None:  # type: ignore[no-untyped-def]
            self.connection = FakeStrictRedis()

        with patch.object(RedisController, "__post_init__", __post_init__):
            rc = RedisController(
                settings.REDIS_SERVER,
                settings.REDIS_PORT,
                settings.REDIS_DB,
                settings.REDIS_PASSWORD,
                settings.APP_ENV
            )
            self.assertEqual(
                rc.connection.set("foo", "bar"), True
            )
            self.assertEqual(rc.connection.get("foo"), b'bar')

    async def test_resque_set(self) -> None:
        def __post_init__(self) -> None:  # type: ignore[no-untyped-def]
            self.connection = FakeStrictRedis()

        with patch.object(RedisController, "__post_init__", __post_init__):
            rc = RedisController(
                settings.REDIS_SERVER,
                settings.REDIS_PORT,
                settings.REDIS_DB,
                settings.REDIS_PASSWORD,
                settings.APP_ENV
            )
            res = await rc.resque_send("foo", {"bar": "baz"})
            self.assertTrue(type(res) is int)
