"""Feature pipeline utilities for NeuroWeave."""

from __future__ import annotations

from typing import Any

import numpy as np

from .base import BaseFeature


class FeaturePipeline:
    """Sequential pipeline for feature extractors and transforms.

    Parameters
    ----------
    *steps : BaseFeature
        Feature steps applied in sequence.
    """

    def __init__(self, *steps: BaseFeature) -> None:
        self.steps = list(steps)
        self._feature_names: list[str] = []

    def fit(self, X: np.ndarray) -> FeaturePipeline:
        """Fit the pipeline sequentially.

        Parameters
        ----------
        X : np.ndarray
            Input stimulus or feature matrix.

        Returns
        -------
        FeaturePipeline
            The fitted pipeline.
        """

        output = np.asarray(X, dtype=float)
        current_names: list[str] = []
        for step in self.steps:
            step._input_feature_names = list(current_names)
            output = step.fit_transform(output)
            current_names = step.feature_names
        self._feature_names = self.steps[-1].feature_names if self.steps else []
        return self

    def transform(self, X: np.ndarray) -> np.ndarray:
        """Apply the pipeline sequentially.

        Parameters
        ----------
        X : np.ndarray
            Input stimulus or feature matrix.

        Returns
        -------
        np.ndarray
            Final feature matrix.
        """

        output = np.asarray(X, dtype=float)
        current_names: list[str] = []
        for step in self.steps:
            step._input_feature_names = list(current_names)
            output = step.transform(output)
            current_names = step.feature_names
        self._feature_names = self.steps[-1].feature_names if self.steps else []
        return output

    def fit_transform(self, X: np.ndarray) -> np.ndarray:
        """Fit the pipeline and apply the full transformation chain.

        Parameters
        ----------
        X : np.ndarray
            Input stimulus or feature matrix.

        Returns
        -------
        np.ndarray
            Final feature matrix.
        """

        output = np.asarray(X, dtype=float)
        current_names: list[str] = []
        for step in self.steps:
            step._input_feature_names = list(current_names)
            output = step.fit_transform(output)
            current_names = step.feature_names
        self._feature_names = self.steps[-1].feature_names if self.steps else []
        return output

    @property
    def feature_names(self) -> list[str]:
        """Feature names produced by the final pipeline step."""

        return list(self._feature_names)

    @property
    def metadata(self) -> dict[str, Any]:
        """Metadata describing the pipeline output."""

        return {"feature_names": self.feature_names, "n_steps": len(self.steps)}
