"""Laporan bulanan untuk Pencatat Keuangan Pribadi."""

from contextlib import closing

import db


def ringkasan_bulanan(bulan, path=db.NAMA_DB):
    """Totalkan pemasukan, pengeluaran, dan saldo satu bulan (format YYYY-MM)."""
    with closing(db.get_connection(path)) as con:
        return con.execute(
            "SELECT"
            " COALESCE(SUM(CASE WHEN jenis = 'masuk' THEN jumlah END), 0) AS total_masuk,"
            " COALESCE(SUM(CASE WHEN jenis = 'keluar' THEN jumlah END), 0) AS total_keluar,"
            " COALESCE(SUM(CASE WHEN jenis = 'masuk' THEN jumlah END), 0)"
            " - COALESCE(SUM(CASE WHEN jenis = 'keluar' THEN jumlah END), 0) AS saldo"
            " FROM transaksi WHERE strftime('%Y-%m', tanggal) = ?",
            (bulan,),
        ).fetchone()


def kategori_terbesar(bulan, batas=3, path=db.NAMA_DB):
    """Ambil kategori pengeluaran terbesar pada satu bulan."""
    with closing(db.get_connection(path)) as con:
        return con.execute(
            "SELECT kategori, COUNT(*) AS jumlah_transaksi, SUM(jumlah) AS total"
            " FROM transaksi"
            " WHERE jenis = 'keluar' AND strftime('%Y-%m', tanggal) = ?"
            " GROUP BY kategori"
            " ORDER BY total DESC, kategori"
            " LIMIT ?",
            (bulan, batas),
        ).fetchall()


def rincian_per_kategori(bulan, path=db.NAMA_DB):
    """Hitung jumlah transaksi serta total masuk dan keluar tiap kategori."""
    with closing(db.get_connection(path)) as con:
        return con.execute(
            "SELECT kategori, COUNT(*) AS jumlah_transaksi,"
            " SUM(CASE WHEN jenis = 'masuk' THEN jumlah ELSE 0 END) AS total_masuk,"
            " SUM(CASE WHEN jenis = 'keluar' THEN jumlah ELSE 0 END) AS total_keluar"
            " FROM transaksi"
            " WHERE strftime('%Y-%m', tanggal) = ?"
            " GROUP BY kategori"
            " ORDER BY total_keluar DESC, kategori",
            (bulan,),
        ).fetchall()


def tampilkan_laporan(bulan, path=db.NAMA_DB):
    """Cetak laporan lengkap satu bulan ke layar."""
    ringkasan = ringkasan_bulanan(bulan, path)
    if ringkasan["total_masuk"] == 0 and ringkasan["total_keluar"] == 0:
        print(f"Tidak ada transaksi pada bulan {bulan}.")
        return

    print(f"=== Laporan Bulan {bulan} ===")
    print(f"Total pemasukan  : {db.format_rupiah(ringkasan['total_masuk'])}")
    print(f"Total pengeluaran: {db.format_rupiah(ringkasan['total_keluar'])}")
    print(f"Saldo            : {db.format_rupiah(ringkasan['saldo'])}")

    print()
    print("Pengeluaran terbesar:")
    for nomor, baris in enumerate(kategori_terbesar(bulan, path=path), start=1):
        print(
            f"{nomor}. {baris['kategori']:<13}"
            f" {db.format_rupiah(baris['total'])} ({baris['jumlah_transaksi']} transaksi)"
        )

    print()
    print("Rincian per kategori:")
    for baris in rincian_per_kategori(bulan, path=path):
        if baris["total_masuk"] > 0:
            print(
                f"{baris['kategori']:<14} {baris['jumlah_transaksi']:>2} transaksi"
                f"  masuk   {db.format_rupiah(baris['total_masuk'])}"
            )
        if baris["total_keluar"] > 0:
            print(
                f"{baris['kategori']:<14} {baris['jumlah_transaksi']:>2} transaksi"
                f"  keluar  {db.format_rupiah(baris['total_keluar'])}"
            )


def main():
    db.init_db()
    bulan = input("Bulan laporan (YYYY-MM): ").strip()
    tampilkan_laporan(bulan)


if __name__ == "__main__":
    main()
