"""Module containing batch flow import models."""

from collections.abc import Iterator
from datetime import datetime
from enum import Enum
from ibm_watsonx_data_integration.common.models import BaseModel
from pydantic import Field
from typing import TYPE_CHECKING, ClassVar

if TYPE_CHECKING:
    from ibm_watsonx_data_integration.cpd_models import Project
    from ibm_watsonx_data_integration.services.datastage.models.flow import BatchFlow


class BatchImportConflictResolution(str, Enum):
    """Conflict resolution option for importing batch flows."""

    SKIP = "skip"
    RENAME = "rename"
    REPLACE = "replace"


class BatchImportOnFailure(str, Enum):
    """On failure option for importing batch flows."""

    CONTINUE = "continue"
    STOP = "stop"


class BatchImportReplaceMode(str, Enum):
    """Replace mode option for importing batch flows."""

    SOFT = "soft"
    HARD = "hard"


class ConflictResolutionStatus(str, Enum):
    """Enum for a flow's conflict resolution status from importing."""

    FLOW_REPLACEMENT_SUCCEEDED = "flow_replacement_succeeded"
    FLOW_REPLACEMENT_FAILED = "flow_replacement_failed"
    IMPORT_FLOW_RENAMED = "import_flow_renamed"
    IMPORT_FLOW_SKIPPED = "import_flow_skipped"

    CONNECTION_REPLACEMENT_SUCCEEDED = "connection_replacement_succeeded"
    CONNECTION_REPLACEMENT_FAILED = "connection_replacement_failed"
    CONNECTION_RENAMED = "connection_renamed"
    CONNECTION_SKIPPED = "connection_skipped"

    PARAMETER_SET_REPLACEMENT_SUCCEEDED = "parameter_set_replacement_succeeded"
    PARAMETER_SET_REPLACEMENT_FAILED = "parameter_set_replacement_failed"
    PARAMETER_SET_RENAMED = "parameter_set_renamed"
    PARAMETER_SET_SKIPPED = "parameter_set_skipped"

    TABLE_DEFINITION_REPLACEMENT_SUCCEEDED = "table_definition_replacement_succeeded"
    TABLE_DEFINITION_REPLACEMENT_FAILED = "table_definition_replacement_failed"
    TABLE_DEFINITION_RENAMED = "table_definition_renamed"
    TABLE_DEFINITION_SKIPPED = "table_definition_skipped"

    SEQUENCE_JOB_REPLACEMENT_SUCCEEDED = "sequence_job_replacement_succeeded"
    SEQUENCE_JOB_REPLACEMENT_FAILED = "sequence_job_replacement_failed"
    SEQUENCE_JOB_RENAMED = "sequence_job_renamed"
    SEQUENCE_JOB_SKIPPED = "sequence_job_skipped"

    SUBFLOW_REPLACEMENT_SUCCEEDED = "subflow_replacement_succeeded"
    SUBFLOW_REPLACEMENT_FAILED = "subflow_replacement_failed"
    SUBFLOW_RENAMED = "subflow_renamed"
    SUBFLOW_SKIPPED = "subflow_skipped"

    MESSAGE_HANDLER_REPLACEMENT_SUCCEEDED = "message_handler_replacement_succeeded"
    MESSAGE_HANDLER_REPLACEMENT_FAILED = "message_handler_replacement_failed"
    MESSAGE_HANDLER_RENAMED = "message_handler_renamed"
    MESSAGE_HANDLER_SKIPPED = "message_handler_skipped"

    BUILD_STAGE_REPLACEMENT_SUCCEEDED = "build_stage_replacement_succeeded"
    BUILD_STAGE_REPLACEMENT_FAILED = "build_stage_replacement_failed"
    BUILD_STAGE_RENAMED = "build_stage_renamed"
    BUILD_STAGE_SKIPPED = "build_stage_skipped"

    WRAPPED_STAGE_REPLACEMENT_SUCCEEDED = "wrapped_stage_replacement_succeeded"
    WRAPPED_STAGE_REPLACEMENT_FAILED = "wrapped_stage_replacement_failed"
    WRAPPED_STAGE_RENAMED = "wrapped_stage_renamed"
    WRAPPED_STAGE_SKIPPED = "wrapped_stage_skipped"

    CUSTOM_STAGE_REPLACEMENT_SUCCEEDED = "custom_stage_replacement_succeeded"
    CUSTOM_STAGE_REPLACEMENT_FAILED = "custom_stage_replacement_failed"
    CUSTOM_STAGE_RENAMED = "custom_stage_renamed"
    CUSTOM_STAGE_SKIPPED = "custom_stage_skipped"

    DATA_QUALITY_RULE_REPLACEMENT_SUCCEEDED = "data_quality_rule_replacement_succeeded"
    DATA_QUALITY_RULE_REPLACEMENT_FAILED = "data_quality_rule_replacement_failed"
    DATA_QUALITY_RULE_RENAMED = "data_quality_rule_renamed"
    DATA_QUALITY_RULE_SKIPPED = "data_quality_rule_skipped"

    DATA_QUALITY_RULE_DEFINITION_REPLACEMENT_SUCCEEDED = "data_quality_rule_definition_replacement_succeeded"
    DATA_QUALITY_RULE_DEFINITION_FAILED = "data_quality_rule_definition_failed"
    DATA_QUALITY_RULE_DEFINITION_RENAMED = "data_quality_rule_definition_renamed"
    DATA_QUALITY_RULE_DEFINITION_SKIPPED = "data_quality_rule_definition_skipped"

    CFF_SCHEMA_REPLACEMENT_SUCCEEDED = "cff_schema_replacement_succeeded"
    CFF_SCHEMA_REPLACEMENT_FAILED = "cff_schema_replacement_failed"
    CFF_SCHEMA_RENAMED = "cff_schema_renamed"
    CFF_SCHEMA_SKIPPED = "cff_schema_skipped"

    TEST_CASE_REPLACEMENT_SUCCEEDED = "test_case_replacement_succeeded"
    TEST_CASE_REPLACEMENT_FAILED = "test_case_replacement_failed"
    TEST_CASE_RENAMED = "test_case_renamed"
    TEST_CASE_SKIPPED = "test_case_skipped"


