import type {
	LaporanCatatanData,
	LaporanHutangPiutangDetailData,
	LaporanPenjualanData
} from '$lib/types/laporan-detail';
import type { LaporanData } from '$lib/types/laporan';
import { formatRupiah } from '$lib/utils/format';
import { formatLaporanTanggalLabel } from '$lib/utils/laporan-date';
import type { jsPDF } from 'jspdf';

type AutoTableFn = (doc: jsPDF, options: Record<string, unknown>) => void;

async function loadPdfLibs(): Promise<{ doc: jsPDF; autoTable: AutoTableFn; pageWidth: number }> {
	const { jsPDF } = await import('jspdf');
	const { default: autoTable } = await import('jspdf-autotable');
	const doc = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' });
	return { doc, autoTable: autoTable as AutoTableFn, pageWidth: doc.internal.pageSize.getWidth() };
}

function formatTanggalId(dateStr: string): string {
	return new Date(dateStr).toLocaleDateString('id-ID', {
		day: 'numeric',
		month: 'long',
		year: 'numeric'
	});
}

function formatSekarang(): string {
	return new Date().toLocaleString('id-ID', {
		day: 'numeric',
		month: 'long',
		year: 'numeric',
		hour: '2-digit',
		minute: '2-digit'
	});
}

function addPdfHeader(
	doc: jsPDF,
	pageWidth: number,
	title: string,
	warungNama: string,
	subtitle: string,
	headerColor: [number, number, number] = [79, 70, 229]
): number {
	doc.setFillColor(...headerColor);
	doc.rect(0, 0, pageWidth, 38, 'F');
	doc.setTextColor(255, 255, 255);
	doc.setFontSize(16);
	doc.setFont('helvetica', 'bold');
	doc.text(title, pageWidth / 2, 14, { align: 'center' });
	doc.setFontSize(11);
	doc.setFont('helvetica', 'normal');
	doc.text(warungNama, pageWidth / 2, 22, { align: 'center' });
	doc.setFontSize(9);
	doc.text(subtitle, pageWidth / 2, 30, { align: 'center' });
	doc.setTextColor(30, 30, 30);
	return 48;
}

function addPdfFooters(doc: jsPDF, memberNama: string, footerLabel: string): void {
	const pageWidth = doc.internal.pageSize.getWidth();
	const totalPages = doc.getNumberOfPages();
	for (let i = 1; i <= totalPages; i++) {
		doc.setPage(i);
		doc.setFontSize(8);
		doc.setTextColor(120, 120, 120);
		doc.text(
			`Dicetak: ${formatSekarang()} · Pemilik: ${memberNama} · Halaman ${i}/${totalPages}`,
			pageWidth / 2,
			doc.internal.pageSize.getHeight() - 8,
			{ align: 'center' }
		);
		doc.text(footerLabel, 14, doc.internal.pageSize.getHeight() - 8);
	}
}

function savePdf(doc: jsPDF, filename: string): void {
	doc.save(filename);
}

function sanitizeFilename(value: string): string {
	return value.replace(/\s+/g, '-').toLowerCase();
}

