# -*- coding: utf-8 -*-
# [SKRIP I3.8] Aturan kualitas data sebagai ekspresi QGIS: tiap aturan dihitung dengan QgsFeatureRequest (filter ekspresi)
# dan semuanya digabung menjadi satu kolom virtual Status_Mutu.
# Penulis: Badar Mubarok Yogaswara
# Dijalankan di Python Console QGIS (proyek boleh kosong). Hanya MEMBACA data.
from qgis.core import (QgsVectorLayer, QgsProject, QgsExpression, QgsFeatureRequest, QgsField, QgsExpressionContext,
                       QgsExpressionContextUtils)
from qgis.PyQt.QtCore import QMetaType

JALUR = r"D:/KPH_Contoh/paket-i3/Survei_Lapangan.gpkg"
titik = QgsVectorLayer(JALUR + "|layername=Titik_Survei", "Titik_Survei", "ogr")
batas = QgsVectorLayer(JALUR + "|layername=Batas_KPH", "Batas_KPH", "ogr")
QgsProject.instance().addMapLayers([titik, batas])      # ekspresi overlay_within memerlukan layer batas ada di proyek

ATURAN = {
    "Kondisi kosong": '"Kondisi" IS NULL',
    "Kondisi tidak baku": '"Kondisi" IS NOT NULL AND "Kondisi" NOT IN (\'Sehat\',\'Terserang Hama\',\'Tebangan Liar\')',
    "Tinggi di luar 0-60": '"Tinggi_Phn" NOT BETWEEN 0 AND 60',
    "Akurasi lebih dari 5 m": '"Akurasi_m" > 5',
    "Tanggal di luar periode": '"Tgl_Survei" NOT BETWEEN to_date(\'2026-09-01\') AND to_date(\'2026-09-12\')',
    "ID ganda": 'count("ID_Survei", group_by:="ID_Survei") > 1',
    "Di luar semua petak": 'NOT overlay_within(\'Batas_KPH\')',
    "Label KPH tidak sesuai": 'overlay_within(\'Batas_KPH\', "NAMA_KPH")[0] <> "KPH"',
}

print("Jumlah baris:", titik.featureCount())
konteks = QgsExpressionContext()
konteks.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(titik))    # agar count(), overlay_*() bekerja
for nama, ekspresi in ATURAN.items():
    permintaan = QgsFeatureRequest().setFilterExpression(ekspresi).setExpressionContext(konteks)
    n = len(list(titik.getFeatures(permintaan)))
    print("%-26s %d" % (nama, n))

# Satu kolom virtual: kata kunci masalah pertama yang ditemukan, atau OK
cabang = " ".join("WHEN %s THEN '%s'" % (e, n.replace("'", "''")) for n, e in ATURAN.items())
titik.addExpressionField("CASE %s ELSE 'OK' END" % cabang, QgsField("Status_Mutu", QMetaType.Type.QString))
hitung = {}
for f in titik.getFeatures():
    hitung[f["Status_Mutu"]] = hitung.get(f["Status_Mutu"], 0) + 1
print("Status_Mutu:", hitung)
