import { fail, redirect } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import { KATEGORI_PENJUALAN } from '$lib/constants/kategori';
import { canCreateTransaksi } from '$lib/server/langganan';
import { getBarangForPenjualan } from '$lib/server/stok';
import { createPenjualan, createPenjualanStok } from '$lib/server/transaksi';
import { pakaiStokInventori } from '$lib/server/warung';
import { getTodayDateString, isValidDateString, parseRupiahInput } from '$lib/utils/parse';

export const load: PageServerLoad = async ({ parent }) => {
	const { pakaiStok, member } = await parent();

	return {
		kategori: KATEGORI_PENJUALAN,
		tanggalDefault: getTodayDateString(),
		pakaiStok,
		barangList: pakaiStok ? await getBarangForPenjualan(member.id) : []
	};
};

function formValues(formData: FormData) {
	return Object.fromEntries(
		[...formData.entries()].map(([key, value]) => [key, typeof value === 'string' ? value : String(value)])
	);
}

export const actions: Actions = {
	default: async ({ request, locals }) => {
		if (!locals.member) {
			return fail(401, { error: 'Sesi login tidak valid. Silakan masuk kembali.' });
		}

		const pakaiStok = await pakaiStokInventori(locals.member.id);
		const formData = await request.formData();

		if (!(await canCreateTransaksi(locals.member.id))) {
			return fail(403, {
				error: 'Batas transaksi bulan ini sudah tercapai. Upgrade paket untuk melanjutkan.',
				values: formValues(formData)
			});
		}
		const tanggal = String(formData.get('tanggal') ?? '').trim();
		const jenisPenjualan = String(formData.get('jenis_penjualan') ?? 'manual');
		const today = getTodayDateString();

		if (!isValidDateString(tanggal)) {
			return fail(400, { error: 'Tanggal tidak valid.', values: formValues(formData) });
		}

		if (tanggal > today) {
			return fail(400, { error: 'Tanggal tidak boleh di masa depan.', values: formValues(formData) });
		}

		const useStok = pakaiStok && jenisPenjualan === 'stok';

		if (useStok) {
			const barangId = Number(formData.get('barang_id'));
			const qty = Number(formData.get('qty'));
			const jumlahRaw = String(formData.get('jumlah') ?? '');

			const values = {
				jenis_penjualan: 'stok',
				barang_id: String(barangId),
				qty: String(qty),
				jumlah: jumlahRaw,
				tanggal
			};

			if (!barangId) {
				return fail(400, { error: 'Pilih produk dari stok.', values });
			}

			if (!Number.isInteger(qty) || qty <= 0) {
				return fail(400, { error: 'Jumlah produk harus lebih dari 0.', values });
			}

			const jumlah = parseRupiahInput(jumlahRaw);
			if (jumlah <= 0) {
				return fail(400, { error: 'Total penjualan harus lebih dari Rp 0.', values });
			}

			try {
				await createPenjualanStok({
					memberId: locals.member.id,
					barangId,
					qty,
					jumlah,
					tanggal
				});
			} catch (error) {
				if (error instanceof Error && error.message === 'STOK_TIDAK_CUKUP') {
					return fail(400, { error: 'Stok produk tidak cukup.', values });
				}
				return fail(500, {
					error: 'Gagal menyimpan penjualan. Pastikan MySQL berjalan.',
					values
				});
			}

			throw redirect(303, '/transaksi/penjualan?success=1');
		}

		const kategori = String(formData.get('kategori') ?? '').trim();
		const deskripsi = String(formData.get('deskripsi') ?? '').trim();
		const jumlahRaw = String(formData.get('jumlah') ?? '');
		const jumlah = parseRupiahInput(jumlahRaw);
		const validKategori = KATEGORI_PENJUALAN.some((k) => k.value === kategori);
		const values = { jenis_penjualan: 'manual', kategori, deskripsi, jumlah: jumlahRaw, tanggal };

		if (!validKategori) {
			return fail(400, { error: 'Pilih kategori yang valid.', values });
		}

		if (!deskripsi) {
			return fail(400, { error: 'Deskripsi penjualan wajib diisi.', values });
		}

		if (deskripsi.length > 255) {
			return fail(400, { error: 'Deskripsi maksimal 255 karakter.', values });
		}

		if (jumlah <= 0) {
			return fail(400, { error: 'Jumlah penjualan harus lebih dari Rp 0.', values });
		}

		try {
			await createPenjualan({
				memberId: locals.member.id,
				kategori,
				deskripsi,
				jumlah,
				tanggal
			});
		} catch {
			return fail(500, {
				error: 'Gagal menyimpan ke database. Pastikan MySQL berjalan dan jalankan npm run db:init.',
				values
			});
		}

		throw redirect(303, '/transaksi/penjualan?success=1');
	}
};
