"""
features.py - 배치별 특성(Feature) 생성
원료 계근 데이터 → AI 모델 입력 피처로 변환
"""
import pandas as pd
import numpy as np


def build_batch_features(batch_no, conn):
    """
    단일 배치의 계근 데이터로부터 피처 dict 생성.
    반환: {feature_name: value, ...}
    """
    sql = """
        SELECT w.material_code, w.std_qty, w.actual_qty, w.deviation_pct,
               w.weigh_seq, m.material_grp,
               b.mix_rpm, b.mix_minutes, b.mix_temp, b.product_code
        FROM cq_weighing w
        JOIN cq_batch b ON b.batch_no = w.batch_no
        LEFT JOIN cq_material m ON m.material_code = w.material_code
        WHERE w.batch_no = %s
    """
    df = pd.read_sql(sql, conn, params=[batch_no])
    if df.empty:
        return None

    feats = {}
    total = df["actual_qty"].sum()
    if total <= 0:
        total = 1.0

    # 1) 원료별 실제 배합비 + 편차율
    for _, r in df.iterrows():
        mc = r["material_code"]
        feats[f"ratio_{mc}"] = float(r["actual_qty"]) / total
        feats[f"dev_{mc}"]   = float(r["deviation_pct"] or 0.0)

    # 2) 원료 그룹별 배합비 합산 (점증제/중화제 등이 물성에 직접 영향)
    grp_sum = df.groupby("material_grp")["actual_qty"].sum() / total
    for grp, val in grp_sum.items():
        if grp:
            feats[f"grp_{grp}"] = float(val)

    # 3) 배치 전체 편차 통계 (재작업 핵심 신호)
    dev = df["deviation_pct"].fillna(0).abs()
    feats["dev_max"]  = float(dev.max())
    feats["dev_mean"] = float(dev.mean())
    feats["dev_std"]  = float(dev.std() or 0.0)
    feats["dev_over_tol_cnt"] = int((dev > 2.0).sum())  # 허용편차 초과 원료 수

    # 4) 공정 조건
    feats["mix_rpm"]     = float(df["mix_rpm"].iloc[0] or 0)
    feats["mix_minutes"] = float(df["mix_minutes"].iloc[0] or 0)
    feats["mix_temp"]    = float(df["mix_temp"].iloc[0] or 0)

    return feats


def build_training_matrix(conn):
    """
    학습용 X(피처), y_reg(물성), y_class(적합여부) 생성.
    품질검사 결과가 존재하는 배치만 사용.
    """
    batches = pd.read_sql("""
        SELECT q.batch_no, q.ph, q.hardness, q.specific_grav,
               q.content_pct, q.viscosity, q.result_flag
        FROM cq_quality q
        JOIN cq_batch b ON b.batch_no = q.batch_no
        WHERE q.result_flag IS NOT NULL
    """, conn)

    rows, y_reg, y_class = [], [], []
    for _, b in batches.iterrows():
        f = build_batch_features(b["batch_no"], conn)
        if not f:
            continue
        rows.append(f)
        y_reg.append({
            "ph": b["ph"], "hardness": b["hardness"],
            "specific_grav": b["specific_grav"],
            "content_pct": b["content_pct"], "viscosity": b["viscosity"],
        })
        # PASS=0, FAIL/REWORK=1 (이상 탐지)
        y_class.append(0 if b["result_flag"] == "PASS" else 1)

    if not rows:
        return None, None, None

    X = pd.DataFrame(rows).fillna(0.0)
    y_reg_df = pd.DataFrame(y_reg)
    return X, y_reg_df, np.array(y_class)


def align_features(feat_dict, feature_names):
    """추론 시 학습 피처 순서에 맞춰 정렬 (없는 피처는 0)"""
    return pd.DataFrame([{fn: feat_dict.get(fn, 0.0) for fn in feature_names}])