export async function exportLaporanPdf(data: LaporanData): Promise<void> {
	const { doc, autoTable, pageWidth } = await loadPdfLibs();
	let y = addPdfHeader(
		doc,
		pageWidth,
		'LAPORAN KEUANGAN WARUNG',
		data.warungNama,
		`Periode: ${data.periodeLabel} (${formatTanggalId(data.tanggalAwal)} - ${formatTanggalId(data.tanggalAkhir)})`
	);

	doc.setFontSize(12);
	doc.setFont('helvetica', 'bold');
	doc.text('Ringkasan Keuangan', 14, y);
	y += 4;

	autoTable(doc, {
		startY: y,
		head: [['Keterangan', 'Nominal']],
		body: [
			['Pendapatan Penjualan', formatRupiah(data.ringkasan.pendapatanPenjualan)],
			['Pendapatan Lainnya', formatRupiah(data.ringkasan.pendapatanLain)],
			['Total Pendapatan', formatRupiah(data.ringkasan.totalPendapatan)],
			['Total Pengeluaran', formatRupiah(data.ringkasan.totalPengeluaran)],
			['Saldo Bersih', formatRupiah(data.ringkasan.saldo)],
			['Jumlah Transaksi', String(data.ringkasan.jumlahTransaksi)],
			['Jumlah Penjualan', String(data.ringkasan.jumlahPenjualan)]
		],
		theme: 'grid',
		headStyles: { fillColor: [16, 185, 129] },
		styles: { fontSize: 9, cellPadding: 3 },
		columnStyles: { 1: { halign: 'right' } }
	});

	y = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY ?? y + 40;
	y += 10;

	if (data.harian.length > 0) {
		doc.setFontSize(12);
		doc.setFont('helvetica', 'bold');
		doc.text('Grafik Harian (Penjualan & Pengeluaran)', 14, y);
		y += 4;

		autoTable(doc, {
			startY: y,
			head: [['Tanggal', 'Hari', 'Penjualan', 'Pengeluaran']],
			body: data.harian.map((h) => [
				h.date,
				h.label,
				formatRupiah(h.penjualan),
				formatRupiah(h.pengeluaran)
			]),
			theme: 'striped',
			headStyles: { fillColor: [59, 130, 246] },
			styles: { fontSize: 8, cellPadding: 2 },
			columnStyles: { 2: { halign: 'right' }, 3: { halign: 'right' } }
		});

		y = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY ?? y + 30;
		y += 10;
	}

	if (data.kategoriPenjualan.length > 0) {
		if (y > 240) {
			doc.addPage();
			y = 20;
		}

		doc.setFontSize(12);
		doc.setFont('helvetica', 'bold');
		doc.text('Penjualan per Kategori', 14, y);
		y += 4;

		autoTable(doc, {
			startY: y,
			head: [['Kategori', 'Total', '%']],
			body: data.kategoriPenjualan.map((k) => [
				k.kategori,
				formatRupiah(k.total),
				`${k.persen.toFixed(1)}%`
			]),
			theme: 'striped',
			headStyles: { fillColor: [16, 185, 129] },
			styles: { fontSize: 8, cellPadding: 2 },
			columnStyles: { 1: { halign: 'right' }, 2: { halign: 'right' } }
		});

		y = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY ?? y + 20;
		y += 10;
	}

	if (data.kategoriPengeluaran.length > 0) {
		if (y > 240) {
			doc.addPage();
			y = 20;
		}

		doc.setFontSize(12);
		doc.setFont('helvetica', 'bold');
		doc.text('Pengeluaran per Kategori', 14, y);
		y += 4;

		autoTable(doc, {
			startY: y,
			head: [['Kategori', 'Total', '%']],
			body: data.kategoriPengeluaran.map((k) => [
				k.kategori,
				formatRupiah(k.total),
				`${k.persen.toFixed(1)}%`
			]),
			theme: 'striped',
			headStyles: { fillColor: [244, 63, 94] },
			styles: { fontSize: 8, cellPadding: 2 },
			columnStyles: { 1: { halign: 'right' }, 2: { halign: 'right' } }
		});

		y = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY ?? y + 20;
		y += 10;
	}

	if (data.transaksi.length > 0) {
		doc.addPage();
		y = 20;

		doc.setFontSize(12);
		doc.setFont('helvetica', 'bold');
		doc.text('Daftar Transaksi', 14, y);
		y += 4;

		autoTable(doc, {
			startY: y,
			head: [['Tgl', 'Jenis', 'Kategori', 'Deskripsi', 'Jumlah']],
			body: data.transaksi.slice(0, 40).map((t) => [
				t.tanggal,
				t.jenis === 'pendapatan' ? 'Masuk' : 'Keluar',
				t.kategori,
				t.deskripsi.length > 28 ? `${t.deskripsi.slice(0, 28)}...` : t.deskripsi,
				formatRupiah(t.jumlah)
			]),
			theme: 'grid',
			headStyles: { fillColor: [99, 102, 241] },
			styles: { fontSize: 7, cellPadding: 2 },
			columnStyles: { 4: { halign: 'right' } }
		});

		y = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY ?? y + 40;
	}

	if (data.hutangPiutang.length > 0) {
		if (y > 220) {
			doc.addPage();
			y = 20;
		} else {
			y += 10;
		}

		doc.setFontSize(12);
		doc.setFont('helvetica', 'bold');
		doc.text('Hutang & Piutang', 14, y);
		y += 4;

		autoTable(doc, {
			startY: y,
			head: [['Jenis', 'Nama', 'Sisa', 'Status']],
			body: data.hutangPiutang.map((h) => [
				h.jenis === 'hutang' ? 'Hutang' : 'Piutang',
				h.nama,
				formatRupiah(h.sisa),
				h.status === 'lunas' ? 'Lunas' : 'Belum Lunas'
			]),
			theme: 'striped',
			headStyles: { fillColor: [245, 158, 11] },
			styles: { fontSize: 8, cellPadding: 2 },
			columnStyles: { 2: { halign: 'right' } }
		});
	}

	addPdfFooters(doc, data.memberNama, 'Catatan Warung — Laporan Keuangan');
	savePdf(
		doc,
		`laporan-${sanitizeFilename(data.warungNama)}-${data.periode}-${data.tanggalAkhir}.pdf`
	);
}

