#!/usr/bin/env python3
"""
LANGKAH 4 — Scoring: menyusun urutan siapa yang didatangi petugas lebih dulu.

Setiap KANDIDAT_BARU diberi skor 0–100 dari lima komponen (masing-masing dinormalkan 0–1):

  ulasan    jumlah ulasan (skala log) — bukti usaha ramai dan masih hidup
  rating    nilai rating — usaha yang dinilai baik cenderung stabil
  harga     tingkat harga 0–4 — indikasi kasar ukuran omzet
  kategori  inti = 1, abu-abu = 0,5 — keyakinan bahwa ia memang objek pajak
  celah     1 − cakupan kecamatan — prioritaskan wilayah yang paling banyak terlewat

Bobot bawaan 30/10/20/20/20 adalah TITIK AWAL, bukan kebenaran. Ubah lewat argumen
lalu bandingkan daftar teratas sebelum dan sesudahnya. Setelah uji petik lapangan,
kalibrasi bobot dengan melihat komponen mana yang paling membedakan kandidat
yang terbukti layak pajak.

Keluaran tambahan: ringkasan cakupan per kecamatan (peta selisih).

Contoh:
  python3 4_skor_prioritas.py --masukan hasil_cocok.csv --keluaran daftar_survei.csv
  python3 4_skor_prioritas.py --masukan hasil_cocok.csv --bobot 40 10 20 10 20
"""

import argparse
import csv
import math
from collections import defaultdict


def angka(x, bawaan=0.0):
    try:
        return float(x)
    except (TypeError, ValueError):
        return bawaan


def main():
    p = argparse.ArgumentParser(description="Skor prioritas kandidat WP baru.")
    p.add_argument("--masukan", required=True, help="keluaran langkah 3")
    p.add_argument("--keluaran", default="daftar_survei.csv")
    p.add_argument("--keluaran-cakupan", default="cakupan_kecamatan.csv")
    p.add_argument("--bobot", nargs=5, type=float, default=[30, 10, 20, 20, 20],
                   metavar=("ULASAN", "RATING", "HARGA", "KATEGORI", "CELAH"))
    p.add_argument("--ikutkan-perlu-cek", action="store_true",
                   help="ikut skor baris PERLU_CEK (diberi tanda)")
    a = p.parse_args()

    with open(a.masukan, encoding="utf-8") as f:
        baris = list(csv.DictReader(f))

    # Cakupan per kecamatan = terdaftar ÷ objek terdeteksi.
    terdeteksi, terdaftar = defaultdict(int), defaultdict(int)
    for b in baris:
        k = b.get("kecamatan", "")
        terdeteksi[k] += 1
        if b["status"] == "TERDAFTAR":
            terdaftar[k] += 1
    cakupan = {k: terdaftar[k] / terdeteksi[k] for k in terdeteksi}

    status_ikut = {"KANDIDAT_BARU"} | ({"PERLU_CEK"} if a.ikutkan_perlu_cek else set())
    kandidat = [b for b in baris if b["status"] in status_ikut]
    if not kandidat:
        print("Tidak ada kandidat untuk diskor.")
        return

    maks_log = max(math.log1p(angka(b.get("jumlah_ulasan"))) for b in kandidat) or 1.0
    total_bobot = sum(a.bobot)
    w = [x / total_bobot for x in a.bobot]

    for b in kandidat:
        komp = [
            math.log1p(angka(b.get("jumlah_ulasan"))) / maks_log,
            angka(b.get("rating")) / 5.0,
            # harga kosong (tidak diketahui) diberi nilai tengah, bukan nol
            angka(b.get("tingkat_harga"), 2.0) / 4.0,
            1.0 if b.get("keranjang") == "inti" else 0.5,
            1.0 - cakupan.get(b.get("kecamatan", ""), 0.0),
        ]
        b["skor"] = round(100 * sum(wi * ki for wi, ki in zip(w, komp)), 1)
        for nama, k in zip(("k_ulasan", "k_rating", "k_harga", "k_kategori", "k_celah"), komp):
            b[nama] = f"{k:.2f}"

    kandidat.sort(key=lambda b: -b["skor"])
    for i, b in enumerate(kandidat, 1):
        b["peringkat"] = i

    depan = ["peringkat", "skor", "nama", "alamat", "kecamatan", "sektor", "keranjang",
             "status", "lat", "lng", "jumlah_ulasan", "rating", "tingkat_harga"]
    kolom = depan + [k for k in kandidat[0] if k not in depan]
    with open(a.keluaran, "w", newline="", encoding="utf-8") as f:
        wr = csv.DictWriter(f, fieldnames=kolom)
        wr.writeheader()
        wr.writerows(kandidat)

    with open(a.keluaran_cakupan, "w", newline="", encoding="utf-8") as f:
        wr = csv.writer(f)
        wr.writerow(["kecamatan", "objek_terdeteksi", "wp_terdaftar", "cakupan_persen"])
        for k in sorted(cakupan, key=cakupan.get):
            wr.writerow([k, terdeteksi[k], terdaftar[k], f"{100 * cakupan[k]:.1f}"])

    print(f"{len(kandidat)} kandidat diskor. 10 teratas:")
    for b in kandidat[:10]:
        print(f"  {b['peringkat']:>3}. {b['skor']:>5}  {b['nama'][:40]:<40} {b.get('kecamatan', '')}")
    print("\nCakupan per kecamatan (terendah = ruang ekstensifikasi terbesar):")
    for k in sorted(cakupan, key=cakupan.get):
        print(f"  {k:<28} {100 * cakupan[k]:5.1f}%  ({terdaftar[k]}/{terdeteksi[k]})")
    print(f"\nDisimpan ke {a.keluaran} dan {a.keluaran_cakupan}")


if __name__ == "__main__":
    main()