class DataImportErrorType(str, Enum):
    """Enum the type of import error that occured."""

    COMPLETED = "completed"
    IN_PROGRESS = "in_progress"
    FAILED = "failed"
    SKIPPED = "skipped"
    DEPRECATED = "deprecated"
    UNSUPPORTED = "unsupported"

    FLOW_CONVERSION_FAILED = "flow_conversion_failed"
    FLOW_CREATION_FAILED = "flow_creation_failed"
    FLOW_COMPILATION_FAILED = "flow_compilation_failed"
    FLOW_COMPILATION_ERROR = "flow_compilation_error"

    JOB_CREATION_FAILED = "job_creation_failed"
    JOB_RUN_FAILED = "job_run_failed"
    JOB_UPDATE_FAILED = "job_update_failed"
    JOB_DELETION_FAILED = "job_deletion_failed"

    CONNECTION_CONVERSION_FAILED = "connection_conversion_failed"
    CONNECTION_CREATION_FAILED = "connection_creation_failed"

    PARAMETER_SET_CONVERSION_FAILED = "parameter_set_conversion_failed"
    PARAMETER_SET_CREATION_FAILED = "parameter_set_creation_failed"
    PARAMETER_SET_UPDATE_FAILED = "parameter_set_update_failed"

    DATA_QUALITY_SPEC_CONVERSION_FAILED = "data_quality_spec_conversion_failed"
    DATA_QUALITY_SPEC_CREATION_FAILED = "data_quality_spec_creation_failed"

    TABLE_DEFINITION_CONVERSION_FAILED = "table_definition_conversion_failed"
    TABLE_DEFINITION_CREATION_FAILED = "table_definition_creation_failed"

    SEQUENCE_JOB_CONVERSION_FAILED = "sequence_job_conversion_failed"
    SEQUENCE_JOB_CREATION_FAILED = "sequence_job_creation_failed"

    MESSAGE_HANDLER_CONVERSION_FAILED = "message_handler_conversion_failed"
    MESSAGE_HANDLER_CREATION_FAILED = "message_handler_creation_failed"

    BUILD_STAGE_CONVERSION_FAILED = "build_stage_conversion_failed"
    BUILD_STAGE_CREATION_FAILED = "build_stage_creation_failed"
    BUILD_STAGE_GENERATION_FAILED = "build_stage_generation_failed"

    XML_SCHEMA_LIBRARY_CREATION_FAILED = "xml_schema_library_creation_failed"

    WRAPPED_STAGE_CONVERSION_FAILED = "wrapped_stage_conversion_failed"
    WRAPPED_STAGE_CREATION_FAILED = "wrapped_stage_creation_failed"
    WRAPPED_STAGE_GENERATION_FAILED = "wrapped_stage_generation_failed"

    ROUTINE_CONVERSION_FAILED = "routine_conversion_failed"
    ROUTINE_CREATION_FAILED = "routine_creation_failed"

    CUSTOM_STAGE_CONVERSION_FAILED = "custom_stage_conversion_failed"
    CUSTOM_STAGE_CREATION_FAILED = "custom_stage_creation_failed"

    FLOW_UPDATE_FAILED = "flow_update_failed"

    COMPLETED_WITH_ERROR = "completed_with_error"

    DATA_QUALITY_RULE_CREATION_FAILED = "data_quality_rule_creation_failed"
    DATA_ASSET_CREATION_FAILED = "data_asset_creation_failed"
    CUSTOM_FUNCTION_CREATION_FAILED = "custom_function_creation_failed"
    DATA_SET_CREATION_FAILED = "data_set_creation_failed"
    FILE_SET_CREATION_FAILED = "file_set_creation_failed"
    DATA_RULE_DEFINITION_CREATION_FAILED = "data_rule_definition_creation_failed"

    CFF_SCHEMA_CREATION_FAILED = "cff_schema_creation_failed"
    CFF_SCHEMA_CONVERSION_FAILED = "cff_schema_conversion_failed"

    TEST_CASE_CREATION_FAILED = "test_case_creation_failed"
    TEST_CASE_CONVERSION_FAILED = "test_case_conversion_failed"

    JAVA_CLASS_LIBRARY_CREATION_FAILED = "java_class_library_creation_failed"

    EMPTY_STAGE_LIST = "empty_stage_list"


