"""Impor dataset CSV ke MySQL (tb_produk + tb_penjualan) untuk aplikasi Kramat Motor BI.

Letakkan file ini di folder yang sama dengan app.py dan database.py, lalu jalankan:

    python import_dataset.py dataset_kramat_motor_2025_2026.csv --dry-run   # cek saja, tidak menulis
    python import_dataset.py dataset_kramat_motor_2025_2026.csv             # impor (tambah data yang belum ada)
    python import_dataset.py dataset_kramat_motor_2025_2026.csv --reset     # kosongkan data lama dulu, lalu impor

Kolom CSV: periode (YYYY-MM-DD), produk, kategori, harga, stok, terjual
"""
import argparse
import sys

import pandas as pd

BULAN = ["Januari", "Februari", "Maret", "April", "Mei", "Juni",
         "Juli", "Agustus", "September", "Oktober", "November", "Desember"]
KOLOM = ["periode", "produk", "kategori", "harga", "stok", "terjual"]

# PENTING: format teks kolom `periode` di tb_penjualan. Samakan dengan isi data awal di
# phpMyAdmin (tabel tb_penjualan, kolom periode). Default: "Januari 2025".
def label_periode(tgl: pd.Timestamp) -> str:
    return f"{BULAN[tgl.month - 1]} {tgl.year}"


def baca_dan_validasi(path: str) -> pd.DataFrame:
    df = pd.read_csv(path, encoding="utf-8-sig")
    df.columns = [c.strip().lower() for c in df.columns]
    kurang = [c for c in KOLOM if c not in df.columns]
    if kurang:
        sys.exit(f"Kolom hilang di CSV: {kurang}")
    df = df[KOLOM].copy()

    df["periode"] = pd.to_datetime(df["periode"], errors="coerce")
    for c in ("harga", "stok", "terjual"):
        df[c] = pd.to_numeric(df[c], errors="coerce")
    df["produk"] = df["produk"].astype(str).str.strip()
    # Samakan dengan penulisan kategori di database ('Aksesoris Mobil', 'GPS Tracking', dst.)
    df["kategori"] = (df["kategori"].astype(str).str.strip().str.title()
                      .replace({"Gps Tracking": "GPS Tracking"}))

    masalah = []
    if df.isna().any().any():
        masalah.append(f"Ada sel kosong/tidak valid: {df.isna().sum()[df.isna().sum() > 0].to_dict()}")
    if (df["periode"].dropna().dt.day != 1).any():
        masalah.append("Ada periode yang bukan tanggal 1.")
    if df.duplicated(["periode", "produk"]).any():
        masalah.append(f"Ada baris ganda periode+produk: {int(df.duplicated(['periode', 'produk']).sum())}")
    if (df.groupby("produk")["kategori"].nunique() > 1).any():
        masalah.append("Ada produk yang punya lebih dari satu kategori.")
    if (df[["harga", "stok", "terjual"]] < 0).any().any():
        masalah.append("Ada harga/stok/terjual bernilai negatif.")
    if masalah:
        sys.exit("CSV tidak valid:\n- " + "\n- ".join(masalah))

    if (df["terjual"] > df["stok"]).any():
        print(f"PERINGATAN: {int((df['terjual'] > df['stok']).sum())} baris terjual > stok.")
    for c in ("harga", "stok", "terjual"):
        df[c] = df[c].astype(int)
    return df.sort_values(["periode", "produk"]).reset_index(drop=True)


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("csv")
    ap.add_argument("--dry-run", action="store_true", help="hanya validasi, tidak menulis ke database")
    ap.add_argument("--reset", action="store_true", help="hapus isi tb_prediksi, tb_penjualan, tb_produk sebelum impor")
    args = ap.parse_args()

    df = baca_dan_validasi(args.csv)
    print(f"CSV valid: {len(df)} baris, {df['produk'].nunique()} produk, "
          f"{df['kategori'].nunique()} kategori, "
          f"{df['periode'].min():%Y-%m} s.d. {df['periode'].max():%Y-%m}")
    print("Contoh label periode:", label_periode(df["periode"].iloc[0]))
    if args.dry_run:
        print("Dry-run selesai, database tidak diubah.")
        return

    from database import get_connection  # memakai koneksi dari .env

    conn = get_connection()
    cur = conn.cursor()
    cur.execute("SELECT DATABASE()")
    print("Terhubung ke database:", cur.fetchone()[0], "<- pastikan sama dengan yang dibuka di phpMyAdmin")
    try:
        if args.reset:
            if input("Ini MENGHAPUS data tb_prediksi, tb_penjualan, tb_produk. Ketik HAPUS untuk lanjut: ") != "HAPUS":
                sys.exit("Dibatalkan.")
            cur.execute("DELETE FROM tb_prediksi")
            cur.execute("DELETE FROM tb_penjualan")
            cur.execute("DELETE FROM tb_produk")

        # 1) tb_produk: satu baris per produk (nama_produk unik)
        produk = df[["produk", "kategori"]].drop_duplicates("produk")
        cur.executemany(
            "INSERT INTO tb_produk (nama_produk, kategori) VALUES (%s,%s) "
            "ON DUPLICATE KEY UPDATE kategori=VALUES(kategori)",
            list(produk.itertuples(index=False, name=None)),
        )

        # 2) ambil id_produk
        cur.execute("SELECT id_produk, nama_produk FROM tb_produk")
        id_map = {nama: pid for pid, nama in cur.fetchall()}

        # 3) tb_penjualan: lewati baris yang sudah ada (aman dijalankan ulang)
        cur.execute("SELECT id_produk, periode_date FROM tb_penjualan")
        ada = {(pid, pd.Timestamp(d)) for pid, d in cur.fetchall()}
        baris = []
        for r in df.itertuples(index=False):
            pid = id_map[r.produk]
            if (pid, r.periode) in ada:
                continue
            baris.append((pid, label_periode(r.periode), r.periode.date(), r.harga, r.stok, r.terjual))
        if baris:
            cur.executemany(
                "INSERT INTO tb_penjualan (id_produk, periode, periode_date, harga, stok, terjual) "
                "VALUES (%s,%s,%s,%s,%s,%s)", baris)
        conn.commit()
        cur.execute("SELECT COUNT(*) FROM tb_produk")
        n_prod = cur.fetchone()[0]
        cur.execute("SELECT COUNT(*) FROM tb_penjualan")
        n_jual = cur.fetchone()[0]
        print(f"Isi database sekarang: tb_produk={n_prod}, tb_penjualan={n_jual}")
        print(f"Selesai: {len(produk)} produk diproses, {len(baris)} baris penjualan ditambahkan "
              f"({len(df) - len(baris)} dilewati karena sudah ada).")
    except Exception:
        conn.rollback()
        raise
    finally:
        cur.close()
        conn.close()


if __name__ == "__main__":
    main()