"""Trend scorer training on real historical OHLCV and snapshot-derived features."""

import logging
import time

import numpy as np

from .data_loader import load_trend_training_frame
from .pipeline import TrainingPipeline

logger = logging.getLogger(__name__)


class TrendTrainer(TrainingPipeline):
    FEATURE_KEYS = [
        "price_change_24h",
        "price_change_7d",
        "volume_24h",
        "market_cap",
        "volume_to_mcap_ratio",
        "rank",
    ]

    def __init__(self):
        super().__init__("trend_scorer")

    def load_data(self):
        logger.info("Loading real trend scoring data from OHLCV history...")
        frame = load_trend_training_frame(days=240, timeframe="4h")
        if frame.empty:
            raise RuntimeError("No historical trend training data available")
        return frame

    def preprocess(self, data):
        data = data.sort_index().reset_index(drop=True)
        X = data[self.FEATURE_KEYS].fillna(0.0).astype(np.float32).values
        y = data["y"].astype(np.float32).values

        n = len(X)
        train_end = int(n * 0.70)
        val_end = int(n * 0.85)

        return X[:train_end], X[train_end:val_end], X[val_end:], y[:train_end], y[train_end:val_end], y[val_end:]

    def train(self, X_train, y_train, X_val, y_val):
        try:
            import xgboost as xgb

            model = xgb.XGBRegressor(
                n_estimators=300,
                max_depth=4,
                learning_rate=0.05,
                subsample=0.85,
                colsample_bytree=0.85,
                reg_alpha=0.05,
                reg_lambda=1.0,
                objective="reg:squarederror",
                eval_metric="rmse",
                early_stopping_rounds=25,
                random_state=42,
            )
            model.fit(X_train, y_train, eval_set=[(X_val, y_val)], verbose=False)
            return model
        except Exception:
            from sklearn.ensemble import RandomForestRegressor

            model = RandomForestRegressor(
                n_estimators=250,
                max_depth=10,
                min_samples_leaf=5,
                random_state=42,
                n_jobs=-1,
            )
            model.fit(X_train, y_train)
            return model

    def evaluate(self, model, X_test, y_test):
        from sklearn.metrics import mean_absolute_error, r2_score

        preds = np.clip(model.predict(X_test), 0, 100)
        return {
            "r2": float(r2_score(y_test, preds)),
            "mae": float(mean_absolute_error(y_test, preds)),
            "test_samples": len(y_test),
        }

    def save(self, model, metrics):
        import joblib

        super().save(model, metrics)
        artifact_path = self.artifact_dir.parent / "trend_scorer.joblib"
        joblib.dump(
            {
                "model": model,
                "trained_at": str(int(time.time())),
                "accuracy": metrics.get("r2"),
                "feature_keys": self.FEATURE_KEYS,
            },
            artifact_path,
        )
        return str(artifact_path)