class DataImportError(BaseModel):
    """Describes an import problem specific to a particular data flow."""

    description: str | None = Field(default=None, description="Additional error text.", repr=False, frozen=True)
    name: str | None = Field(default=None, description="Error object name.", repr=True, frozen=True)
    stage_type: str | None = Field(default=None, description="Error stage type.", repr=False, frozen=True)
    type: DataImportErrorType = Field(description="Error type.", repr=True, frozen=True)


class ImportedFlowType(str, Enum):
    """Enum for the type of flow that was imported."""

    PX_JOB = "px_job"
    SERVER_JOB = "server_job"
    CONNECTION = "connection"
    TABLE_DEF = "table_def"
    PARAMETER_SET = "parameter_set"
    ROUTINE = "routine"
    SUBFLOW = "subflow"
    SEQUENCE_JOB = "sequence_job"
    DATA_QUALITY_SPEC = "data_quality_spec"
    SERVER_CONTAINER = "server_container"
    MESSAGE_HANDLER = "message_handler"
    BUILD_STAGE = "build_stage"
    WRAPPED_STAGE = "wrapped_stage"
    CUSTOM_STAGE = "custom_stage"
    XML_SCHEMA_LIBRARY = "xml_schema_library"
    CUSTOM_STAGE_LIBRARY = "custom_stage_library"
    FUNCTION_LIBRARY = "function_library"
    DATA_INTG_PARALLEL_FUNCTION = "data_intg_parallel_function"
    DATA_INTG_JAVA_LIBRARY = "data_intg_java_library"
    ODM_RULESET = "odm_ruleset"
    JOB = "job"
    DATA_QUALITY_RULE = "data_quality_rule"
    DATA_QUALITY_DEFINITION = "data_quality_definition"
    DATA_ASSET = "data_asset"
    DATA_INTG_DATA_SET = "data_intg_data_set"
    DATA_INTG_FILE_SET = "data_intg_file_set"
    ODBC_CONFIGURATION = "odbc_configuration"
    DATA_INTG_CFF_SCHEMA = "data_intg_cff_schema"
    DATA_INTG_TEST_CASE = "data_intg_test_case"
    DATA_ELEMENT = "data_element"
    IMS_DATABASE = "ims_database"
    IMS_VIEWSET = "ims_viewset"
    MAINFRAME_JOB = "mainframe_job"
    MACHINE_PROFILE = "machine_profile"
    MAINFRAME_ROUTINE = "mainframe_routine"
    PARALLEL_ROUTINE = "parallel_routine"
    TRANSFORM = "transform"
    JDBC_DRIVER = "jdbc_driver"


