"""Synthetic RFM exercise. Run with Python 3.11-3.13; files resolve beside this script."""
from pathlib import Path
import pandas as pd
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

BASE = Path(__file__).resolve().parent
DEADLINE = pd.Timestamp("2024-05-01")
raw = pd.read_csv(BASE / "sales.csv", parse_dates=["ORDERDATE"])
sales = raw.dropna(subset=["USERID", "ORDERDATE", "AMOUNTINFO"])
sales = sales[(sales["AMOUNTINFO"] > 1) & (sales["ORDERDATE"] < DEADLINE)]
rfm = sales.groupby("USERID").agg(
    last_order=("ORDERDATE", "max"),
    frequency=("ORDERDATE", "size"),
    monetary=("AMOUNTINFO", "sum"),
)
rfm["recency"] = (DEADLINE - rfm.pop("last_order")).dt.days
# Fixed teaching thresholds, NOT quantiles. Recent purchases receive higher scores.
rfm["r_score"] = pd.cut(rfm.recency, [0, 7, 30, 60, 90, float("inf")], labels=[5, 4, 3, 2, 1], include_lowest=True).astype(int)
rfm["f_score"] = pd.cut(rfm.frequency, [0, 1, 2, 3, 4, float("inf")], labels=[1, 2, 3, 4, 5]).astype(int)
rfm["m_score"] = pd.cut(rfm.monetary, [0, 50, 100, 200, 400, float("inf")], labels=[1, 2, 3, 4, 5]).astype(int)
rfm["score"] = (rfm.r_score * 0.2 + rfm.f_score * 0.2 + rfm.m_score * 0.6).round(2)
# pd.cut uses right-closed intervals: [0, 2], (2, 4], (4, 5].
rfm["segment"] = pd.cut(rfm.score, [0, 2, 4, 5], labels=["Low", "Medium", "High"], include_lowest=True)
rfm.to_csv(BASE / "rfm_result.csv")
counts = rfm.segment.value_counts().reindex(["Low", "Medium", "High"], fill_value=0)
fig, ax = plt.subplots(figsize=(6, 4), layout="constrained")
ax.bar(counts.index, counts.values, color=["#78909c", "#26a69a", "#5c6bc0"])
ax.set(title="Customer segments (synthetic data)", xlabel="Segment", ylabel="Customers", ylim=(0, 3))
ax.set_yticks([0, 1, 2, 3])
fig.savefig(BASE / "segments.png", dpi=160)
plt.close(fig)
print(rfm[["recency", "frequency", "monetary", "score", "segment"]].to_string())
