"""Build a lightweight bucket-prior ranking model from snapshot labels."""
from __future__ import annotations

import argparse
import json
from pathlib import Path

import pandas as pd

from libs.backtest.ranking_models import _resolve_feature_key


FEATURE_SPECS = [
    ("event_type", 0.08),
    ("direction_guidance_combo", 0.27),
    ("reaction_bucket", 0.22),
    ("close_bucket", 0.15),
    ("volume_bucket", 0.12),
    ("gap_bucket", 0.08),
    ("document_bucket", 0.05),
    ("confidence_bucket", 0.03),
]


def build_model(
    snapshot_path: Path,
    cutoff_event_date: str,
    min_bucket_count: int,
) -> dict:
    df = pd.read_parquet(snapshot_path)
    df["event_date"] = pd.to_datetime(df["event_date"]).dt.date
    df["reaction_date"] = pd.to_datetime(df["reaction_date"], errors="coerce").dt.date
    cutoff_date = pd.to_datetime(cutoff_event_date).date()
    df = df[
        (df["event_date"] <= cutoff_date)
        & (df["reaction_date"] == df["event_date"])
        & (df["reaction_day_return"] > 0)
        & df["event_type"].isin(["earnings_release", "guidance_update"])
        & df["fwd_return_20d"].notna()
    ].copy()
    global_mean = float(df["fwd_return_20d"].mean()) if not df.empty else 0.0

    features = []
    for name, weight in FEATURE_SPECS:
        bucket_map: dict[str, list[float]] = {}
        for row in df.to_dict("records"):
            key = _resolve_feature_key(name, row)
            if key is None:
                continue
            bucket_map.setdefault(key, []).append(float(row["fwd_return_20d"]))
        values = {
            key: sum(values) / len(values)
            for key, values in bucket_map.items()
            if len(values) >= min_bucket_count
        }
        features.append(
            {
                "name": name,
                "weight": weight,
                "values": values,
            }
        )

    return {
        "model_type": "bucket_blend_v1",
        "target": "fwd_return_20d",
        "snapshot_id": snapshot_path.parent.name,
        "cutoff_event_date": cutoff_event_date,
        "min_bucket_count": min_bucket_count,
        "training_rows": int(len(df)),
        "global_mean": global_mean,
        "features": features,
    }


def main() -> None:
    parser = argparse.ArgumentParser(description="Build a bucket-prior ranking model")
    parser.add_argument("--snapshot", required=True, help="Path to the parquet snapshot")
    parser.add_argument("--output", required=True, help="Output JSON path")
    parser.add_argument("--cutoff-event-date", default="2024-12-31")
    parser.add_argument("--min-bucket-count", type=int, default=8)
    args = parser.parse_args()

    model = build_model(
        snapshot_path=Path(args.snapshot),
        cutoff_event_date=args.cutoff_event_date,
        min_bucket_count=args.min_bucket_count,
    )
    output = Path(args.output)
    output.parent.mkdir(parents=True, exist_ok=True)
    output.write_text(json.dumps(model, indent=2))
    print(output)


if __name__ == "__main__":
    main()