class ImportedFlowWarningType(str, Enum):
    """Enum that indicates the type of flow warning on import."""

    UNRELEASED_STAGE_TYPE = "unreleased_stage_type"
    UNRELEASED_FEATURE = "unreleased_feature"
    CREDENTIALS_FILE_WARNING = "credentials_file_warning"
    TRANSFORMER_TRIGGER_UNSUPPORTED = "transformer_trigger_unsupported"
    TRANSFORMER_BUILDTAB_UNSUPPORTED = "transformer_buildtab_unsupported"
    UNSUPPORTED_SECURE_GATEWAY = "unsupported_secure_gateway"
    PLACEHOLDER_CONNECTION_PARAMETERS = "placeholder_connection_parameters"
    DESCRIPTION_TRUNCATED = "description_truncated"
    EMPTY_STAGE_LIST = "empty_stage_list"
    MISSING_PARAMETER_SET = "missing_parameter_set"
    MISSING_SUBFLOW = "missing_subflow"
    MISSING_TABLE_DEFINITION = "missing_table_definition"
    MISSING_DATA_CONNECTION = "missing_data_connection"
    DUPLICATE_JOB = "duplicate_job"
    UNSUPPORTED_CONNECTION = "unsupported_connection"
    UNSUPPORTED_ACTIVITY_TRIGGER = "unsupported_activity_trigger"
    UNSUPPORTED_EXPRESSION = "unsupported_expression"
    UNSUPPORTED_FUNCTION = "unsupported_function"
    UNSUPPORTED_OPERATOR = "unsupported_operator"
    UNSUPPORTED_VARIABLE = "unsupported_variable"
    UNSUPPORTED_ACTIVITY_VARIABLE = "unsupported_activity_variable"
    DEFAULT_CONNECTION_PARAMETER = "default_connection_parameter"
    UNMATCHED_FOR_VAR_WARNING = "unmatched_for_var_warning"
    UNSUPPORTED_ROUTINE_STATEMENT = "unsupported_routine_statement"
    UNSUPPORTED_BEFORE_AFTER_ROUTINE = "unsupported_before_after_routine"
    ATTACHMENT_CREATION_FAILED = "attachment_creation_failed"
    UNSUPPORTED_JOB_CONTROL = "unsupported_job_control"
    UNSUPPORTED_DRS_RDBMS_PARAMETER = "unsupported_drs_rdbms_parameter"
    DATACONNECTION_CONFLICT = "dataconnection_conflict"
    PLACEHOLDER_PARAMETER_SET = "placeholder_parameter_set"
    MISSING_ROUTINE = "missing_routine"
    UNSUPPORTED_STORED_PROCEDURE_TRANSFORM = "unsupported_stored_procedure_transform"
    UNATTACHED_LINKS = "unattached_links"
    UNRELEASED_DATASOURCE_IN_STOREDPROCEDURE = "unreleased_datasource_in_storedprocedure"
    UNSUPPORTED_PARQUET_COMPRESSION_TYPE_LZO = "unsupported_parquet_compression_type_lzo"
    UNSUPPORTED_STPPX_DBVENDOR_PARAMETER = "unsupported_stppx_dbvendor_parameter"
    UNSUPPORTED_SAPPACK_CONNECTOR_PROPERTY = "unsupported_sappack_connector_property"
    UNDEFINED_VARIABLE = "undefined_variable"
    UNSUPPORTED_XMLOUTPUTPX_FEATURES = "unsupported_xmloutputpx_features"
    XML_TRANSFORM_MISSED_SCHEMA = "xml_transform_missed_schema"
    UNSUPPORTED_STAGE_TYPE = "unsupported_stage_type"
    UNBOUND_REFERENCE = "unbound_reference"
    MISSING_STAGE_TYPE = "missing_stage_type"
    UNSUPPORTED_DEPENDENCY = "unsupported_dependency"
    MISSING_DATA_ASSET = "missing_data_asset"
    UNSUPPORTED_SVTRANSFORMER_BEFORE_AFTER_SUBROUTINE = "unsupported_svtransformer_before_after_subroutine"
    DEPRECATED_LOAD_CONTROL_PROPERTIES = "deprecated_load_control_properties"
    MISSING_PARAMETER = "missing_parameter"
    UNSUPPORTED_STAGE_TYPE_IN_SUBFLOW = "unsupported_stage_type_in_subflow"
    UNSUPPORTED_XMLINPUTPX_FEATURES = "unsupported_xmlinputpx_features"
    EXPORT_REQUEST_IN_PROGRESS = "export_request_in_progress"
    UNSUPPORTED_STPPX_FOR_DB2I_DB2Z = "unsupported_stppx_for_db2i_db2z"
    DEPRECATED_CONNECTION_PROPERTY = "deprecated_connection_property"
    HARD_CODED_FILE_PATH = "hard_coded_file_path"
    UNSUPPORTED_PROPERTY_VALUE = "unsupported_property_value"
    UNSUPPORTED_PROPERTY = "unsupported_property"
    UNSUPPORTED_DCN_DATA_CONNECTION = "unsupported_dcn_data_connection"
    XMLSTAGE_UNSUPPORTED_FUNCTION = "xmlstage_unsupported_function"
    ATTACHMENT_UPDATE_FAILED = "attachment_update_failed"
    UNCHANGED_PARAMETER_SET = "unchanged_parameter_set"
    CONNECTION_PARAMETER_SET_CREATED = "connection_parameter_set_created"
    CONNECTION_PARAMETER_SET_PATCHED = "connection_parameter_set_patched"
    SKIPPED_DUPLICATE_CONNECTION = "skipped_duplicate_connection"
    UNCHANGED_CONNECTION = "unchanged_connection"
    UNSUPPORTED_XPATH = "unsupported_xpath"
    PARAMETERS_IN_EXISTING_PARAMETER_SET = "parameters_in_existing_parameter_set"
    DIFFERENT_PARAMETER_TYPE_IN_PARAMETER_SET = "different_parameter_type_in_parameter_set"
    UNSUPPORTED_DATAQUALITY_RENAME = "unsupported_dataquality_rename"
    UNSUPPORTED_DATA_CONNECTION_SECURE_GATEWAY = "unsupported_data_connection_secure_gateway"
    MISSING_DEFAULT_PARAMETER_VALUE = "missing_default_parameter_value"
    MISSING_REFERENCED_CONNECTION = "missing_referenced_connection"
    UNSUPPORTED_ROUTINE_ACTIVITY = "unsupported_routine_activity"
    UNSUPPORTED_EXECUTION_ACTION_VALIDATE = "unsupported_execution_action_validate"
    UNSUPPORTED_EXECUTION_ACTION_RESET = "unsupported_execution_action_reset"
    RUNTIME_JIS_GENERATION_FAILED = "runtime_jis_generation_failed"
    MISSING_JOB = "missing_job"
    MISSING_DATASET = "missing_dataset"
    MISSING_FILESET = "missing_fileset"
    IDENTICAL_PARAMETER_SET = "identical_parameter_set"
    MISSING_RUNTIME_ENVIRONMENT = "missing_runtime_environment"
    MISSING_MATCH_SPEC = "missing_match_spec"
    UNSUPPORTED_BEFORE_AFTER_SUBROUTINE = "unsupported_before_after_subroutine"
    DEPRECATED_STAGE_TYPE = "deprecated_stage_type"
    MISSING_STORAGE_VOLUME = "missing_storage_volume"
    UNSUPPORTED_WEBSPHEREMQ_SERVER_MODE = "unsupported_websphereMQ_server_mode"
    UNSUPPORTED_PARAMETER_NAME = "unsupported_parameter_name"
    UNSUPPORTED_PROPERTY_ON_CLOUD = "unsupported_property_on_cloud"
    INVALID_JOB_SCHEDULE = "invalid_job_schedule"
    MISSING_CFF_SCHEMA = "missing_cff_schema"
    MISSING_DATA_INTG_FLOW = "missing_data_intg_flow"
    JOB_IMPORT_SKIPPED = "job_import_skipped"
    UNSUPPORTED_SPPARAM_TYPE = "unsupported_spparam_type"
    UNSUPPORTED_MULTIPLE_REJECT_LINKS = "unsupported_multiple_reject_links"
    BINARIES_IMPORT_FAILED = "binaries_import_failed"
    MISSING_BINARIES = "missing_binaries"
    DEPRECATED_JOB_ENVIRONMENT_INPUT = "deprecated_job_environment_input"
    UNCLEAR_NUMERIC_TYPE = "unclear_numeric_type"
    DUPLICATE_PARAMETER_NAME = "duplicate_parameter_name"
    USER_STATUS_MIGRATED_TO_GLOBAL_USER_VARIABLE = "user_status_migrated_to_global_user_variable"
    USER_STATUS_MIGRATED_TO_DSSETUSERSTATUS_FUNCTION = "user_status_migrated_to_dssetuserstatus_function"
    SUBROUTINE_UNSUPPORTED_ON_CLOUD = "subroutine_unsupported_on_cloud"


