from decimal import Decimal, ROUND_HALF_UP


MONEY_FIELDS = [
    "kas", "simpanan", "piutang", "persediaan", "tanah", "bangunan", "kendaraan",
    "mesin", "peralatan", "inventaris", "aset_tetap_lainnya", "hutang_dagang",
    "hutang_bank", "hutang_leasing", "hutang_keluarga", "hutang_lainnya",
    "omzet_bulanan", "harga_pokok_penjualan", "biaya_operasional", "biaya_gaji",
    "biaya_listrik", "biaya_transport", "biaya_lainnya", "penerimaan_bulanan",
    "pengeluaran_bulanan", "penghasilan_bersih", "pengeluaran_rumah_tangga",
    "angsuran_lama", "estimasi_angsuran_baru", "luas_tanah", "luas_bangunan",
    "nilai_pasar", "nilai_likuidasi", "plafon_kredit", "suku_bunga",
]


def d(value):
    if value is None or value == "":
        return Decimal("0")
    return Decimal(str(value)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)


def pct(numerator, denominator):
    denominator = d(denominator)
    if denominator == 0:
        return Decimal("0")
    return (d(numerator) / denominator * Decimal("100")).quantize(Decimal("0.01"))


def ratio(numerator, denominator):
    denominator = d(denominator)
    if denominator == 0:
        return Decimal("0")
    return (d(numerator) / denominator).quantize(Decimal("0.01"))


def ratio_status(value, bands):
    value = d(value)
    for threshold, label in bands:
        if value >= Decimal(str(threshold)):
            return label
    return "Berisiko"


