from __future__ import annotations

from pathlib import Path
import re
import numpy as np
import pandas as pd


def read_table(path: str | Path, sheet_name=0) -> pd.DataFrame:
    path = Path(path)
    if not path.exists():
        raise FileNotFoundError(f"Input file not found: {path}")
    if path.suffix.lower() in [".xlsx", ".xlsm", ".xls"]:
        return pd.read_excel(path, sheet_name=sheet_name)
    return pd.read_csv(path)


def infer_columns(df: pd.DataFrame, target: str | None = None, features: str | list[str] | None = None):
    columns = list(df.columns)
    if target is None:
        candidates = [
            c for c in columns
            if re.match(r"^(target|t:|o:|max:|min:|=[+-]?\d*\.?\d+(?:[eE][+-]?\d+)?:)", str(c))
        ]
        target = candidates[0] if candidates else columns[0]

    if isinstance(features, str):
        features = [s.strip() for s in features.split(",") if s.strip()]
    if features is None:
        features = [
            c for c in columns
            if c != target and not str(c).startswith("-") and pd.api.types.is_numeric_dtype(df[c])
        ]

    return target, features


def split_observed_candidates(df: pd.DataFrame, target: str, features: list[str]):
    X = df[features].to_numpy(dtype=float)
    y = df[target].to_numpy(dtype=float)
    observed_mask = ~np.isnan(y)
    return X, y, observed_mask