class ImportedFlowWarning(BaseModel):
    """Describes a warning message specific to a particular data flow."""

    description: str | None = Field(default=None, description="Additional warning text.", repr=False, frozen=True)
    name: str = Field(description="Warning object name.", repr=True, frozen=True)
    type: ImportedFlowWarningType = Field(description="Warning type.", repr=True, frozen=True)


class ImportedFlow(BaseModel):
    """Model representing an imported flow."""

    conflict_resolution_status: ConflictResolutionStatus | None = Field(
        default=None, description="Conflict resolution status.", repr=False, frozen=True
    )
    end_time: datetime | None = Field(
        default=None,
        description=(
            "The timestamp when the flow import is completed. In format YYYY-MM-DDTHH:mm:ssZ or "
            "YYYY-MM-DDTHH:mm:ss.sssZ, matching the date-time format as specified by RFC 3339."
        ),
        repr=False,
        frozen=True,
    )
    errors: list[DataImportError] = Field(
        default_factory=list[DataImportError],
        description=(
            "The errors array report all the problems preventing the data flow from being successfully imported."
        ),
        repr=False,
        frozen=True,
    )
    flow_id: str | None = Field(
        default=None,
        alias="id",
        description=(
            "Unique id of the data flow. This field is returned only if the underlying data flow has been "
            "successfully imported"
        ),
        repr=True,
        frozen=True,
    )
    job_id: str | None = Field(
        default=None,
        description=(
            "Unique id of the job. This field is returned only if the corresponding job object has been "
            "successfully created."
        ),
        repr=False,
        frozen=True,
    )
    job_name: str | None = Field(
        default=None,
        description=(
            "Job name. This field is returned only if the corresponding job object has been successfully created."
        ),
        repr=False,
        frozen=True,
    )
    name: str = Field(description="Name of the imported data flow.", repr=True, frozen=True)
    original_name: str | None = Field(
        default=None, description="Name of the data flow to be imported.", repr=False, frozen=True
    )
    ref_asset_id: str | None = Field(
        default=None,
        description=(
            "The ID of an existing asset this object refers to. If ref_asset_id is specified, the id field will be "
            "the same as ref_asset_id for backward compatibility."
        ),
        repr=False,
        frozen=True,
    )
    type: ImportedFlowType | None = Field(
        default=None, description="Type of the job or data connection in the import file."
    )
    warnings: list[ImportedFlowWarning] = Field(
        default_factory=list[ImportedFlowWarning],
        description="The warnings array report all the warnings in the data flow import operation.",
        repr=False,
        frozen=True,
    )


