"""Aplikasi Inventaris SQLite - antarmuka pengguna."""

import sqlite3

import database


def format_rupiah(nilai: int) -> str:
    """Format angka menjadi teks rupiah, contoh 15000 menjadi Rp15.000."""
    return "Rp" + f"{nilai:,}".replace(",", ".")


def cetak_tabel(rows: list) -> None:
    """Cetak daftar produk sebagai tabel rapi."""
    print(f"{'ID':<3} {'Nama':<18} {'Kategori':<10} {'Harga':>10} {'Stok':>4}")
    print(f"{'---':<3} {'-' * 18} {'-' * 10} {'-' * 10} {'-' * 4}")
    for row in rows:
        print(
            f"{row['id']:<3} {row['nama']:<18} {row['kategori']:<10} "
            f"{format_rupiah(row['harga']):>10} {row['stok']:>4}"
        )


def baca_angka(prompt: str) -> int:
    """Minta masukan angka bulat, ulangi sampai masukan sah."""
    while True:
        teks = input(prompt).strip()
        try:
            return int(teks)
        except ValueError:
            print("Masukkan angka bulat, misalnya 15000.")


def menu_tambah(conn: sqlite3.Connection) -> None:
    nama = input("Nama produk: ").strip()
    kategori = input("Kategori: ").strip()
    harga = baca_angka("Harga (Rp): ")
    stok = baca_angka("Stok awal: ")

    try:
        database.validasi_produk(nama, kategori, harga, stok)
    except ValueError as galat:
        print(f"Gagal: {galat}")
        return

    try:
        id_baru = database.tambah_produk(conn, nama, kategori, harga, stok)
    except sqlite3.IntegrityError:
        print(f"Produk dengan nama '{nama}' sudah terdaftar.")
        return

    print(f"Produk '{nama}' tersimpan dengan id {id_baru}.")


def menu_lihat(conn: sqlite3.Connection) -> None:
    rows = database.lihat_produk(conn)
    if not rows:
        print("Belum ada produk.")
        return
    cetak_tabel(rows)


def menu_cari(conn: sqlite3.Connection) -> None:
    keyword = input("Kata kunci nama: ").strip()
    if not keyword:
        print("Kata kunci tidak boleh kosong.")
        return
    hasil = database.cari_produk(conn, keyword)
    if not hasil:
        print(f"Tidak ada produk yang mengandung '{keyword}'.")
        return
    print(f"Hasil pencarian untuk '{keyword}':")
    cetak_tabel(hasil)


def menu_filter(conn: sqlite3.Connection) -> None:
    kategori = input("Kategori: ").strip()
    if not kategori:
        print("Kategori tidak boleh kosong.")
        return
    hasil = database.filter_kategori(conn, kategori)
    if not hasil:
        print(f"Tidak ada produk pada kategori '{kategori}'.")
        return
    print(f"Produk pada kategori '{kategori}':")
    cetak_tabel(hasil)


def menu_ubah_harga(conn: sqlite3.Connection) -> None:
    produk_id = baca_angka("ID produk: ")
    harga_baru = baca_angka("Harga baru (Rp): ")
    if database.perbarui_harga(conn, produk_id, harga_baru):
        print("Harga berhasil diperbarui.")
    else:
        print(f"Tidak ada produk dengan id {produk_id}.")


def menu_sesuaikan_stok(conn: sqlite3.Connection) -> None:
    produk_id = baca_angka("ID produk: ")
    perubahan = baca_angka("Perubahan stok (boleh negatif): ")
    keterangan = input("Keterangan: ").strip() or "penyesuaian manual"

    try:
        database.sesuaikan_stok(conn, produk_id, perubahan, keterangan)
    except ValueError as galat:
        print(f"Gagal: {galat}")
        return
    except sqlite3.IntegrityError:
        print("Gagal: penyesuaian membuat stok negatif. Transaksi dibatalkan.")
        return

    print("Stok berhasil disesuaikan.")


def menu_hapus(conn: sqlite3.Connection) -> None:
    produk_id = baca_angka("ID produk: ")
    if database.hapus_produk(conn, produk_id):
        print("Produk berhasil dihapus.")
    else:
        print(f"Tidak ada produk dengan id {produk_id}.")


