import { fail, redirect } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import {
	createSessionToken,
	getSessionCookieOptions,
	SESSION_COOKIE
} from '$lib/server/auth';
import {
	getMemberProfile,
	updateMemberPassword,
	updateMemberProfile,
	updateMemberAvatar
} from '$lib/server/member';
import { saveMemberAvatar } from '$lib/server/avatar';
import {
	getHariBukaList,
	getKategoriWarungList,
	getKodeposById,
	hasKodeposData,
	resolveHariBukaKode,
	resolveWilayahSelection,
	validateAndResolveWilayah,
	validateHariBuka,
	validateKategoriWarung
} from '$lib/server/referensi';
import { getMemberEntitlements, hasPrivilege } from '$lib/server/langganan';
import { getWarungByMemberId, upsertWarung, warungToFormInput } from '$lib/server/warung';
import type { KategoriWarung, ModeInventori } from '$lib/types/warung';

export const load: PageServerLoad = async ({ locals, url, parent }) => {
	if (!locals.member) {
		throw redirect(303, '/login');
	}

	const profil = await getMemberProfile(locals.member.id);
	if (!profil) {
		throw redirect(303, '/login');
	}

	const warung = await getWarungByMemberId(locals.member.id);
	const kodeposReady = await hasKodeposData();

	const [kategoriList, hariBukaList] = await Promise.all([
		getKategoriWarungList(),
		getHariBukaList()
	]);

	const warungForm = warungToFormInput(warung);
	const { entitlements, langganan } = await parent();

	if (warung && kodeposReady) {
		const selection = await resolveWilayahSelection(
			warung.provinsi,
			warung.kota,
			warung.kecamatan,
			warung.kelurahan,
			warung.kode_pos
		);

		warungForm.provinsi = selection.provinsi;
		warungForm.kota = selection.kota;
		warungForm.kecamatan = selection.kecamatan;
		warungForm.kodepos_id = selection.kodepos_id;
		warungForm.hari_buka_kode = await resolveHariBukaKode(warung.hari_buka);

		if (selection.kodepos_id) {
			const resolved = await getKodeposById(Number(selection.kodepos_id));
			if (resolved) {
				warungForm.kelurahan = resolved.kelurahan;
				warungForm.kode_pos = resolved.kode_pos;
			}
		}
	}

	return {
		member: locals.member,
		profil,
		warung,
		warungForm,
		referensi: {
			kategori: kategoriList,
			hariBuka: hariBukaList,
			kodeposReady
		},
		langganan,
		entitlements,
		canInventoriStok: entitlements ? hasPrivilege(entitlements, 'inventori_stok') : false,
		canWarungPublik: entitlements ? hasPrivilege(entitlements, 'warung_publik') : false,
		profilUpdated: url.searchParams.get('profil') === '1',
		warungUpdated: url.searchParams.get('warung') === '1',
		passwordUpdated: url.searchParams.get('password') === '1'
	};
};