class MissingAsset(BaseModel):
    """Represents a missing asset in the import."""

    name: str = Field(description="Name of asset.", repr=True, frozen=True)
    type: str = Field(description="Type of asset.", repr=True, frozen=True)


class ImportExportNotification(BaseModel):
    """Import/Export event notification."""

    created_at: datetime = Field(
        description=(
            "The timestamp when the notification was created. In format YYYY-MM-DDTHH:mm:ssZ or "
            "YYYY-MM-DDTHH:mm:ss.sssZ, matching the date-time format as specified by RFC 3339."
        ),
        repr=True,
        frozen=True,
    )
    notification_id: str = Field(alias="id", description="Notification id.", repr=True, frozen=True)
    status: str = Field(description="Import/Export status associated with the notification.", repr=True, frozen=True)


class BatchImportStatus(str, Enum):
    """Enum representing the different types of import statuses."""

    IN_PROGRESS = "in_progress"
    CANCELLED = "cancelled"
    QUEUED = "queued"
    STARTED = "started"
    COMPLETED = "completed"


class ImportCount(BaseModel):
    """Import statistics."""

    build_stages_total: int = Field(default=0, description="Total number of build stages.", repr=False, frozen=True)
    cff_schemas_total: int = Field(default=0, description="Total number of cff schemas.", repr=False, frozen=True)
    connection_creation_failed: int = Field(
        default=0, description="Total number of connection creation failures.", repr=False, frozen=True
    )
    connections_total: int = Field(default=0, description="Total number of data connections.", repr=False, frozen=True)
    custom_stages_total: int = Field(default=0, description="Total number of custom stages.", repr=False, frozen=True)
    data_assets_total: int = Field(default=0, description="Total number of data assets.", repr=False, frozen=True)
    data_elements_total: int = Field(default=0, description="Total number of data elements.", repr=False, frozen=True)
    data_quality_definitions_total: int = Field(
        default=0, description="Total number of data quality rules.", repr=False, frozen=True
    )
    data_quality_rules_total: int = Field(
        default=0, description="Total number of data quality rules.", repr=False, frozen=True
    )
    data_quality_spec_total: int = Field(
        default=0, description="Total number of data quality spec.", repr=False, frozen=True
    )
    data_sets_total: int = Field(default=0, description="Total number of datastage datasets.", repr=False, frozen=True)
    deprecated: int = Field(
        default=0, description="Total number of deprecated resources in the import file.", repr=False, frozen=True
    )
    failed: int = Field(
        default=0,
        description="Total number of data flows that cannot be imported due to import errors.",
        repr=False,
        frozen=True,
    )
    file_sets_total: int = Field(default=0, description="Total number of datastage filesets.", repr=False, frozen=True)
    flow_compilation_failed: int = Field(
        default=0, description="Total number of data flows that failed to compile.", repr=False, frozen=True
    )
    flow_creation_failed: int = Field(
        default=0, description="Total number of flow creation failures.", repr=False, frozen=True
    )
    function_libraries_total: int = Field(
        default=0, description="Total number of function libraries.", repr=False, frozen=True
    )
    imported: int = Field(
        default=0, description="Total number of data flows successfully imported.", repr=True, frozen=True
    )
    ims_databases_total: int = Field(default=0, description="Total number of IMS databases.", repr=False, frozen=True)
    ims_viewsets_total: int = Field(default=0, description="Total number of IMS viewsets.", repr=False, frozen=True)
    java_libraries_total: int = Field(default=0, description="Total number of java libraries.", repr=False, frozen=True)
    job_creation_failed: int = Field(
        default=0, description="Total number of job creation failures.", repr=False, frozen=True
    )
    machine_profiles_total: int = Field(
        default=0, description="Total number of machine profiles.", repr=False, frozen=True
    )
    mainframe_jobs_total: int = Field(default=0, description="Total number of mainframe jobs.", repr=False, frozen=True)
    mainframe_routines_total: int = Field(
        default=0, description="Total number of mainframe routines.", repr=False, frozen=True
    )
    message_handlers_total: int = Field(
        default=0, description="Total number of message handlers.", repr=False, frozen=True
    )

    odm_libraries_total: int = Field(
        default=0, description="Total number of ilogjrule/odm libraries.", repr=False, frozen=True
    )
    parallel_jobs_total: int = Field(default=0, description="Total number of parallel jobs.", repr=False, frozen=True)
    parallel_routines_total: int = Field(
        default=0, description="Total number of parallel routines.", repr=False, frozen=True
    )
    parameter_sets_total: int = Field(default=0, description="Total number of parameter sets.", repr=False, frozen=True)
    pending: int = Field(
        default=0, description="Total number of data flows that have not been processed.", repr=True, frozen=True
    )
    renamed: int = Field(
        default=0,
        description=(
            "Total number of data flows successfully imported and renamed due to a name conflict. The renamed count "
            "is included in the imported count."
        ),
        repr=True,
        frozen=True,
    )
    replaced: int = Field(
        default=0,
        description=(
            "Total number of existing data flows replaced by imported flows. The replaced count is included in "
            "the imported count."
        ),
        repr=False,
        frozen=True,
    )
    routines_total: int = Field(default=0, description="Total number of routines.", repr=False, frozen=True)
    sequence_job_creation_failed: int = Field(
        default=0, description="Total number of sequence job creation failures.", repr=False, frozen=True
    )
    sequence_jobs_total: int = Field(default=0, description="Total number of sequence jobs.", repr=False, frozen=True)
    server_containers_total: int = Field(
        default=0, description="Total number of server containers.", repr=False, frozen=True
    )
    skipped: int = Field(
        default=0,
        description=(
            "Total number of data flows skipped due to name conflicts. The skipped count is not included "
            "in the failed count or imported count."
        ),
        repr=True,
        frozen=True,
    )
    subflows_total: int = Field(
        default=0, description="Total number of parallel job subflows.", repr=False, frozen=True
    )
    table_definitions_total: int = Field(
        default=0, description="Total number of table definitions.", repr=False, frozen=True
    )
    test_cases_total: int = Field(default=0, description="Total number of test cases.", repr=False, frozen=True)
    total: int = Field(default=0, description="Total number of data flows to be imported.", repr=True, frozen=True)
    transforms_total: int = Field(default=0, description="Total number of transforms.", repr=False, frozen=True)
    unsupported: int = Field(
        default=0, description="Total number of unsupported resources in the import file.", repr=True, frozen=True
    )
    wrapped_stages_total: int = Field(default=0, description="Total number of wrapped stages.", repr=False, frozen=True)
    xml_schema_libraries_total: int = Field(
        default=0, description="Total number of xml schema libraries.", repr=False, frozen=True
    )


