import datetime
from typing import Any

import fakeredis
import msgspec

from csirtmu.beta.handler import Handler
from csirtmu.beta.redis_structs import RedisStruct, TransactionStateEnum
from csirtmu.beta.rt_queue import Queue
from csirtmu.beta_temporal.external_services.rt.structs import TransactionStruct


class TestTransactionRetention:
    async def test_redis_call_on_exception(
        self, temporal_patch_exception: type[Any], queue_map: dict[str, Queue], mock_nats_msg: Any
    ) -> None:
        temporal = temporal_patch_exception()
        redis = fakeredis.FakeRedis(version=6)
        handler = Handler(queue_map=queue_map, client=temporal, redis=redis)
        await handler.process_transaction(mock_nats_msg)

        transaction = msgspec.json.decode(mock_nats_msg.data.decode(), type=TransactionStruct)

        keys: list[Any] = redis.keys()
        assert len(keys) == 1
        assert int(keys[0]) == transaction.id

        data: list[RedisStruct] = [msgspec.json.decode(redis.get(k) or "{}", type=RedisStruct) for k in keys]  # type: ignore
        assert len(data) == 1
        redis_struct = data[0]

        assert redis_struct.transaction.id == transaction.id
        assert redis_struct.transaction == transaction
        assert redis_struct.state == TransactionStateEnum.PENDING
        queue = queue_map.get(transaction.queue)
        assert queue is not None
        assert redis_struct.workflows == queue.transaction_rules.get(transaction.type)
        assert redis_struct.error == "Test exception"
        assert redis_struct.timestamp < datetime.datetime.now(tz=datetime.UTC)
        redis.delete(*keys)
