"""
Master training pipeline.

Runs the entire ML pipeline end to end in the correct dependency order:
preprocessing -> feature engineering -> all 6 model training scripts.
Stops immediately on the first failure rather than continuing with a
partially-built model directory, since later models may silently use
incomplete data from an earlier failed step.

This is what you run on a fresh checkout (or after refreshing raw data)
to produce a complete, consistent data/models/v1/ directory.

Usage:
    python -m ml_pipeline.training.run_full_pipeline \
        --raw-climate data/raw/imd/rainfall.csv \
        --raw-crop data/raw/icrisat/yield.csv \
        --raw-market data/raw/agmarknet/prices.csv \
        --output-dir data/models/v1
"""

import argparse
import subprocess
import sys
from pathlib import Path

from ml_pipeline.training.training_utils import get_logger

logger = get_logger(__name__)


def run_step(description: str, command: list[str]) -> None:
    logger.info(f"=== {description} ===")
    logger.info(f"Running: {' '.join(command)}")
    result = subprocess.run(command, capture_output=False)
    if result.returncode != 0:
        logger.error(f"Step FAILED: {description} (exit code {result.returncode})")
        sys.exit(1)
    logger.info(f"Step completed: {description}\n")


def main() -> None:
    parser = argparse.ArgumentParser(description="Run the full ML training pipeline end to end")
    parser.add_argument("--raw-climate", required=True)
    parser.add_argument("--raw-crop", required=True)
    parser.add_argument("--raw-market", required=True)
    parser.add_argument("--crop-lookup", default="data/lookup/crops.json")
    parser.add_argument("--processed-dir", default="data/processed")
    parser.add_argument("--output-dir", default="data/models/v1")
    args = parser.parse_args()

    processed_dir = Path(args.processed_dir)
    climate_clean = processed_dir / "climate_clean.csv"
    crop_clean = processed_dir / "crop_clean.csv"
    market_clean = processed_dir / "market_clean.csv"
    final_matrix = processed_dir / "final_feature_matrix.csv"

    py = sys.executable

    run_step(
        "1/9 Validate raw climate data",
        [py, "-m", "ml_pipeline.data_collection.validate_raw_data",
         "--file", args.raw_climate, "--schema", "climate"],
    )
    run_step(
        "2/9 Validate raw crop data",
        [py, "-m", "ml_pipeline.data_collection.validate_raw_data",
         "--file", args.raw_crop, "--schema", "crop_yield"],
    )
    run_step(
        "3/9 Validate raw market data",
        [py, "-m", "ml_pipeline.data_collection.validate_raw_data",
         "--file", args.raw_market, "--schema", "market"],
    )
    run_step(
        "4/9 Clean climate data",
        [py, "-m", "ml_pipeline.preprocessing.clean_climate_data",
         "--input", args.raw_climate, "--output", str(climate_clean)],
    )
    run_step(
        "5/9 Clean crop data",
        [py, "-m", "ml_pipeline.preprocessing.clean_crop_data",
         "--input", args.raw_crop, "--output", str(crop_clean)],
    )
    run_step(
        "6/9 Clean market data",
        [py, "-m", "ml_pipeline.preprocessing.clean_market_data",
         "--input", args.raw_market, "--output", str(market_clean)],
    )
    run_step(
        "7/9 Build feature matrix",
        [py, "-m", "ml_pipeline.feature_engineering.build_feature_matrix",
         "--climate", str(climate_clean), "--crop", str(crop_clean),
         "--market", str(market_clean), "--crop-lookup", args.crop_lookup,
         "--output", str(final_matrix)],
    )
    run_step(
        "8/9 Train SARIMAX climate models",
        [py, "-m", "ml_pipeline.training.train_sarimax_climate",
         "--input", str(climate_clean), "--output-dir", args.output_dir],
    )
    run_step(
        "8/9 Train SARIMAX market models",
        [py, "-m", "ml_pipeline.training.train_sarimax_market",
         "--input", str(market_clean), "--output-dir", args.output_dir],
    )
    run_step(
        "9/9 Train XGBoost feasibility classifier",
        [py, "-m", "ml_pipeline.training.train_xgb_feasibility",
         "--input", str(final_matrix), "--output-dir", args.output_dir],
    )
    run_step(
        "9/9 Train XGBoost yield regressor",
        [py, "-m", "ml_pipeline.training.train_xgb_yield",
         "--input", str(final_matrix), "--output-dir", args.output_dir],
    )
    run_step(
        "9/9 Train Decision Tree trend classifier",
        [py, "-m", "ml_pipeline.training.train_dt_trend",
         "--input", str(final_matrix), "--output-dir", args.output_dir],
    )
    run_step(
        "9/9 Train Random Forest recommendation model",
        [py, "-m", "ml_pipeline.training.train_rf_recommendation",
         "--input", str(final_matrix), "--output-dir", args.output_dir],
    )

    logger.info("=" * 60)
    logger.info("FULL PIPELINE COMPLETE")
    logger.info(f"All 6 model artifacts saved to {args.output_dir}")
    logger.info("Run ml_pipeline/evaluation/validate_model_bundle.py next "
                "to confirm the model directory is ready for the API to load.")
    logger.info("=" * 60)


if __name__ == "__main__":
    main()
