import { c as createServerFn } from "./createServerFn-CIHAFgYl.mjs";
import { t as createClient } from "../_libs/supabase__supabase-js.mjs";
import { a as objectType, o as stringType, r as literalType } from "../_libs/zod.mjs";
import { t as createServerRpc } from "./createServerRpc-B90ckaqP.mjs";
//#region node_modules/.nitro/vite/services/ssr/assets/booking.functions-BBevndU6.js
function serverClient() {
	return createClient(process.env.SUPABASE_URL, process.env.SUPABASE_PUBLISHABLE_KEY, { auth: {
		storage: void 0,
		persistSession: false,
		autoRefreshToken: false
	} });
}
/** Fallback when a service has no duration entered yet. */
var DEFAULT_DURATION_MIN = 30;
var dayInput = objectType({
	providerId: stringType().uuid(),
	serviceId: stringType().uuid(),
	date: stringType().regex(/^\d{4}-\d{2}-\d{2}$/)
});
/** Offset of a time zone from UTC at a given instant, in milliseconds. */
function tzOffsetMs(at, timeZone) {
	const parts = Object.fromEntries(new Intl.DateTimeFormat("en-US", {
		timeZone,
		hour12: false,
		year: "numeric",
		month: "2-digit",
		day: "2-digit",
		hour: "2-digit",
		minute: "2-digit",
		second: "2-digit"
	}).formatToParts(at).map((p) => [p.type, p.value]));
	return Date.UTC(Number(parts.year), Number(parts.month) - 1, Number(parts.day), Number(parts.hour) % 24, Number(parts.minute), Number(parts.second)) - at.getTime();
}
/** Convert Belgrade wall-clock time to a UTC instant, independent of server TZ. */
function belgradeToUtc(y, m, d, hh, mm) {
	const guess = Date.UTC(y, m - 1, d, hh, mm);
	let off = tzOffsetMs(new Date(guess), "Europe/Belgrade");
	const corrected = guess - off;
	const off2 = tzOffsetMs(new Date(corrected), "Europe/Belgrade");
	if (off2 !== off) off = off2;
	return new Date(guess - off);
}
/**
* Returns available slot start times (ISO) for a provider on a given day.
* Slots come exclusively from admin-entered `availability` ranges for that
* date (15-min grid), minus existing appointments and blocked times.
*/
var getAvailableSlots_createServerFn_handler = createServerRpc({
	id: "aaeade12c1b9ad0ca1955de7f9d4fbb7848b4fe7f8732dfbf247220aabaa9f7c",
	name: "getAvailableSlots",
	filename: "src/lib/booking.functions.ts"
}, (opts) => getAvailableSlots.__executeServer(opts));
var getAvailableSlots = createServerFn({ method: "POST" }).inputValidator((d) => dayInput.parse(d)).handler(getAvailableSlots_createServerFn_handler, async ({ data }) => {
	const supa = serverClient();
	const { data: svc, error: svcErr } = await supa.from("services").select("duration_minutes, provider_id").eq("id", data.serviceId).maybeSingle();
	if (svcErr) throw svcErr;
	if (!svc) return {
		slots: [],
		note: "Usluga nije pronađena"
	};
	const duration = svc.duration_minutes ?? DEFAULT_DURATION_MIN;
	const [Y, M, D] = data.date.split("-").map(Number);
	const { data: avail, error: availErr } = await supa.from("availability").select("start_time, end_time").eq("provider_id", data.providerId).eq("date", data.date).order("start_time");
	if (availErr) throw availErr;
	if (!avail || avail.length === 0) return {
		slots: [],
		note: "Nema slobodnih termina za izabrani dan"
	};
	const dayStart = belgradeToUtc(Y, M, D, 0, 0);
	const dayEnd = belgradeToUtc(Y, M, D + 1, 0, 0);
	const [busyRes, blockRes] = await Promise.all([supa.rpc("get_busy_slots", {
		_provider_id: data.providerId,
		_from: dayStart.toISOString(),
		_to: dayEnd.toISOString()
	}), supa.from("blocked_times").select("start_time, end_time").eq("provider_id", data.providerId).lt("start_time", dayEnd.toISOString()).gt("end_time", dayStart.toISOString())]);
	const busy = [];
	for (const b of busyRes.data ?? []) busy.push({
		s: new Date(b.start_time).getTime(),
		e: new Date(b.end_time).getTime()
	});
	for (const b of blockRes.data ?? []) busy.push({
		s: new Date(b.start_time).getTime(),
		e: new Date(b.end_time).getTime()
	});
	const slots = /* @__PURE__ */ new Set();
	const step = 15;
	const now = Date.now();
	for (const range of avail) {
		const [sh, sm] = range.start_time.split(":").map(Number);
		const [eh, em] = range.end_time.split(":").map(Number);
		const rangeStart = belgradeToUtc(Y, M, D, sh, sm).getTime();
		const rangeEnd = belgradeToUtc(Y, M, D, eh, em).getTime();
		for (let t = rangeStart; t + duration * 6e4 <= rangeEnd; t += step * 6e4) {
			const slotEnd = t + duration * 6e4;
			if (t < now + 60 * 6e4) continue;
			if (!busy.some((b) => t < b.e && slotEnd > b.s)) slots.add(new Date(t).toISOString());
		}
	}
	return {
		slots: [...slots].sort(),
		note: null
	};
});
var createInput = objectType({
	providerId: stringType().uuid(),
	serviceId: stringType().uuid(),
	startTime: stringType(),
	clientName: stringType().trim().min(2).max(100),
	clientPhone: stringType().trim().min(5).max(30),
	note: stringType().trim().max(500).optional().nullable(),
	consent: literalType(true)
});
var createAppointment_createServerFn_handler = createServerRpc({
	id: "37d6f876d7bed51f21dabcff93ddcc677c0366eb401205a19670a6588607880b",
	name: "createAppointment",
	filename: "src/lib/booking.functions.ts"
}, (opts) => createAppointment.__executeServer(opts));
var createAppointment = createServerFn({ method: "POST" }).inputValidator((d) => createInput.parse(d)).handler(createAppointment_createServerFn_handler, async ({ data }) => {
	const supa = serverClient();
	const { data: svc, error: svcErr } = await supa.from("services").select("id, name, duration_minutes, provider_id").eq("id", data.serviceId).maybeSingle();
	if (svcErr) throw svcErr;
	if (!svc) throw new Error("Usluga nije pronađena");
	if (svc.provider_id !== data.providerId) throw new Error("Nedozvoljen provajder za ovu uslugu");
	const duration = svc.duration_minutes ?? DEFAULT_DURATION_MIN;
	const startAt = new Date(data.startTime);
	if (isNaN(startAt.getTime()) || startAt.getTime() < Date.now()) throw new Error("Datum termina nije važeći");
	const endAt = new Date(startAt.getTime() + duration * 6e4);
	const apptId = crypto.randomUUID();
	const { error } = await supa.from("appointments").insert({
		id: apptId,
		provider_id: data.providerId,
		service_id: svc.id,
		client_name: data.clientName,
		client_phone: data.clientPhone,
		note: data.note ?? null,
		start_time: startAt.toISOString(),
		end_time: endAt.toISOString(),
		status: "scheduled"
	});
	if (error) {
		if (error.message?.includes("no_overlap")) throw new Error("Ovaj termin je već zauzet. Molimo izaberite drugi.");
		throw error;
	}
	try {
		const { supabaseAdmin } = await import("./client.server-Bw6iWMJ-.mjs");
		const { buildConfirmationSms, buildReminderSms, queueSms } = await import("./sms.server-LAZmyyGn.mjs");
		const date = startAt.toLocaleDateString("sr-RS");
		const time = startAt.toLocaleTimeString("sr-RS", {
			hour: "2-digit",
			minute: "2-digit"
		});
		await queueSms(supabaseAdmin, {
			appointmentId: apptId,
			type: "confirmation",
			recipient: data.clientPhone,
			body: buildConfirmationSms({
				service: svc.name,
				date,
				time
			})
		});
		const reminderAt = /* @__PURE__ */ new Date(startAt.getTime() - 10800 * 1e3);
		if (reminderAt.getTime() > Date.now()) await queueSms(supabaseAdmin, {
			appointmentId: apptId,
			type: "reminder",
			recipient: data.clientPhone,
			body: buildReminderSms({
				service: svc.name,
				time
			}),
			sendAfter: reminderAt.toISOString()
		});
	} catch (smsErr) {
		console.warn("[booking] SMS queue skipped:", smsErr.message);
	}
	return {
		id: apptId,
		startTime: startAt.toISOString(),
		endTime: endAt.toISOString()
	};
});
//#endregion
export { createAppointment_createServerFn_handler, getAvailableSlots_createServerFn_handler };
