import os
import joblib
import pandas as pd
from datetime import datetime
from flask import Flask, request, jsonify
from sqlalchemy import text
from config.database import get_db_connection
from services.trainer import train_and_save_models
from services.feature_builder import FEATURE_COLUMNS

app = Flask(__name__)


@app.post("/api/train")
def run_training():
    """ Endpoint untuk memicu proses training dari tombol Laravel """
    result = train_and_save_models()
    return jsonify(result)


@app.post("/api/predict")
def predict_sales():
    """ Endpoint untuk melakukan prediksi penjualan suatu produk di tanggal tertentu """
    payload = request.get_json(force=True)

    # Validasi input minimal (menggantikan validasi otomatis Pydantic)
    required_fields = ["produk_id", "tanggal_prediksi"]
    for field in required_fields:
        if field not in payload:
            return jsonify({"detail": f"Field '{field}' wajib diisi."}), 422

    produk_id = payload["produk_id"]
    tanggal_prediksi = payload["tanggal_prediksi"]
    is_weekend = payload.get("is_weekend", 0)
    is_libur_nasional = payload.get("is_libur_nasional", 0)
    is_ramadhan = payload.get("is_ramadhan", 0)
    is_idul_fitri = payload.get("is_idul_fitri", 0)
    is_idul_adha = payload.get("is_idul_adha", 0)
    is_tahun_baru = payload.get("is_tahun_baru", 0)

    rf_path = "models/model_rf.pkl"
    xgb_path = "models/model_xgb.pkl"

    if not os.path.exists(rf_path) or not os.path.exists(xgb_path):
        return jsonify({"detail": "Model belum dilatih! Jalankan /api/train terlebih dahulu."}), 400

    rf_model = joblib.load(rf_path)
    xgb_model = joblib.load(xgb_path)

    # Format Fitur Input
    dt = datetime.strptime(tanggal_prediksi, "%Y-%m-%d")

    input_data = pd.DataFrame([{
        'produk_id': produk_id,
        'hari_num': dt.weekday(),
        'bulan': dt.month,
        'tahun': dt.year,
        'is_weekend': is_weekend,
        'is_libur_nasional': is_libur_nasional,
        'is_ramadhan': is_ramadhan,
        'is_idul_fitri': is_idul_fitri,
        'is_idul_adha': is_idul_adha,
        'is_tahun_baru': is_tahun_baru
    }])[FEATURE_COLUMNS]

    # Tebak Angka Penjualan
    pred_rf = float(rf_model.predict(input_data)[0])
    pred_xgb = float(xgb_model.predict(input_data)[0])

    # Pastikan hasil tidak minus
    pred_rf = max(0.0, pred_rf)
    pred_xgb = max(0.0, pred_xgb)

    # Simpan/Update Langsung ke Database Laravel (Tabel prediksi_penjualan)
    conn = get_db_connection()
    upsert_query = text("""
        INSERT INTO prediksi_penjualan
            (produk_id, tanggal_prediksi, prediksi_rf, prediksi_xgb, created_at, updated_at)
        VALUES
            (:produk_id, :tanggal, :rf, :xgb, NOW(), NOW())
        ON DUPLICATE KEY UPDATE
            prediksi_rf = :rf,
            prediksi_xgb = :xgb,
            updated_at = NOW();
    """)

    conn.execute(upsert_query, {
        "produk_id": produk_id,
        "tanggal": tanggal_prediksi,
        "rf": round(pred_rf, 2),
        "xgb": round(pred_xgb, 2)
    })
    conn.commit()
    conn.close()

    return jsonify({
        "status": "success",
        "produk_id": produk_id,
        "tanggal_prediksi": tanggal_prediksi,
        "prediksi_rf": round(pred_rf, 2),
        "prediksi_xgb": round(pred_xgb, 2)
    })


# Flask app object sudah WSGI-compatible secara native — tidak perlu wrapper apapun.
# Passenger akan langsung memanggil "app" ini sebagai WSGI callable.