class ImportResponseMetadata(BaseModel):
    """Metadata for an import response."""

    catalog_id: str | None = Field(default=None, description="Catalog id.", repr=False, frozen=True)
    catalog_name: str | None = Field(default=None, description="Catalog name.", repr=False, frozen=True)
    created_at: datetime | None = Field(
        default=None,
        description=(
            "The timestamp when the import API was submitted. In format YYYY-MM-DDTHH:mm:ssZ or "
            "YYYY-MM-DDTHH:mm:ss.sssZ, matching the date-time format as specified by RFC 3339."
        ),
        repr=True,
        frozen=True,
    )
    id: str = Field(description="The unique import id.", repr=True, frozen=True)
    modified_at: datetime | None = Field(
        default=None,
        description=(
            "The timestamp when the import API was last updated. In format YYYY-MM-DDTHH:mm:ssZ or "
            "YYYY-MM-DDTHH:mm:ss.sssZ, matching the date-time format as specified by RFC 3339."
        ),
        repr=False,
        frozen=True,
    )
    name: str | None = Field(default=None, description="Import file name.", repr=True, frozen=True)
    project_id: str | None = Field(default=None, description="Project id", repr=False, frozen=True)
    project_name: str | None = Field(default=None, description="Project name", repr=True, frozen=True)
    space_id: str | None = Field(default=None, description="Space id.", repr=False, frozen=True)
    space_name: str | None = Field(default=None, description="Space name.", repr=False, frozen=True)
    url: str = Field(
        description="The URL which can be used to get the status of the import request right after it is submitted.",
        repr=False,
        frozen=True,
    )


