import { serve } from "https://deno.land/std@0.190.0/http/server.ts"; import { createClient } from "https://esm.sh/@supabase/supabase-js@2.39.3"; const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type, x-supabase-client-platform, x-supabase-client-platform-version, x-supabase-client-runtime, x-supabase-client-runtime-version", }; serve(async (req) => { if (req.method === "OPTIONS") { return new Response(null, { headers: corsHeaders }); } try { const supabaseUrl = Deno.env.get("SUPABASE_URL")!; const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!; const supabase = createClient(supabaseUrl, supabaseServiceKey); const { booking_id, session_id } = await req.json(); if (!booking_id) { return new Response( JSON.stringify({ error: "Missing booking_id" }), { status: 400, headers: { ...corsHeaders, "Content-Type": "application/json" } } ); } // Fetch booking const { data: booking, error: bookingErr } = await supabase .from("amenity_bookings") .select("*") .eq("id", booking_id) .single(); if (bookingErr || !booking) { return new Response( JSON.stringify({ error: "Booking not found" }), { status: 404, headers: { ...corsHeaders, "Content-Type": "application/json" } } ); } // Only process if still pending_payment if (booking.status !== "pending_payment") { return new Response( JSON.stringify({ success: true, message: "Already processed" }), { headers: { ...corsHeaders, "Content-Type": "application/json" } } ); } // Update booking status to confirmed await supabase .from("amenity_bookings") .update({ status: "confirmed" }) .eq("id", booking_id); // Extract pin_id from notes let pinId: string | null = null; try { const notes = typeof booking.notes === "string" ? JSON.parse(booking.notes) : booking.notes; pinId = notes?.pin_id || null; } catch { /* ignore */ } // Mark pin as rented if (pinId && booking.amenity_id) { const { data: amenity } = await supabase .from("amenities") .select("map_config") .eq("id", booking.amenity_id) .single(); if (amenity?.map_config?.pins) { const updatedPins = amenity.map_config.pins.map((pin: any) => pin.id === pinId ? { ...pin, status: "rented" } : pin ); await supabase .from("amenities") .update({ map_config: { ...amenity.map_config, pins: updatedPins }, updated_at: new Date().toISOString(), }) .eq("id", booking.amenity_id); } } // Send confirmation email if (booking.guest_email) { try { const { data: amenityRow } = await supabase .from("amenities").select("name, association_id").eq("id", booking.amenity_id).single(); const { data: assocRow } = amenityRow?.association_id ? await supabase.from("associations").select("name").eq("id", amenityRow.association_id).single() : { data: null }; const { data: pageRow } = amenityRow?.association_id ? await supabase.from("association_public_pages").select("slug").eq("association_id", amenityRow.association_id).maybeSingle() : { data: null }; const origin = req.headers.get("origin") || "https://avria.cloud"; const dateObj = booking.booking_date ? new Date(`${booking.booking_date}T12:00:00`) : null; const formattedDate = dateObj ? dateObj.toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" }) : ""; await supabase.functions.invoke("send-transactional-email", { body: { templateName: "amenity-booking-confirmation", recipientEmail: booking.guest_email, idempotencyKey: `amenity-booking-confirmed-${booking.id}`, templateData: { guestName: booking.guest_name, amenityName: amenityRow?.name, associationName: (assocRow as any)?.name, bookingDate: formattedDate, startTime: booking.start_time || "", status: "confirmed", confirmationLink: `${origin}/booking/${booking.id}`, }, }, }); } catch (err) { console.error("Failed to send confirmation email:", err); } } return new Response( JSON.stringify({ success: true }), { headers: { ...corsHeaders, "Content-Type": "application/json" } } ); } catch (err) { console.error("Error in confirm-reservation-payment:", err); return new Response( JSON.stringify({ error: err.message || "Internal server error" }), { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } } ); } });