export async function exportLaporanPenjualanPdf(data: LaporanPenjualanData): Promise<void> {
	const { doc, autoTable, pageWidth } = await loadPdfLibs();
	const periodeLabel = formatLaporanTanggalLabel(data.tanggalAwal, data.tanggalAkhir);
	let y = addPdfHeader(
		doc,
		pageWidth,
		'LAPORAN PENJUALAN',
		data.warungNama,
		`Periode: ${periodeLabel}`,
		[16, 185, 129]
	);

	doc.setFontSize(12);
	doc.setFont('helvetica', 'bold');
	doc.text('Ringkasan', 14, y);
	y += 4;

	autoTable(doc, {
		startY: y,
		head: [['Keterangan', 'Nilai']],
		body: [
			['Total Penjualan', formatRupiah(data.total)],
			['Jumlah Transaksi', String(data.jumlah)]
		],
		theme: 'grid',
		headStyles: { fillColor: [16, 185, 129] },
		styles: { fontSize: 9, cellPadding: 3 },
		columnStyles: { 1: { halign: 'right' } }
	});

	y = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY ?? y + 20;
	y += 10;

	doc.setFontSize(12);
	doc.setFont('helvetica', 'bold');
	doc.text('Daftar Penjualan', 14, y);
	y += 4;

	autoTable(doc, {
		startY: y,
		head: [['Tanggal', 'Kategori', 'Deskripsi', 'Produk', 'Qty', 'Jumlah']],
		body:
			data.items.length > 0
				? data.items.map((item) => [
						item.tanggal,
						item.kategori,
						item.deskripsi.length > 24 ? `${item.deskripsi.slice(0, 24)}...` : item.deskripsi,
						item.barang_nama ?? '-',
						item.qty != null ? String(item.qty) : '-',
						formatRupiah(item.jumlah)
					])
				: [['-', '-', 'Tidak ada data', '-', '-', '-']],
		theme: 'striped',
		headStyles: { fillColor: [16, 185, 129] },
		styles: { fontSize: 7, cellPadding: 2 },
		columnStyles: { 5: { halign: 'right' } }
	});

	addPdfFooters(doc, data.memberNama, 'Catatan Warung — Laporan Penjualan');
	savePdf(
		doc,
		`laporan-penjualan-${sanitizeFilename(data.warungNama)}-${data.tanggalAkhir}.pdf`
	);
}