def calculate(row):
    total_aset_lancar = sum(d(getattr(row, key, 0)) for key in ["kas", "simpanan", "piutang", "persediaan"])
    total_aset_tetap = sum(
        d(getattr(row, key, 0))
        for key in ["tanah", "bangunan", "kendaraan", "mesin", "peralatan", "inventaris", "aset_tetap_lainnya"]
    )
    total_aset = total_aset_lancar + total_aset_tetap
    total_kewajiban = sum(
        d(getattr(row, key, 0))
        for key in ["hutang_dagang", "hutang_bank", "hutang_leasing", "hutang_keluarga", "hutang_lainnya"]
    )
    modal = total_aset - total_kewajiban

    total_biaya = sum(
        d(getattr(row, key, 0))
        for key in ["biaya_operasional", "biaya_gaji", "biaya_listrik", "biaya_transport", "biaya_lainnya"]
    )
    laba_kotor = d(row.omzet_bulanan) - d(row.harga_pokok_penjualan)
    laba_bersih = laba_kotor - total_biaya
    cash_flow_bersih = d(row.penerimaan_bulanan) - d(row.pengeluaran_bulanan)
    saldo_kas = d(row.kas) + cash_flow_bersih

    current_ratio = ratio(total_aset_lancar, total_kewajiban)
    debt_ratio = pct(total_kewajiban, total_aset)
    der = ratio(total_kewajiban, modal) if modal > 0 else Decimal("0")
    working_capital = total_aset_lancar - total_kewajiban
    roa = pct(laba_bersih, total_aset)
    roe = pct(laba_bersih, modal) if modal > 0 else Decimal("0")
    asset_turnover = ratio(d(row.omzet_bulanan), total_aset)

    penghasilan_tersedia = d(row.penghasilan_bersih) - d(row.pengeluaran_rumah_tangga) - d(row.angsuran_lama)
    kemampuan_membayar = penghasilan_tersedia
    rpc = pct(d(row.estimasi_angsuran_baru), kemampuan_membayar) if kemampuan_membayar > 0 else Decimal("0")
    sisa_penghasilan = kemampuan_membayar - d(row.estimasi_angsuran_baru)
    rpc_status = "Layak" if rpc <= 35 and sisa_penghasilan >= 0 else "Dipertimbangkan" if rpc <= 50 and sisa_penghasilan >= 0 else "Tidak Layak"

    total_5c = sum(int(getattr(row, key, 0) or 0) for key in [
        "score_character", "score_capacity", "score_capital", "score_collateral", "score_condition"
    ])
    percentage_5c = Decimal(total_5c * 100 / 25).quantize(Decimal("0.01"))
    if percentage_5c >= 80:
        conclusion_5c = "Sangat Baik"
    elif percentage_5c >= 65:
        conclusion_5c = "Baik"
    elif percentage_5c >= 50:
        conclusion_5c = "Cukup"
    elif percentage_5c >= 35:
        conclusion_5c = "Kurang"
    else:
        conclusion_5c = "Berisiko"

    coverage_agunan = pct(d(row.nilai_likuidasi), d(row.plafon_kredit))
    ltv = pct(d(row.plafon_kredit), d(row.nilai_pasar))

    monthly_rate = d(row.suku_bunga) / Decimal("100") / Decimal("12")
    tenor = int(row.tenor or 0)
    plafon = d(row.plafon_kredit)
    if plafon > 0 and tenor > 0:
        if monthly_rate > 0:
            factor = (Decimal("1") + monthly_rate) ** tenor
            angsuran_bulanan = plafon * monthly_rate * factor / (factor - Decimal("1"))
        else:
            angsuran_bulanan = plafon / tenor
    else:
        angsuran_bulanan = Decimal("0")
    angsuran_bulanan = angsuran_bulanan.quantize(Decimal("0.01"))
    total_pembayaran = (angsuran_bulanan * tenor).quantize(Decimal("0.01"))
    total_bunga = max(total_pembayaran - plafon, Decimal("0"))

    der_quality = "Sangat Baik" if der <= 0.5 else "Baik" if der <= 1 else "Cukup" if der <= 2 else "Kurang" if der <= 3 else "Berisiko"
    current_quality = ratio_status(current_ratio, [(2, "Sangat Baik"), (1.5, "Baik"), (1, "Cukup"), (0.75, "Kurang")])
    debt_quality = "Sangat Baik" if debt_ratio <= 30 else "Baik" if debt_ratio <= 50 else "Cukup" if debt_ratio <= 65 else "Kurang" if debt_ratio <= 80 else "Berisiko"

    score = 0
    reasons = []
    if rpc_status == "Layak":
        score += 30
        reasons.append("RPC berada dalam batas aman.")
    elif rpc_status == "Dipertimbangkan":
        score += 15
        reasons.append("RPC masih perlu mitigasi.")
    else:
        reasons.append("RPC melebihi batas kemampuan bayar.")
    if conclusion_5c in ["Sangat Baik", "Baik"]:
        score += 25
        reasons.append("Skor 5C mendukung kelayakan.")
    elif conclusion_5c == "Cukup":
        score += 12
        reasons.append("Skor 5C cukup namun perlu penguatan data.")
    if der <= 2 and modal > 0:
        score += 20
        reasons.append("Struktur modal masih sehat.")
    else:
        reasons.append("Leverage relatif tinggi.")
    if coverage_agunan >= 100 or d(row.nilai_likuidasi) == 0:
        score += 15
    if laba_bersih > 0 and cash_flow_bersih >= 0:
        score += 10
        reasons.append("Usaha menghasilkan laba dan arus kas positif.")
    else:
        reasons.append("Laba atau arus kas belum kuat.")

    recommendation = "Layak" if score >= 75 else "Layak Bersyarat" if score >= 55 else "Tidak Layak"
    rekomendasi_plafon = min(plafon, max(kemampuan_membayar * Decimal("0.35") * max(tenor, 1), Decimal("0"))).quantize(Decimal("0.01"))

    return {
        "total_aset_lancar": total_aset_lancar,
        "total_aset_tetap": total_aset_tetap,
        "total_aset": total_aset,
        "total_kewajiban": total_kewajiban,
        "modal": modal,
        "total_biaya": total_biaya,
        "laba_kotor": laba_kotor,
        "laba_bersih": laba_bersih,
        "cash_flow_bersih": cash_flow_bersih,
        "saldo_kas": saldo_kas,
        "current_ratio": current_ratio,
        "debt_ratio": debt_ratio,
        "der": der,
        "working_capital": working_capital,
        "net_worth": modal,
        "roa": roa,
        "roe": roe,
        "asset_turnover": asset_turnover,
        "current_quality": current_quality,
        "debt_quality": debt_quality,
        "der_quality": der_quality,
        "rpc": rpc,
        "kemampuan_membayar": kemampuan_membayar,
        "sisa_penghasilan": sisa_penghasilan,
        "rpc_status": rpc_status,
        "total_5c": total_5c,
        "percentage_5c": percentage_5c,
        "conclusion_5c": conclusion_5c,
        "recommendation_5c": "Lanjutkan analisis kredit." if percentage_5c >= 65 else "Perkuat verifikasi usaha dan mitigasi risiko.",
        "coverage_agunan": coverage_agunan,
        "ltv": ltv,
        "angsuran_bulanan": angsuran_bulanan,
        "total_bunga": total_bunga,
        "total_pembayaran": total_pembayaran,
        "recommendation": recommendation,
        "recommendation_reasons": reasons,
        "rekomendasi_plafon": rekomendasi_plafon,
    }

