from datetime import UTC, datetime
from typing import Type, override

from pandas import DataFrame

from bb_integrations_lib.models.pipeline_structs import NoPipelineData
from bb_integrations_lib.protocols.pipelines import Parser, Step
from bb_integrations_lib.shared.model import RawData


class ConvertFreightInvoicesStep(Step):
    """Convert freight invoices to CSV using a parser."""

    @override
    def __init__(
        self,
        parser: Type[Parser],
        file_base_name: str = "Freight-Invoices",
        parser_kwargs: dict | None = None,
        *args,
        **kwargs,
    ):
        super().__init__(*args, **kwargs)
        self.file_base_name = file_base_name
        self.parser = parser(**(parser_kwargs or {}))

    def describe(self) -> str:
        return "Convert freight invoices to CSV"

    async def execute(self, invoices: list[dict]) -> RawData:
        rows, exported_invoice_numbers = self.parser.parse_invoices(invoices)
        if not rows:
            raise NoPipelineData("No invoice data to export after conversion")

        df = DataFrame.from_records(rows)
        now = datetime.now(UTC).strftime("%Y%m%d_%H%M%S")
        file_name = f"{self.file_base_name}_{now}.csv"

        self.pipeline_context.extra_data["exported_invoice_numbers"] = (
            exported_invoice_numbers
        )

        return RawData(
            file_name=file_name,
            data=df.to_csv(index=False, header=True).encode("utf-8"),
        )
