"""fmatch.io – Utilities for efficient, storage-agnostic file loading."""

from __future__ import annotations
import pandas as pd
import polars as pl
from fmatch.saas.storage import get_storage_backend, MissingObjectError
from fmatch.shared.settings import get_settings

settings = get_settings()


class FileLoader:
    """
    Handles loading data from and writing data to the configured storage backend
    (local or S3). Uses Polars for lazy, memory-efficient scanning of large files.
    """

    def __init__(self):
        """Initializes the FileLoader by getting the configured storage backend."""
        self.fs = get_storage_backend()
        print(f"FileLoader initialized with filesystem: {self.fs.__class__.__name__}")

    def load_polars_lazy(self, file_path: str) -> pl.LazyFrame:
        """
        Loads a large CSV lazily using Polars to avoid out-of-memory errors.

        Args:
            file_path: The path to the file within the storage backend. For S3,
                       this should be the object key (e.g., 'project_123/source.csv').

        Returns:
            A Polars LazyFrame, ready for analysis.

        Raises:
            MissingObjectError: If the file does not exist in the storage backend.
        """
        # Construct the full path depending on the backend
        full_path = (
            f"{settings.S3_BUCKET_NAME}/{file_path}"
            if settings.STORAGE_BACKEND == "s3"
            else file_path
        )

        if not self.fs.exists(full_path):
            raise MissingObjectError(f"Object not found at path: {full_path}")

        # Use Polars' scan_csv, which can read directly from a URL-like path
        # or a local path, leveraging the fsspec backend.
        # Note: Polars < 1.0 needs `storage_options`, >= 1.0 uses `fsspec_options`.
        try:  # For polars >= 1.0
            return pl.scan_csv(full_path, fsspec_options=self.fs.storage_options)
        except TypeError:  # Fallback for polars < 1.0
            return pl.scan_csv(full_path, storage_options=self.fs.storage_options)

    def write_results(self, df: pd.DataFrame, file_path: str):
        """
        Writes a pandas DataFrame back to the configured storage as a CSV.

        Args:
            df: The DataFrame to save.
            file_path: The destination path (key) for the file in storage.
        """
        full_path = (
            f"{settings.S3_BUCKET_NAME}/{file_path}"
            if settings.STORAGE_BACKEND == "s3"
            else file_path
        )

        print(f"Writing results to {full_path}...")
        with self.fs.open(full_path, "w") as f:
            df.to_csv(f, index=False)
        print(f"Successfully wrote results to {full_path}")
