#!/usr/bin/env python3
"""
LANGKAH 6 — Segmentasi RFM wajib pajak: siapa yang patuh, siapa yang mulai menghilang.

Dari data transaksi yang sama dengan langkah 5, setiap WP diberi tiga nilai:
  R (recency)   berapa hari sejak setoran terakhir — makin kecil makin baik
  F (frequency) berapa kali menyetor dalam periode pengamatan
  M (monetary)  total nominal setoran

Masing-masing diubah jadi skor 1–5 (kuintil), lalu digolongkan:
  Andalan        R tinggi, F tinggi, M tinggi  → pertahankan, layani dengan baik
  Patuh          R tinggi, F tinggi            → pantau rutin
  Mulai Renggang R sedang/rendah, F dulu tinggi → prioritas imbauan/penagihan
  Hilang         R sangat rendah               → verifikasi: tutup, pindah, atau menunggak?
  Baru/Kecil     sisanya                        → pembinaan

Kebutuhan: Python 3.9+, tanpa pustaka tambahan.

Contoh:
  python3 6_rfm_wp.py --masukan contoh/contoh_transaksi.csv --tanggal-acuan 2025-12-31
"""

import argparse
import csv
from collections import Counter, defaultdict
from datetime import datetime

# Fungsi baca tanggal & nominal sama dengan langkah 5.
from importlib import import_module

bt = import_module("5_backtest_proyeksi")


def kuintil(nilai, terbalik=False):
    """Skor 1–5 berdasarkan peringkat; terbalik=True untuk recency (hari sedikit = skor tinggi)."""
    urut = sorted(nilai, key=nilai.get, reverse=terbalik)
    n = len(urut)
    return {k: 1 + min(4, i * 5 // n) for i, k in enumerate(urut)}


def golongan(r, f, m):
    if r >= 4 and f >= 4 and m >= 4:
        return "Andalan"
    if r >= 4 and f >= 3:
        return "Patuh"
    if r <= 1:
        return "Hilang"
    if f >= 3 and r <= 3:
        return "Mulai Renggang"
    return "Baru/Kecil"


def main():
    p = argparse.ArgumentParser(description="Segmentasi RFM wajib pajak.")
    p.add_argument("--masukan", required=True)
    p.add_argument("--kolom-id", default="id_wp")
    p.add_argument("--kolom-nama", default="nama_wp")
    p.add_argument("--kolom-tanggal", default="tanggal_bayar")
    p.add_argument("--kolom-nominal", default="nominal")
    p.add_argument("--jenis-pajak", help="batasi ke satu jenis pajak (nilai kolom jenis_pajak)")
    p.add_argument("--tanggal-acuan", help="YYYY-MM-DD; bawaan = tanggal setoran terakhir di data")
    p.add_argument("--keluaran", default="rfm_wp.csv")
    a = p.parse_args()

    terakhir, frek, total, nama = {}, defaultdict(int), defaultdict(float), {}
    with open(a.masukan, encoding="utf-8") as fh:
        for r in csv.DictReader(fh):
            if a.jenis_pajak and r.get("jenis_pajak", "").strip() != a.jenis_pajak:
                continue
            wp = r[a.kolom_id].strip()
            tgl = bt.baca_tanggal(r[a.kolom_tanggal])
            nama[wp] = r.get(a.kolom_nama, "")
            terakhir[wp] = max(terakhir.get(wp, tgl), tgl)
            frek[wp] += 1
            total[wp] += bt.baca_nominal(r[a.kolom_nominal])

    acuan = datetime.strptime(a.tanggal_acuan, "%Y-%m-%d") if a.tanggal_acuan else max(terakhir.values())
    hari = {wp: (acuan - t).days for wp, t in terakhir.items()}

    sr = kuintil(hari, terbalik=True)
    sf = kuintil(frek)
    sm = kuintil(total)

    baris = []
    for wp in terakhir:
        g = golongan(sr[wp], sf[wp], sm[wp])
        baris.append({
            "id_wp": wp, "nama_wp": nama[wp], "hari_sejak_setor": hari[wp],
            "jumlah_setor": frek[wp], "total_setor": round(total[wp]),
            "R": sr[wp], "F": sf[wp], "M": sm[wp], "segmen": g,
        })
    baris.sort(key=lambda b: (b["segmen"], -b["total_setor"]))

    with open(a.keluaran, "w", newline="", encoding="utf-8") as fh:
        w = csv.DictWriter(fh, fieldnames=list(baris[0].keys()))
        w.writeheader()
        w.writerows(baris)

    hitung = Counter(b["segmen"] for b in baris)
    nilai = defaultdict(float)
    for b in baris:
        nilai[b["segmen"]] += b["total_setor"]
    semua = sum(nilai.values()) or 1
    print(f"{len(baris)} WP disegmentasi (acuan {acuan:%d-%m-%Y})")
    for s in ("Andalan", "Patuh", "Mulai Renggang", "Hilang", "Baru/Kecil"):
        print(f"  {s:<15} {hitung[s]:>5} WP   {100 * nilai[s] / semua:5.1f}% nilai setoran")
    print(f"Disimpan ke {a.keluaran}")


if __name__ == "__main__":
    main()
