# pylint: disable=R0401, C0302

from __future__ import annotations

from typing import Optional

from sqlalchemy import Column, String
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.ext.mutable import MutableList

from fides.api.db.base_class import Base  # type: ignore[attr-defined]
from fides.api.db.util import EnumColumn
from fides.api.models.worker_task import ExecutionLogStatus, TaskExecutionLog
from fides.api.schemas.policy import ActionType, CurrentStep

# Locations from which privacy request execution can be resumed, in order.
EXECUTION_CHECKPOINTS = [
    CurrentStep.pre_webhooks,
    CurrentStep.access,
    CurrentStep.upload_access,
    CurrentStep.erasure,
    CurrentStep.finalize_erasure,
    CurrentStep.consent,
    CurrentStep.finalize_consent,
    CurrentStep.email_post_send,
    CurrentStep.post_webhooks,
    CurrentStep.finalization,
]

COMPLETED_EXECUTION_LOG_STATUSES = [
    ExecutionLogStatus.complete,
    ExecutionLogStatus.skipped,
]

EXITED_EXECUTION_LOG_STATUSES = [
    ExecutionLogStatus.complete,
    ExecutionLogStatus.error,
    ExecutionLogStatus.skipped,
]


def can_run_checkpoint(
    request_checkpoint: CurrentStep, from_checkpoint: Optional[CurrentStep] = None
) -> bool:
    """Determine whether we should run a specific checkpoint in privacy request execution

    If there's no from_checkpoint specified we should always run the current checkpoint.
    """
    if not from_checkpoint:
        return True
    return EXECUTION_CHECKPOINTS.index(
        request_checkpoint
    ) >= EXECUTION_CHECKPOINTS.index(from_checkpoint)


class ExecutionLog(TaskExecutionLog, Base):
    """
    Stores the individual execution logs associated with a PrivacyRequest.

    Execution logs contain information about the individual queries as they progress through the workflow
    generated by the query builder.
    """

    connection_key = Column(String, index=True)
    # Name of the fides-annotated dataset, for example: my-mongo-db
    dataset_name = Column(String, index=True)
    # Name of the particular collection or table affected
    collection_name = Column(String, index=True)
    # A JSON Array describing affected fields along with their data categories and paths
    fields_affected = Column(MutableList.as_mutable(JSONB), nullable=True)
    action_type = Column(
        EnumColumn(ActionType),
        index=True,
        nullable=False,
    )

    privacy_request_id = Column(
        String,
        nullable=False,
        index=True,
    )
