"""
컬럼 일별 리포트 — 지정 기간 일별 운전값 + 생산맵 예측품질(shadow).

사용: python3 daily_report.py --prefix 62 --asset /ASSETS/P6 \
        --start 2026-04-01 --end 2026-06-01 --train-end 2026-04-01

train-end 이전 PROD로 생산맵 학습 → start~end 일별로 예측 OP vs 실제 비교(전진 shadow).
"""
import argparse
import numpy as np
import pandas as pd
import psycopg
from c6111_extract import roles_for, tag_frame, classify_phases, DSN
from c6111_shadow import SteamPredictor, FEATURES, SMOOTH
from sklearn.metrics import mean_absolute_error


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--prefix", default="62")
    ap.add_argument("--asset", default="/ASSETS/P6")
    ap.add_argument("--start", default="2026-04-01")
    ap.add_argument("--end", default="2026-06-01")
    ap.add_argument("--train-end", default="2026-04-01")
    a = ap.parse_args()

    with psycopg.connect(DSN) as conn:
        df = tag_frame(conn, roles_for(a.prefix, a.asset), a.asset)
    df["mode"] = classify_phases(df)
    for c in FEATURES:
        df[c + "_s"] = df[c].rolling(SMOOTH, min_periods=1).median()

    prod = df[df["mode"] == "PROD"].copy()
    prod = prod[(prod["feed"] > 50) & (prod["steam_flow"] > 10) & (prod["steam_op"] > 1)]
    te = pd.Timestamp(a.train_end)
    train = prod[prod["dtat"] < te]
    print(f"전체 {df.dtat.min()}~{df.dtat.max()}, PROD {len(prod)}행. "
          f"학습(<{a.train_end}) {len(train)}행")

    pred = SteamPredictor().fit(train) if len(train) > 500 else None
    if pred:
        lo, hi = train[FEATURES].quantile(0.01), train[FEATURES].quantile(0.99)

    s, e = pd.Timestamp(a.start), pd.Timestamp(a.end)
    win = df[(df["dtat"] >= s) & (df["dtat"] < e)]
    rows = []
    for day, g in win.groupby(win["dtat"].dt.date):
        gp = g[(g["mode"] == "PROD") & (g["feed"] > 50) & (g["steam_flow"] > 10) & (g["steam_op"] > 1)]
        r = dict(date=day, n=len(g),
                 PROD=round(100*(g["mode"] == "PROD").mean()),
                 feed=gp["feed"].median(), steam=gp["steam_flow"].median(),
                 ratio=round((gp["steam_flow"]/gp["feed"]).median(), 3) if len(gp) else np.nan,
                 T_C=round(gp["T_C"].median(), 2) if len(gp) else np.nan,
                 OP=round(gp["steam_op"].median(), 1) if len(gp) else np.nan)
        if pred and len(gp) > 5:
            Xs = gp[[c + "_s" for c in FEATURES]].values
            po = pred.flow_to_op(pred.predict_flow(Xs))
            ao = gp["steam_op"].values
            env = ((gp[FEATURES] >= lo) & (gp[FEATURES] <= hi)).all(axis=1)
            r["predOP_MAE"] = round(mean_absolute_error(ao, po), 2)
            r["within2%"] = round(100*np.mean(np.abs(po-ao) <= 2))
            r["OOD%"] = round(100*(~env).mean())
        rows.append(r)
    R = pd.DataFrame(rows)
    pd.set_option("display.width", 200)
    print(f"\n=== {a.prefix} 일별 리포트 ({a.start}~{a.end}) ===")
    R["date"] = R["date"].astype(str)
    print(R.round(1).to_string(index=False))
    print("\n=== 요약 ===")
    print(f"  feed 중앙 {R.feed.median():.0f}, steam 중앙 {R.steam.median():.0f}, "
          f"steam/feed비 중앙 {R.ratio.median():.3f}")
    if "predOP_MAE" in R:
        print(f"  예측 OP MAE 중앙 {R.predOP_MAE.median():.2f}%, "
              f"within2% 중앙 {R['within2%'].median():.0f}%, OOD 중앙 {R['OOD%'].median():.0f}%")


if __name__ == "__main__":
    main()
