import copy

from moto.stepfunctions.parser.api import HistoryEventType, TaskFailedEventDetails
from moto.stepfunctions.parser.asl.component.common.error_name.custom_error_name import (
    CustomErrorName,
)
from moto.stepfunctions.parser.asl.component.common.error_name.failure_event import (
    FailureEvent,
    FailureEventException,
)
from moto.stepfunctions.parser.asl.eval.environment import Environment
from moto.stepfunctions.parser.asl.eval.event.event_detail import EventDetails
from moto.stepfunctions.parser.mocking.mock_config import (
    MockedResponse,
    MockedResponseReturn,
    MockedResponseThrow,
)


def _eval_mocked_response_throw(
    env: Environment, mocked_response: MockedResponseThrow
) -> None:
    task_failed_event_details = TaskFailedEventDetails(
        error=mocked_response.error, cause=mocked_response.cause
    )
    error_name = CustomErrorName(mocked_response.error)
    failure_event = FailureEvent(
        env=env,
        error_name=error_name,
        event_type=HistoryEventType.TaskFailed,
        event_details=EventDetails(taskFailedEventDetails=task_failed_event_details),
    )
    raise FailureEventException(failure_event=failure_event)


def _eval_mocked_response_return(
    env: Environment, mocked_response: MockedResponseReturn
) -> None:
    payload_copy = copy.deepcopy(mocked_response.payload)
    env.stack.append(payload_copy)


def eval_mocked_response(env: Environment, mocked_response: MockedResponse) -> None:
    if isinstance(mocked_response, MockedResponseReturn):
        _eval_mocked_response_return(env=env, mocked_response=mocked_response)
    elif isinstance(mocked_response, MockedResponseThrow):
        _eval_mocked_response_throw(env=env, mocked_response=mocked_response)
    else:
        raise RuntimeError(f"Invalid MockedResponse type '{type(mocked_response)}'")