def menu_riwayat(conn: sqlite3.Connection) -> None:
    produk_id = baca_angka("ID produk: ")
    produk = database.ambil_produk(conn, produk_id)
    if produk is None:
        print(f"Tidak ada produk dengan id {produk_id}.")
        return

    rows = database.lihat_riwayat(conn, produk_id)
    if not rows:
        print(f"Belum ada riwayat untuk '{produk['nama']}'.")
        return

    print(f"Riwayat untuk '{produk['nama']}':")
    print(f"{'Waktu':<21} {'Perubahan':>9}  Keterangan")
    for row in rows:
        print(f"{row['waktu']:<21} {row['perubahan']:>+9}  {row['keterangan']}")


def menu_stok_menipis(conn: sqlite3.Connection) -> None:
    hasil = database.laporan_stok_menipis(conn)
    if not hasil:
        print(f"Tidak ada produk dengan stok di bawah {database.BATAS_STOK_MENIPIS}.")
        return
    print(f"Produk dengan stok di bawah {database.BATAS_STOK_MENIPIS}:")
    print(f"{'ID':<3} {'Nama':<18} {'Kategori':<10} {'Stok':>4}")
    print(f"{'---':<3} {'-' * 18} {'-' * 10} {'-' * 4}")
    for row in hasil:
        print(f"{row['id']:<3} {row['nama']:<18} {row['kategori']:<10} {row['stok']:>4}")


def menu_nilai_inventaris(conn: sqlite3.Connection) -> None:
    hasil = database.nilai_inventaris_per_kategori(conn)
    if not hasil:
        print("Belum ada produk untuk dihitung.")
        return
    print(f"{'Kategori':<12} {'Jumlah':>7} {'Nilai Total':>13}")
    print(f"{'-' * 12} {'-' * 7} {'-' * 13}")
    total_nilai = 0
    total_produk = 0
    for row in hasil:
        print(
            f"{row['kategori']:<12} {row['jumlah_produk']:>7} "
            f"{format_rupiah(row['nilai_total']):>13}"
        )
        total_nilai += row["nilai_total"]
        total_produk += row["jumlah_produk"]
    print(f"{'-' * 12} {'-' * 7} {'-' * 13}")
    print(f"{'TOTAL':<12} {total_produk:>7} {format_rupiah(total_nilai):>13}")


def menu_top_produk(conn: sqlite3.Connection) -> None:
    hasil = database.top_produk(conn)
    if not hasil:
        print("Belum ada produk untuk dihitung.")
        return
    print(f"Top {database.JUMLAH_TOP_PRODUK} produk berdasarkan nilai stok:")
    print(f"{'#':<3} {'Nama':<18} {'Harga':>10} {'Stok':>4} {'Nilai':>12}")
    print(f"{'---':<3} {'-' * 18} {'-' * 10} {'-' * 4} {'-' * 12}")
    for peringkat, row in enumerate(hasil, start=1):
        print(
            f"{peringkat:<3} {row['nama']:<18} "
            f"{format_rupiah(row['harga']):>10} {row['stok']:>4} "
            f"{format_rupiah(row['nilai']):>12}"
        )


def tampilkan_menu() -> None:
    print()
    print("=== Aplikasi Inventaris ===")
    print("1. Tambah produk")
    print("2. Lihat semua produk")
    print("3. Ubah harga")
    print("4. Sesuaikan stok (+/-)")
    print("5. Hapus produk")
    print("6. Riwayat produk")
    print("7. Cari produk")
    print("8. Filter per kategori")
    print("9. Laporan stok menipis")
    print("10. Nilai inventaris per kategori")
    print("11. Top produk")
    print("0. Keluar")


def tangani_pilihan(conn: sqlite3.Connection, pilihan: str) -> None:
    match pilihan:
        case "1":
            menu_tambah(conn)
        case "2":
            menu_lihat(conn)
        case "3":
            menu_ubah_harga(conn)
        case "4":
            menu_sesuaikan_stok(conn)
        case "5":
            menu_hapus(conn)
        case "6":
            menu_riwayat(conn)
        case "7":
            menu_cari(conn)
        case "8":
            menu_filter(conn)
        case "9":
            menu_stok_menipis(conn)
        case "10":
            menu_nilai_inventaris(conn)
        case "11":
            menu_top_produk(conn)
        case _:
            print("Pilihan tidak dikenal.")


def main() -> None:
    database.inisialisasi()
    conn = database.koneksi()
    try:
        print("Database siap. Selamat datang!")
        while True:
            tampilkan_menu()
            try:
                pilihan = input("Pilih menu: ").strip()
            except EOFError:
                print()
                break

            if pilihan == "0":
                print("Sampai jumpa!")
                break

            tangani_pilihan(conn, pilihan)
    finally:
        conn.close()


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\nProgram dihentikan.")
