from typing import Any


from bb_integrations_lib.gravitate.sd_api import GravitateSDAPI
from bb_integrations_lib.models.pipeline_structs import BolExportResults, NoPipelineData
from bb_integrations_lib.shared.model import FileReference, RawData
from bb_integrations_lib.pipelines.steps.exporting.sftp_export_file_step import SFTPExportFileStep
from bb_integrations_lib.pipelines.steps.exporting.sftp_export_many_files_step import SFTPExportManyFilesStep
from bb_integrations_lib.protocols.pipelines import Step
from bb_integrations_lib.provider.ftp.client import FTPIntegrationClient


class BBDExportOrderSFTPStep(Step[RawData | list[FileReference | RawData | BolExportResults], Any]):
    def __init__(self, sd_client: GravitateSDAPI, ftp_client: FTPIntegrationClient, ftp_destination_dir: str, *args, **kwargs):
        """
        Export a RawData from an order export parser, with specialty handling for order export status.

        Sets exported orders backoffice_erp.status to 'sent', and errored orders to their errors, and will roll back
        export status to 'pending' if the FTP export fails.
        """
        self.sd_client = sd_client
        self.ftp_client = ftp_client
        self.ftp_destination_dir = ftp_destination_dir
        super().__init__(*args, **kwargs)

    def describe(self) -> str:
        return "Export exported order files to FTPs and mark ERP status"

    async def execute(self, i: RawData | list[FileReference | RawData | BolExportResults]) -> Any:

        # Try to export the data
        # If the export errors, set the processed_orders to "pending"
        try:
            if isinstance(i, list):
                export_step = SFTPExportManyFilesStep(
                    ftp_client=self.ftp_client,
                    ftp_destination_dir=self.ftp_destination_dir,
                )
                export_step.pipeline_context = self.pipeline_context
                await export_step.execute(i)
            else:
                export_step = SFTPExportFileStep(
                    ftp_client=self.ftp_client,
                    ftp_destination_dir=self.ftp_destination_dir,
                )
                export_step.pipeline_context = self.pipeline_context
                await export_step.execute(i)
        except NoPipelineData as e:
            raise e
        except Exception as e:
            self.pipeline_context.extra_data["rollback_processed"] = True
            raise e
