from typing import Union
import json
import sys

from logging518 import logger

from Blocktrace.Schemas import Block, TransactionTrace, ActionTrace
from Blocktrace.Utils import BlocktraceLog


def deserialize_block_to_json(block: Block) -> str:
    """Deserialize Block object to JSON string

    Parameters
    ----------
    block : Block
        Block object

    Returns
    -------
    str
        JSON string
    """
    try:
        if block:
            return json.dumps(
                {
                    "blockId": block.id,
                    "blockNumber": block.number,
                    "timestamp": block.timestamp,
                    "producer": block.producer,
                    "unfilteredTransactionCount": block.unfilteredTransactionCount,
                    "unfilteredTransactionTraceCount": block.unfilteredTransactionTraceCount,
                    "unfilteredExecutedInputActionCount": block.unfilteredExecutedInputActionCount,
                    "unfilteredExecutedTotalActionCount": block.unfilteredExecutedTotalActionCount,
                    "filteringIncludeFilterExpr": block.filteringIncludeFilterExpr,
                    "filteredTransactionTraceCount": block.filteredTransactionTraceCount,
                    "filteredExecutedInputActionCount": block.filteredExecutedInputActionCount,
                    "filteredExecutedTotalActionCount": block.filteredExecutedTotalActionCount,
                    "filteredTransactionCount": block.filteredTransactionCount,
                },
                sort_keys=True,
            )
        else:
            raise ValueError("None block made it through")
    except ValueError as e:
        logger.exception(
            BlocktraceLog(
                __name__,
                "catching_exception",
                {"hint": "Check debug logs to see why None Block made it through"},
            )
        )
        return ""


def deserialize_transaction_to_json(tx: TransactionTrace) -> str:
    """Deserialize TransactionTrace object to JSON string

    Parameters
    ----------
    tx : TransactionTrace
        TransactionTrace object

    Returns
    -------
    str
        JSON string
    """
    return json.dumps(
        {
            "transactionId": tx.id,
            "blockNumber": tx.blockNum,
            "blockTime": tx.blockTime,
            "status": tx.status,
            "cpuUsageMicroSeconds": tx.cpuUsageMicroSeconds,
            "netUsage": tx.netUsage,
            "elapsed": tx.wallTimeElapsed,
        },
        sort_keys=True,
    )


def deserialize_action_to_json(act: ActionTrace) -> str:
    """Deserialize ActionTrace object to JSON string

    Parameters
    ----------
    act : ActionTrace
        ActionTrace object

    Returns
    -------
    str
        JSON string
    """
    return json.dumps(
        {
            "transactionId": act.transactionId,
            "blockNumber": act.blockNum,
            "actionOrdinal": act.actionOrdinal,
            "account": act.action.account,
            "actionName": act.action.name,
            "actionData": act.action.jsonData,
            "elapsed": act.elapsed,
            "actor": act.actor,
            "receiver": act.receiver,
        },
        sort_keys=True,
    )