export async function exportLaporanCatatanPdf(data: LaporanCatatanData): Promise<void> {
	const { doc, autoTable, pageWidth } = await loadPdfLibs();
	const periodeLabel = formatLaporanTanggalLabel(data.tanggalAwal, data.tanggalAkhir);
	let y = addPdfHeader(
		doc,
		pageWidth,
		'LAPORAN CATATAN HARIAN',
		data.warungNama,
		`Periode: ${periodeLabel} · Filter: ${data.jenisLabel}`,
		[59, 130, 246]
	);

	doc.setFontSize(12);
	doc.setFont('helvetica', 'bold');
	doc.text('Ringkasan', 14, y);
	y += 4;

	autoTable(doc, {
		startY: y,
		head: [['Keterangan', 'Nominal']],
		body: [
			['Total Pemasukan', formatRupiah(data.totalPendapatan)],
			['Total Pengeluaran', formatRupiah(data.totalPengeluaran)],
			['Saldo', formatRupiah(data.saldo)],
			['Jumlah Catatan', String(data.jumlah)]
		],
		theme: 'grid',
		headStyles: { fillColor: [59, 130, 246] },
		styles: { fontSize: 9, cellPadding: 3 },
		columnStyles: { 1: { halign: 'right' } }
	});

	y = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY ?? y + 24;
	y += 10;

	doc.setFontSize(12);
	doc.setFont('helvetica', 'bold');
	doc.text('Daftar Catatan', 14, y);
	y += 4;

	autoTable(doc, {
		startY: y,
		head: [['Tanggal', 'Jenis', 'Kategori', 'Deskripsi', 'Jumlah']],
		body:
			data.items.length > 0
				? data.items.map((item) => [
						item.tanggal,
						item.jenis === 'pendapatan' ? 'Pemasukan' : 'Pengeluaran',
						item.kategori,
						item.deskripsi.length > 28 ? `${item.deskripsi.slice(0, 28)}...` : item.deskripsi,
						formatRupiah(item.jumlah)
					])
				: [['-', '-', '-', 'Tidak ada data', '-']],
		theme: 'striped',
		headStyles: { fillColor: [59, 130, 246] },
		styles: { fontSize: 7, cellPadding: 2 },
		columnStyles: { 4: { halign: 'right' } }
	});

	addPdfFooters(doc, data.memberNama, 'Catatan Warung — Laporan Catatan');
	savePdf(
		doc,
		`laporan-catatan-${sanitizeFilename(data.warungNama)}-${data.tanggalAkhir}.pdf`
	);
}

export async function exportLaporanHutangPiutangPdf(data: LaporanHutangPiutangDetailData): Promise<void> {
	const { doc, autoTable, pageWidth } = await loadPdfLibs();
	const periodeLabel = formatLaporanTanggalLabel(data.tanggalAwal, data.tanggalAkhir);
	let y = addPdfHeader(
		doc,
		pageWidth,
		'LAPORAN HUTANG & PIUTANG',
		data.warungNama,
		`Periode: ${periodeLabel} · Filter: ${data.filterLabel}`,
		[245, 158, 11]
	);

	doc.setFontSize(12);
	doc.setFont('helvetica', 'bold');
	doc.text('Ringkasan', 14, y);
	y += 4;

	autoTable(doc, {
		startY: y,
		head: [['Keterangan', 'Nominal / Jumlah']],
		body: [
			['Total Hutang (sisa)', formatRupiah(data.totalHutang)],
			['Total Piutang (sisa)', formatRupiah(data.totalPiutang)],
			['Jumlah Catatan', String(data.jumlah)]
		],
		theme: 'grid',
		headStyles: { fillColor: [245, 158, 11] },
		styles: { fontSize: 9, cellPadding: 3 },
		columnStyles: { 1: { halign: 'right' } }
	});

	y = (doc as { lastAutoTable?: { finalY: number } }).lastAutoTable?.finalY ?? y + 24;
	y += 10;

	doc.setFontSize(12);
	doc.setFont('helvetica', 'bold');
	doc.text('Daftar Hutang & Piutang', 14, y);
	y += 4;

	autoTable(doc, {
		startY: y,
		head: [['Tanggal', 'Jenis', 'Nama', 'Deskripsi', 'Jumlah', 'Sisa', 'Status']],
		body:
			data.items.length > 0
				? data.items.map((item) => [
						item.tanggal,
						item.jenis === 'hutang' ? 'Hutang' : 'Piutang',
						item.nama.length > 18 ? `${item.nama.slice(0, 18)}...` : item.nama,
						item.deskripsi.length > 20 ? `${item.deskripsi.slice(0, 20)}...` : item.deskripsi || '-',
						formatRupiah(item.jumlah),
						formatRupiah(item.sisa),
						item.status === 'lunas' ? 'Lunas' : 'Belum Lunas'
					])
				: [['-', '-', '-', 'Tidak ada data', '-', '-', '-']],
		theme: 'striped',
		headStyles: { fillColor: [245, 158, 11] },
		styles: { fontSize: 7, cellPadding: 2 },
		columnStyles: { 4: { halign: 'right' }, 5: { halign: 'right' } }
	});

	addPdfFooters(doc, data.memberNama, 'Catatan Warung — Laporan Hutang & Piutang');
	savePdf(
		doc,
		`laporan-hutang-piutang-${sanitizeFilename(data.warungNama)}-${data.tanggalAkhir}.pdf`
	);
}