class BatchImportResponse(BaseModel):
    """Response object of a batch import request."""

    EXPOSED_DATA_PATH: ClassVar[dict] = {"entity": {}}

    cancelled_by: str | None = Field(
        default=None,
        description=(
            "Account ID of the user who cancelled the import request. This field is required only when the status "
            'field is "cancelled".'
        ),
        repr=False,
        frozen=True,
    )
    conflict_resolution: str | None = Field(
        default=None, description="The conflict_resolution option used for the import.", repr=False, frozen=True
    )
    elapsed_time: str | None = Field(
        default=None, description="The duration of import processing time", repr=False, frozen=True
    )
    end_time: datetime | None = Field(
        default=None,
        description=(
            "The timestamp when the import opearton completed. In format YYYY-MM-DDTHH:mm:ssZ or "
            "YYYY-MM-DDTHH:mm:ss.sssZ, matching the date-time format as specified by RFC 3339."
        ),
        repr=False,
        frozen=True,
    )
    import_data_flows: list[ImportedFlow] = Field(
        default_factory=list[ImportedFlow],
        description=(
            "All batch flows imported or to be imported. Each ImportFlow object contains status for the individual "
            "data flow import operation."
        ),
        repr=False,
        frozen=True,
    )
    import_error: str | None = Field(default=None, description="Import error.", repr=False, frozen=True)
    missing_assets: list[MissingAsset] = Field(
        default_factory=list[MissingAsset], description="List of all missing assets.", repr=False, frozen=True
    )
    name: str | None = Field(default=None, description="Name of the import request.", repr=True, frozen=True)
    notifications: list[ImportExportNotification] = Field(
        default_factory=list[ImportExportNotification],
        description="Import event notifications.",
        repr=False,
        frozen=True,
    )
    on_failure: str | None = Field(
        default=None, description="The on_failure option used for the import.", repr=False, frozen=True
    )
    remaining_time: int | None = Field(
        default=None, description="Estimate of remaining time in seconds.", repr=False, frozen=True
    )
    start_time: datetime | None = Field(
        default=None,
        description=(
            "The timestamp when the import opearton started. In format YYYY-MM-DDTHH:mm:ssZ or "
            "YYYY-MM-DDTHH:mm:ss.sssZ, matching the date-time format as specified by RFC 3339."
        ),
        repr=False,
        frozen=True,
    )
    status: BatchImportStatus = Field(description="Status of the import.", repr=True, frozen=True)
    tally: ImportCount | None = Field(
        default=None,
    )
    metadata: ImportResponseMetadata = Field(description="Metadata of the import response.", repr=False, frozen=True)
    import_id: str = Field(repr=True, default_factory=lambda fields: fields["metadata"].id, frozen=True, exclude=True)

    def __init__(self, project: "Project", **project_json: dict) -> None:
        """__init__ function of BatchImportResponse."""
        super().__init__(**project_json)
        self._project: Project = project

    def refresh(self) -> "BatchImportResponse":
        """Refreshes the batch import to get the most up-to-date status.

        Returns:
            BatchImportResponse: updated import response.
        """
        response = self._project._platform._batch_flow_api.get_import_status(
            self.import_id, project_id=self._project.project_id
        )
        return BatchImportResponse(self._project, **response.json())

    def imported_flows(self, load: bool = False) -> Iterator["BatchFlow"]:
        """An iterator of the flows that were imported.

        Args:
            load: If set to True, will retrieve the flow's DAG and all relevant metadata. If set to False, will return
            imported flows with only their flow id and name. Defaults to False

        Yields:
            An iterator of the batch flows that have finished importing.
        """
        from ibm_watsonx_data_integration.services.datastage.models.flow import BatchFlow

        for imported_flow in self.import_data_flows:
            # px_job = batch flow
            # if flow id is None, then it has not finished importing
            if imported_flow.type != ImportedFlowType.PX_JOB or imported_flow.flow_id is None:
                continue

            batch_flow = BatchFlow(project=self._project, flow_id=imported_flow.flow_id, name=imported_flow.name)

            if load:
                yield self._project.flows.get(flow_type="batch", flow_id=batch_flow.flow_id)
            else:
                yield batch_flow
