import { supabase } from "@/integrations/supabase/client";

export type Jenis = "pemasukan" | "pengeluaran";
export type Kas = "operasional" | "besar";

export type Transaksi = {
  id: string;
  jenis: Jenis;
  nominal: number;
  tanggal: string;
  kategori: string;
  catatan: string | null;
  sumber: string | null;
  tujuan: string | null;
  bukti_path: string | null;
  bukti_nama: string | null;
  created_at: string;
  user_id: string | null;
  kas: Kas;
};

export const KATEGORI_PENGELUARAN = [
  "Makan",
  "Belanja",
  "Transportasi",
  "Sewa",
  "Tagihan",
  "Hiburan",
  "Kesehatan",
  "Transfer",
  "Lainnya",
];

export const KATEGORI_PEMASUKAN = [
  "Gaji",
  "Freelance",
  "Bonus",
  "Investasi",
  "Hadiah",
  "Lainnya",
];

export const KATEGORI_ADMIN_PENGELUARAN = [
  "Pembelian Barang",
  "Topup Petty Cash",
  "Pembayaran Project",
  "Gaji Karyawan",
  "Operasional Kantor",
  "Pajak & Legal",
  "Lainnya",
];

export const KATEGORI_ADMIN_PEMASUKAN = [
  "Pembayaran Project",
  "Modal Masuk",
  "Penjualan",
  "Pengembalian Dana",
  "Lainnya",
];

export const KATEGORI_TOPUP = "Topup Petty Cash";

export const SEMUA_KATEGORI = Array.from(
  new Set([
    ...KATEGORI_PEMASUKAN,
    ...KATEGORI_PENGELUARAN,
    ...KATEGORI_ADMIN_PEMASUKAN,
    ...KATEGORI_ADMIN_PENGELUARAN,
  ]),
).sort();

export function daftarKategori(kas: Kas, jenis: Jenis) {
  if (kas === "besar") {
    return jenis === "pemasukan" ? KATEGORI_ADMIN_PEMASUKAN : KATEGORI_ADMIN_PENGELUARAN;
  }
  return jenis === "pemasukan" ? KATEGORI_PEMASUKAN : KATEGORI_PENGELUARAN;
}

export function formatRupiah(n: number) {
  return new Intl.NumberFormat("id-ID", {
    style: "currency",
    currency: "IDR",
    maximumFractionDigits: 0,
  }).format(n);
}

export function formatTanggal(iso: string) {
  return new Date(iso + "T00:00:00").toLocaleDateString("id-ID", {
    day: "numeric",
    month: "long",
    year: "numeric",
  });
}

export function formatTanggalPendek(iso: string) {
  return new Date(iso + "T00:00:00").toLocaleDateString("id-ID", {
    day: "numeric",
    month: "short",
  });
}

export async function ambilTransaksi(kas?: Kas): Promise<Transaksi[]> {
  let q = supabase.from("transaksi").select("*");
  if (kas) q = q.eq("kas", kas);
  const { data, error } = await q
    .order("tanggal", { ascending: false })
    .order("created_at", { ascending: false });
  if (error) throw error;
  return (data ?? []) as Transaksi[];
}

export async function ambilTransaksiSatu(id: string): Promise<Transaksi | null> {
  const { data, error } = await supabase.from("transaksi").select("*").eq("id", id).maybeSingle();
  if (error) throw error;
  return (data as Transaksi) ?? null;
}

export async function unggahBukti(file: File): Promise<{ path: string; nama: string }> {
  const ext = file.name.split(".").pop() ?? "dat";
  const path = `${crypto.randomUUID()}.${ext}`;
  const { error } = await supabase.storage.from("bukti").upload(path, file);
  if (error) throw error;
  return { path, nama: file.name };
}

export async function urlBukti(path: string): Promise<string | null> {
  const { data, error } = await supabase.storage.from("bukti").createSignedUrl(path, 60 * 60);
  if (error) return null;
  return data.signedUrl;
}

export type BaruTransaksi = {
  jenis: Jenis;
  nominal: number;
  tanggal: string;
  kategori: string;
  kas?: Kas;
  catatan?: string | null;
  sumber?: string | null;
  tujuan?: string | null;
  bukti_path?: string | null;
  bukti_nama?: string | null;
};

async function idPengguna() {
  const { data } = await supabase.auth.getUser();
  const id = data.user?.id;
  if (!id) throw new Error("Sesi berakhir. Silakan masuk kembali.");
  return id;
}

export async function simpanTransaksi(input: BaruTransaksi) {
  const user_id = await idPengguna();
  const { error } = await supabase
    .from("transaksi")
    .insert({ ...input, kas: input.kas ?? "operasional", user_id });
  if (error) throw error;
}

/** Topup dari kas besar ke petty cash: keluar di kas besar, masuk di kas operasional. */
export async function topupPettyCash(input: {
  nominal: number;
  tanggal: string;
  catatan?: string | null;
  sumber?: string | null;
}) {
  const user_id = await idPengguna();
  const dasar = {
    nominal: input.nominal,
    tanggal: input.tanggal,
    kategori: KATEGORI_TOPUP,
    catatan: input.catatan ?? null,
    user_id,
  };
  const { error } = await supabase.from("transaksi").insert([
    { ...dasar, jenis: "pengeluaran", kas: "besar", sumber: input.sumber ?? "Kas besar", tujuan: "Petty cash" },
    { ...dasar, jenis: "pemasukan", kas: "operasional", sumber: input.sumber ?? "Kas besar", tujuan: "Petty cash" },
  ]);
  if (error) throw error;
}

export async function hapusTransaksi(id: string) {
  const { error } = await supabase.from("transaksi").delete().eq("id", id);
  if (error) throw error;
}

export function ringkasBulanIni(items: Transaksi[]) {
  const now = new Date();
  const kunci = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
  const bulanIni = items.filter((t) => t.tanggal.startsWith(kunci));
  const masuk = bulanIni
    .filter((t) => t.jenis === "pemasukan")
    .reduce((a, t) => a + Number(t.nominal), 0);
  const keluar = bulanIni
    .filter((t) => t.jenis === "pengeluaran")
    .reduce((a, t) => a + Number(t.nominal), 0);
  const saldo = items.reduce(
    (a, t) => a + (t.jenis === "pemasukan" ? Number(t.nominal) : -Number(t.nominal)),
    0,
  );
  return { masuk, keluar, saldo, jumlah: bulanIni.length };
}