export const actions: Actions = {
	updateProfil: async ({ request, locals, cookies }) => {
		const formData = await request.formData();
		const nama = String(formData.get('nama') ?? '').trim();
		const email = String(formData.get('email') ?? '').trim().toLowerCase();
		const values = { nama, email };
		const avatarInput = formData.get('avatar');

		if (!nama || !email) {
			return fail(400, { profilError: 'Nama dan email wajib diisi.', values });
		}

		if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
			return fail(400, { profilError: 'Format email tidak valid.', values });
		}

		try {
			const updated = await updateMemberProfile({ id: locals.member!.id, nama, email });
			if (!updated) {
				return fail(409, { profilError: 'Email sudah digunakan member lain.', values });
			}

			if (avatarInput instanceof File && avatarInput.size > 0) {
				try {
					const avatarUrl = await saveMemberAvatar(locals.member!.id, avatarInput);
					await updateMemberAvatar(locals.member!.id, avatarUrl);
				} catch (err) {
					const code = err instanceof Error ? err.message : '';
					if (code === 'FILE_TOO_LARGE') {
						return fail(400, {
							profilError: 'Ukuran gambar avatar maksimal 1 MB.',
							values
						});
					}
					if (code === 'INVALID_TYPE') {
						return fail(400, {
							profilError: 'Format gambar harus JPG, PNG, WEBP, atau GIF.',
							values
						});
					}
					return fail(400, { profilError: 'Gagal mengunggah gambar avatar.', values });
				}
			}
		} catch {
			return fail(500, { profilError: 'Gagal menyimpan profil ke database.' });
		}

		const token = createSessionToken({ id: locals.member!.id, nama, email });
		cookies.set(SESSION_COOKIE, token, getSessionCookieOptions());

		throw redirect(303, '/profil?profil=1');
	},

	updateWarung: async ({ request, locals }) => {
		const formData = await request.formData();
		const kategoriInput = String(formData.get('kategori') ?? '');
		const hariBukaKode = String(formData.get('hari_buka_kode') ?? '');
		const latitude = String(formData.get('latitude') ?? '').trim();
		const longitude = String(formData.get('longitude') ?? '').trim();

		const warungValues = {
			nama: String(formData.get('nama') ?? '').trim(),
			deskripsi: String(formData.get('deskripsi') ?? '').trim(),
			kategori: kategoriInput as KategoriWarung,
			alamat: String(formData.get('alamat') ?? '').trim(),
			kelurahan: '',
			kecamatan: String(formData.get('kecamatan') ?? '').trim(),
			kota: String(formData.get('kota') ?? '').trim(),
			provinsi: String(formData.get('provinsi') ?? '').trim(),
			kode_pos: '',
			telepon: String(formData.get('telepon') ?? '').trim(),
			whatsapp: String(formData.get('whatsapp') ?? '').trim(),
			latitude,
			longitude,
			jam_buka: String(formData.get('jam_buka') ?? '08:00'),
			jam_tutup: String(formData.get('jam_tutup') ?? '21:00'),
			hari_buka: '',
			hari_buka_kode: hariBukaKode,
			kodepos_id: String(formData.get('kodepos_id') ?? ''),
			foto_url: String(formData.get('foto_url') ?? '').trim(),
			is_aktif: formData.has('is_aktif'),
			is_publik: formData.has('is_publik'),
			mode_inventori: (String(formData.get('mode_inventori') ?? 'tanpa_stok') as ModeInventori)
		};

		if (warungValues.mode_inventori !== 'tanpa_stok' && warungValues.mode_inventori !== 'dengan_stok') {
			warungValues.mode_inventori = 'tanpa_stok';
		}

		const entitlements = await getMemberEntitlements(locals.member!.id);
		if (warungValues.mode_inventori === 'dengan_stok' && !hasPrivilege(entitlements, 'inventori_stok')) {
			warungValues.mode_inventori = 'tanpa_stok';
		}
		if (warungValues.is_publik && !hasPrivilege(entitlements, 'warung_publik')) {
			warungValues.is_publik = false;
		}

		if (!warungValues.nama) {
			return fail(400, { warungError: 'Nama warung wajib diisi.', warungValues });
		}

		if (!warungValues.alamat) {
			return fail(400, { warungError: 'Alamat jalan wajib diisi.', warungValues });
		}

		if (!(await hasKodeposData())) {
			return fail(503, {
				warungError: 'Data kodepos belum diimpor. Jalankan: npm run db:kodepos',
				warungValues
			});
		}

		const kategori = await validateKategoriWarung(kategoriInput);
		if (!kategori) {
			return fail(400, { warungError: 'Kategori tidak valid.', warungValues });
		}

		const hariBukaLabel = await validateHariBuka(hariBukaKode);
		if (!hariBukaLabel) {
			return fail(400, { warungError: 'Hari buka tidak valid.', warungValues });
		}

		const wilayahResult = await validateAndResolveWilayah({
			provinsi: warungValues.provinsi,
			kota: warungValues.kota,
			kecamatan: warungValues.kecamatan,
			kodepos_id: warungValues.kodepos_id
		});

		if (!wilayahResult.ok) {
			return fail(400, { warungError: wilayahResult.message, warungValues });
		}

		warungValues.kategori = kategori;
		warungValues.hari_buka = hariBukaLabel;
		warungValues.provinsi = wilayahResult.data.provinsi;
		warungValues.kota = wilayahResult.data.kota;
		warungValues.kecamatan = wilayahResult.data.kecamatan;
		warungValues.kelurahan = wilayahResult.data.kelurahan;
		warungValues.kode_pos = wilayahResult.data.kode_pos;

		const lat = Number(latitude);
		const lng = Number(longitude);

		if (Number.isNaN(lat) || lat < -90 || lat > 90) {
			return fail(400, { warungError: 'Latitude tidak valid (-90 s/d 90).', warungValues });
		}

		if (Number.isNaN(lng) || lng < -180 || lng > 180) {
			return fail(400, { warungError: 'Longitude tidak valid (-180 s/d 180).', warungValues });
		}

		try {
			await upsertWarung(locals.member!.id, warungValues);
		} catch {
			return fail(500, {
				warungError: 'Gagal menyimpan data warung ke database.',
				warungValues
			});
		}

		throw redirect(303, '/profil?warung=1');
	},

	updatePassword: async ({ request, locals }) => {
		const formData = await request.formData();
		const password_lama = String(formData.get('password_lama') ?? '');
		const password_baru = String(formData.get('password_baru') ?? '');
		const konfirmasi = String(formData.get('konfirmasi') ?? '');

		if (!password_lama || !password_baru || !konfirmasi) {
			return fail(400, { passwordError: 'Semua field password wajib diisi.' });
		}

		if (password_baru.length < 6) {
			return fail(400, { passwordError: 'Password baru minimal 6 karakter.' });
		}

		if (password_baru !== konfirmasi) {
			return fail(400, { passwordError: 'Konfirmasi password tidak cocok.' });
		}

		try {
			const result = await updateMemberPassword(locals.member!.id, password_lama, password_baru);

			if (result === 'wrong_password') {
				return fail(401, { passwordError: 'Password lama tidak sesuai.' });
			}

			if (result === 'failed') {
				return fail(500, { passwordError: 'Gagal mengubah password.' });
			}
		} catch {
			return fail(500, { passwordError: 'Gagal menyimpan password ke database.' });
		}

		throw redirect(303, '/profil?password=1');
	}
};
